diff --git a/.classpath b/.classpath index 45fe10e05..84016272a 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + @@ -14,15 +15,9 @@ - - - - - - @@ -46,8 +41,6 @@ - - @@ -67,7 +60,6 @@ - @@ -88,14 +80,44 @@ - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope index c237e4f6b..000a6e8e0 100644 --- a/.settings/.jsdtscope +++ b/.settings/.jsdtscope @@ -1,6 +1,6 @@ - + diff --git a/.settings/org.eclipse.wst.jsdt.core.prefs b/.settings/org.eclipse.wst.jsdt.core.prefs index 7b594a52b..291cdc4c8 100644 --- a/.settings/org.eclipse.wst.jsdt.core.prefs +++ b/.settings/org.eclipse.wst.jsdt.core.prefs @@ -57,6 +57,7 @@ org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentRefer org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.wst.jsdt.core.compiler.source=1.3 +org.eclipse.wst.jsdt.core.compiler.source.type=script org.eclipse.wst.jsdt.core.compiler.taskCaseSensitive=enabled org.eclipse.wst.jsdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL org.eclipse.wst.jsdt.core.compiler.taskTags=TODO,FIXME,XXX @@ -318,4 +319,5 @@ org.eclipse.wst.jsdt.core.formatter.tabulation.char=space org.eclipse.wst.jsdt.core.formatter.tabulation.size=4 org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true -semanticValidation=enabled +semanticValidation=disabled +strictOnKeywordUsage=disabled diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 000000000..b09608453 --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,8 @@ +DELEGATES_PREFERENCE=delegateValidatorList +USER_BUILD_PREFERENCE=enabledBuildValidatorList +USER_MANUAL_PREFERENCE=enabledManualValidatorList +USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationtrueversion1.2.700.v201508251749 +eclipse.preferences.version=1 +override=true +suspend=true +vf.version=3 diff --git a/broker/appengine/.classpath b/broker/appengine/.classpath deleted file mode 100644 index 4f8426eef..000000000 --- a/broker/appengine/.classpath +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/broker/appengine/.project b/broker/appengine/.project deleted file mode 100644 index 7b4860b54..000000000 --- a/broker/appengine/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - grefine-appengine-broker - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/com.google.gdt.eclipse.core.webAppProjectValidator.launch - - - - - com.google.appengine.eclipse.core.enhancerbuilder - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/com.google.appengine.eclipse.core.projectValidator.launch - - - - - - org.eclipse.jdt.core.javanature - com.google.appengine.eclipse.core.gaeNature - - diff --git a/broker/core/.classpath b/broker/core/.classpath deleted file mode 100644 index ef2854438..000000000 --- a/broker/core/.classpath +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/broker/core/.project b/broker/core/.project deleted file mode 100644 index 4538782c6..000000000 --- a/broker/core/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - grefine-broker - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/build.xml b/build.xml index 4ad005eba..1135d638b 100644 --- a/build.xml +++ b/build.xml @@ -140,6 +140,10 @@ + + + + diff --git a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java index 51cc2175e..f5650acf6 100644 --- a/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java +++ b/extensions/database/src/com/google/refine/extension/database/DatabaseImportController.java @@ -46,7 +46,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.extension.database.model.DatabaseColumn; @@ -56,6 +55,7 @@ import com.google.refine.importing.ImportingController; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/extensions/database/test/com/google/refine/extension/database/DatabaseImportControllerTest.java b/extensions/database/test/com/google/refine/extension/database/DatabaseImportControllerTest.java index b1ee56bfa..df75a81db 100644 --- a/extensions/database/test/com/google/refine/extension/database/DatabaseImportControllerTest.java +++ b/extensions/database/test/com/google/refine/extension/database/DatabaseImportControllerTest.java @@ -25,7 +25,7 @@ import org.testng.annotations.Parameters; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.stub.RefineDbServletStub; diff --git a/extensions/database/test/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java b/extensions/database/test/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java index 12ee019f3..0dc52016c 100644 --- a/extensions/database/test/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java +++ b/extensions/database/test/com/google/refine/extension/database/cmd/SavedConnectionCommandTest.java @@ -25,7 +25,7 @@ import org.testng.annotations.Parameters; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.extension.database.DBExtensionTestUtils; import com.google.refine.extension.database.DBExtensionTests; diff --git a/extensions/gdata/.classpath b/extensions/gdata/.classpath deleted file mode 100644 index f6d5efd90..000000000 --- a/extensions/gdata/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extensions/gdata/.project b/extensions/gdata/.project deleted file mode 100644 index c6f5e416a..000000000 --- a/extensions/gdata/.project +++ /dev/null @@ -1,31 +0,0 @@ - - - grefine-gdata-extension - - - gridworks - gridworks-server - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/extensions/gdata/.settings/.jsdtscope b/extensions/gdata/.settings/.jsdtscope deleted file mode 100644 index b13d30357..000000000 --- a/extensions/gdata/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/extensions/gdata/module/MOD-INF/.gitignore b/extensions/gdata/module/MOD-INF/.gitignore deleted file mode 100644 index 840e7d312..000000000 --- a/extensions/gdata/module/MOD-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/classes/ diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java index 8e4dbfbb7..c02b3253f 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/FusionTableImporter.java @@ -39,11 +39,11 @@ import com.google.api.services.fusiontables.model.Column; import com.google.api.services.fusiontables.model.Sqlresponse; import com.google.api.services.fusiontables.model.Table; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; /** diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java index edbb4a8e1..a4d58c2a6 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java @@ -45,11 +45,11 @@ import com.google.gdata.data.spreadsheet.SpreadsheetEntry; import com.google.gdata.data.spreadsheet.WorksheetEntry; import com.google.gdata.util.ServiceException; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; /** diff --git a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java index fb654c83c..3e9e47da1 100644 --- a/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java +++ b/extensions/gdata/src/com/google/refine/extension/gdata/GDataImportingController.java @@ -65,7 +65,6 @@ import com.google.gdata.util.AuthenticationException; import com.google.gdata.util.ServiceException; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.commands.HttpUtilities; import com.google.refine.importing.DefaultImportingController; @@ -73,6 +72,7 @@ import com.google.refine.importing.ImportingController; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; diff --git a/extensions/jython/.classpath b/extensions/jython/.classpath deleted file mode 100644 index fc48762f5..000000000 --- a/extensions/jython/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/extensions/jython/.project b/extensions/jython/.project deleted file mode 100644 index 8d1297098..000000000 --- a/extensions/jython/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - grefine-jython - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/extensions/pc-axis/.classpath b/extensions/pc-axis/.classpath deleted file mode 100644 index f68b34a90..000000000 --- a/extensions/pc-axis/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/extensions/pc-axis/.project b/extensions/pc-axis/.project deleted file mode 100644 index eef3b87d9..000000000 --- a/extensions/pc-axis/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - refine-pd-extension - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/extensions/pc-axis/module/MOD-INF/.gitignore b/extensions/pc-axis/module/MOD-INF/.gitignore deleted file mode 100644 index 840e7d312..000000000 --- a/extensions/pc-axis/module/MOD-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/classes/ diff --git a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java index 64e78a67d..ea137ec7e 100644 --- a/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java +++ b/extensions/pc-axis/src/com/google/refine/pcaxis/PCAxisImporter.java @@ -41,10 +41,10 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class PCAxisImporter extends TabularImportingParserBase { diff --git a/extensions/sample/.classpath b/extensions/sample/.classpath deleted file mode 100644 index 03c606eeb..000000000 --- a/extensions/sample/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/extensions/sample/.project b/extensions/sample/.project deleted file mode 100644 index 8fd50839d..000000000 --- a/extensions/sample/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - grefine-sample-extension - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/extensions/sample/.settings/.jsdtscope b/extensions/sample/.settings/.jsdtscope deleted file mode 100644 index b13d30357..000000000 --- a/extensions/sample/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/extensions/sample/module/MOD-INF/.gitignore b/extensions/sample/module/MOD-INF/.gitignore deleted file mode 100644 index 840e7d312..000000000 --- a/extensions/sample/module/MOD-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/classes/ diff --git a/main/.classpath b/main/.classpath deleted file mode 100644 index d3035ccc5..000000000 --- a/main/.classpath +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/main/.gitignore b/main/.gitignore deleted file mode 100644 index 8c0a17c3f..000000000 --- a/main/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/test-output diff --git a/main/.project b/main/.project deleted file mode 100644 index 2f5ebba12..000000000 --- a/main/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - grefine - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/main/.settings/.jsdtscope b/main/.settings/.jsdtscope deleted file mode 100644 index b13d30357..000000000 --- a/main/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/main/resources/schemas/TableSchemaValidator.json b/main/resources/schemas/TableSchemaValidator.json new file mode 100644 index 000000000..8f7111fb7 --- /dev/null +++ b/main/resources/schemas/TableSchemaValidator.json @@ -0,0 +1,213 @@ +{ + "version": "1.0.0", + "errors": { + + + "io-error": { + "name": "IO Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source returned an IO Error of type {error_type}", + "description": "Data reading error because of IO error.\n\n How it could be resolved:\n - Fix path if it's not correct." + }, + "http-error": { + "name": "HTTP Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source returned an HTTP error with a status code of {status_code}", + "description": "Data reading error because of HTTP error.\n\n How it could be resolved:\n - Fix url link if it's not correct." + }, + "source-error": { + "name": "Source Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source has not supported or has inconsistent contents; no tabular data can be extracted", + "description": "Data reading error because of not supported or inconsistent contents.\n\n How it could be resolved:\n - Fix data contents (e.g. change JSON data to array or arrays/objects).\n - Set correct source settings in {validator}." + }, + "scheme-error": { + "name": "Scheme Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source is in an unknown scheme; no tabular data can be extracted", + "description": "Data reading error because of incorrect scheme.\n\n How it could be resolved:\n - Fix data scheme (e.g. change scheme from `ftp` to `http`).\n - Set correct scheme in {validator}." + }, + "format-error": { + "name": "Format Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source is in an unknown format; no tabular data can be extracted", + "description": "Data reading error because of incorrect format.\n\n How it could be resolved:\n - Fix data format (e.g. change file extension from `txt` to `csv`).\n - Set correct format in {validator}." + }, + "encoding-error": { + "name": "Encoding Error", + "type": "source", + "context": "table", + "weight": 100, + "message": "The data source could not be successfully decoded with {encoding} encoding", + "description": "Data reading error because of an encoding problem.\n\n How it could be resolved:\n - Fix data source if it's broken.\n - Set correct encoding in {validator}." + }, + + + "blank-header": { + "name": "Blank Header", + "type": "structure", + "context": "head", + "weight": 3, + "message": "Header in column {column_number} is blank", + "description": "A column in the header row is missing a value. Column names should be provided.\n\n How it could be resolved:\n - Add the missing column name to the first row of the data source.\n - If the first row starts with, or ends with a comma, remove it.\n - If this error should be ignored disable `blank-header` check in {validator}." + }, + "duplicate-header": { + "name": "Duplicate Header", + "type": "structure", + "context": "head", + "weight": 3, + "message": "Header in column {column_number} is duplicated to header in column(s) {column_numbers}", + "description": "Two columns in the header row have the same value. Column names should be unique.\n\n How it could be resolved:\n - Add the missing column name to the first row of the data.\n - If the first row starts with, or ends with a comma, remove it.\n - If this error should be ignored disable `duplicate-header` check in {validator}." + }, + "blank-row": { + "name": "Blank Row", + "type": "structure", + "context": "body", + "weight": 9, + "message": "Row {row_number} is completely blank", + "description": "This row is empty. A row should contain at least one value.\n\n How it could be resolved:\n - Delete the row.\n - If this error should be ignored disable `blank-row` check in {validator}." + }, + "duplicate-row": { + "name": "Duplicate Row", + "type": "structure", + "context": "body", + "weight": 5, + "message": "Row {row_number} is duplicated to row(s) {row_numbers}", + "description": "The exact same data has been seen in another row.\n\n How it could be resolved:\n - If some of the data is incorrect, correct it.\n - If the whole row is an incorrect duplicate, remove it.\n - If this error should be ignored disable `duplicate-row` check in {validator}." + }, + "extra-value": { + "name": "Extra Value", + "type": "structure", + "context": "body", + "weight": 9, + "message": "Row {row_number} has an extra value in column {column_number}", + "description": "This row has more values compared to the header row (the first row in the data source). A key concept is that all the rows in tabular data must have the same number of columns.\n\n How it could be resolved:\n - Check data has an extra comma between the values in this row.\n - If this error should be ignored disable `extra-value` check in {validator}." + }, + "missing-value": { + "name": "Missing Value", + "type": "structure", + "context": "body", + "weight": 9, + "message": "Row {row_number} has a missing value in column {column_number}", + "description": "This row has less values compared to the header row (the first row in the data source). A key concept is that all the rows in tabular data must have the same number of columns.\n\n How it could be resolved:\n - Check data is not missing a comma between the values in this row.\n - If this error should be ignored disable `missing-value` check in {validator}." + }, + + + "schema-error": { + "name": "Table Schema Error", + "type": "schema", + "context": "table", + "weight": 15, + "message": "Table Schema error: {error_message}", + "description": "Provided schema is not valid.\n\n How it could be resolved:\n - Update schema descriptor to be a valid descriptor\n - If this error should be ignored disable schema checks in {validator}." + }, + "non-matching-header": { + "name": "Non-Matching Header", + "type": "schema", + "context": "head", + "weight": 9, + "message": "Header in column {column_number} doesn't match field name {field_name} in the schema", + "description": "One of the data source headers doesn't match the field name defined in the schema.\n\n How it could be resolved:\n - Rename header in the data source or field in the schema\n - If this error should be ignored disable `non-matching-header` check in {validator}." + }, + "extra-header": { + "name": "Extra Header", + "type": "schema", + "context": "head", + "weight": 9, + "message": "There is an extra header in column {column_number}", + "description": "The first row of the data source contains header that doesn't exist in the schema.\n\n How it could be resolved:\n - Remove the extra column from the data source or add the missing field to the schema\n - If this error should be ignored disable `extra-header` check in {validator}." + }, + "missing-header": { + "name": "Missing Header", + "type": "schema", + "context": "head", + "weight": 9, + "message": "There is a missing header in column {column_number}", + "description": "Based on the schema there should be a header that is missing in the first row of the data source.\n\n How it could be resolved:\n - Add the missing column to the data source or remove the extra field from the schema\n - If this error should be ignored disable `missing-header` check in {validator}." + }, + "type-or-format-error": { + "name": "Type or Format Error", + "type": "schema", + "context": "body", + "weight": 9, + "message": "The value {value} in row {row_number} and column {column_number} is not type {field_type} and format {field_format}", + "description": "The value does not match the schema type and format for this field.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If this value is correct, adjust the type and/or format.\n - To ignore the error, disable the `type-or-format-error` check in {validator}. In this case all schema checks for row values will be ignored." + }, + "required-constraint": { + "name": "Required Constraint", + "type": "schema", + "context": "body", + "weight": 9, + "message": "Column {column_number} is a required field, but row {row_number} has no value", + "description": "This field is a required field, but it contains no value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove the `required` constraint from the schema.\n - If this error should be ignored disable `required-constraint` check in {validator}." + }, + "pattern-constraint": { + "name": "Pattern Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the pattern constraint of {constraint}", + "description": "This field value should conform to constraint pattern.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `pattern` constraint in the schema.\n - If this error should be ignored disable `pattern-constraint` check in {validator}." + }, + "unique-constraint": { + "name": "Unique Constraint", + "type": "schema", + "context": "body", + "weight": 9, + "message": "Rows {row_numbers} has unique constraint violation in column {column_number}", + "description": "This field is a unique field but it contains a value that has been used in another row.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then the values in this column are not unique. Remove the `unique` constraint from the schema.\n - If this error should be ignored disable `unique-constraint` check in {validator}." + }, + "enumerable-constraint": { + "name": "Enumerable Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the given enumeration: {constraint}", + "description": "This field value should be equal to one of the values in the enumeration constraint.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `enum` constraint in the schema.\n - If this error should be ignored disable `enumerable-constraint` check in {validator}." + }, + "minimum-constraint": { + "name": "Minimum Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the minimum constraint of {constraint}", + "description": "This field value should be greater or equal than constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `minimum` constraint in the schema.\n - If this error should be ignored disable `minimum-constraint` check in {validator}." + }, + "maximum-constraint": { + "name": "Maximum Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the maximum constraint of {constraint}", + "description": "This field value should be less or equal than constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `maximum` constraint in the schema.\n - If this error should be ignored disable `maximum-constraint` check in {validator}." + }, + "minimum-length-constraint": { + "name": "Minimum Length Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the minimum length constraint of {constraint}", + "description": "A lenght of this field value should be greater or equal than schema constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `minimumLength` constraint in the schema.\n - If this error should be ignored disable `minimum-length-constraint` check in {validator}." + }, + "maximum-length-constraint": { + "name": "Maximum Length Constraint", + "type": "schema", + "context": "body", + "weight": 7, + "message": "The value {value} in row {row_number} and column {column_number} does not conform to the maximum length constraint of {constraint}", + "description": "A lenght of this field value should be less or equal than schema constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `maximumLength` constraint in the schema.\n - If this error should be ignored disable `maximum-length-constraint` check in {validator}." + } + + + } +} diff --git a/main/resources/schemas/datapackage-template.json b/main/resources/schemas/datapackage-template.json new file mode 100644 index 000000000..53e5180cc --- /dev/null +++ b/main/resources/schemas/datapackage-template.json @@ -0,0 +1,16 @@ +{ + "image": "", + "license": "", + "last_updated": "", + "keywords": [], + "sources": [{ + "web": "", + "name": "", + "title": "" + }], + "name": "", + "description": "", + "resources": [], + "title": "", + "version": "" +} \ No newline at end of file diff --git a/main/src/com/google/refine/ProjectManager.java b/main/src/com/google/refine/ProjectManager.java index b01ffbae3..7373d5155 100644 --- a/main/src/com/google/refine/ProjectManager.java +++ b/main/src/com/google/refine/ProjectManager.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.io.InputStream; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -45,7 +46,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.tools.tar.TarOutputStream; import org.json.JSONArray; import org.json.JSONException; @@ -55,6 +56,8 @@ import org.slf4j.LoggerFactory; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; @@ -73,7 +76,6 @@ public abstract class ProjectManager { // Don't spend more than this much time saving projects if doing a quick save static protected final int QUICK_SAVE_MAX_TIME = 1000 * 30; // 30 secs - protected Map _projectsMetadata; protected Map _projectsTags;// TagName, number of projects having that tag protected PreferenceStore _preferenceStore; @@ -99,8 +101,8 @@ public abstract class ProjectManager { transient protected Map _projects; static public ProjectManager singleton; - - protected ProjectManager(){ + + protected ProjectManager() { _projectsMetadata = new HashMap(); _preferenceStore = new PreferenceStore(); _projects = new HashMap(); @@ -191,7 +193,7 @@ public abstract class ProjectManager { } catch (Exception e) { e.printStackTrace(); } - }//FIXME what should be the behaviour if metadata is null? i.e. not found + } Project project = getProject(id); if (project != null && metadata != null && metadata.getModified().isAfter(project.getLastSave())) { @@ -200,8 +202,7 @@ public abstract class ProjectManager { } catch (Exception e) { e.printStackTrace(); } - }//FIXME what should be the behaviour if project is null? i.e. not found or loaded. - //FIXME what should happen if the metadata is found, but not the project? or vice versa? + } } } @@ -212,7 +213,7 @@ public abstract class ProjectManager { * @param projectId * @throws Exception */ - public abstract void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception; + public abstract void saveMetadata(IMetadata metadata, long projectId) throws Exception; /** * Save project to the data store @@ -265,23 +266,23 @@ public abstract class ProjectManager { Project project = _projects.get(id); // don't call getProject() as that will load the project. if (project != null) { + LocalDateTime projectLastSaveTime = project.getLastSave(); boolean hasUnsavedChanges = - metadata.getModified().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() >= project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + !metadata.getModified().isBefore(projectLastSaveTime); // We use >= instead of just > to avoid the case where a newly created project // has the same modified and last save times, resulting in the project not getting // saved at all. if (hasUnsavedChanges) { - long msecsOverdue = startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - + long msecsOverdue = ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave); + records.add(new SaveRecord(project, msecsOverdue)); - } else if (!project.getProcessManager().hasPending() - && startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() > PROJECT_FLUSH_DELAY) { + && ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave) > PROJECT_FLUSH_DELAY) { /* - * It's been a while since the project was last saved and it hasn't been - * modified. We can safely remove it from the cache to save some memory. + * It's been a while since the project was last saved and it hasn't been + * modified. We can safely remove it from the cache to save some memory. */ _projects.remove(id).dispose(); } @@ -307,13 +308,10 @@ public abstract class ProjectManager { "Saving all modified projects ..." : "Saving some modified projects ..." ); - - for (int i = 0; - i < records.size() && - (allModified || (LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - - startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() < QUICK_SAVE_MAX_TIME)); + + for (int i = 0;i < records.size() && + (allModified || (ChronoUnit.MILLIS.between(startTimeOfSave, LocalDateTime.now()) < QUICK_SAVE_MAX_TIME)); i++) { - try { saveProject(records.get(i).project); } catch (Exception e) { @@ -351,14 +349,14 @@ public abstract class ProjectManager { /** * Gets the project metadata from memory - * Requires that the metadata has already been loaded from the data store + * Requires that the metadata has already been loaded from the data store. * @param id * @return */ public ProjectMetadata getProjectMetadata(long id) { return _projectsMetadata.get(id); } - + /** * Gets the project metadata from memory * Requires that the metadata has already been loaded from the data store @@ -368,7 +366,7 @@ public abstract class ProjectManager { public ProjectMetadata getProjectMetadata(String name) { for (ProjectMetadata pm : _projectsMetadata.values()) { if (pm.getName().equals(name)) { - return pm; + return pm; } } return null; @@ -420,7 +418,7 @@ public abstract class ProjectManager { userMetadataPreference = new JSONArray(userMeta); } catch (JSONException e1) { logger.warn("wrong definition of userMetadata format. Please use form [{\"name\": \"client name\", \"display\":true}, {\"name\": \"progress\", \"display\":false}]"); - logger.error(ExceptionUtils.getFullStackTrace(e1)); + logger.error(ExceptionUtils.getStackTrace(e1)); } for (int index = 0; index < userMetadataPreference.length(); index++) { @@ -465,7 +463,7 @@ public abstract class ProjectManager { JSONObject projectMetaJsonObj = jsonObjArray.getJSONObject(index); projectMetaJsonObj.put("display", false); } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } } @@ -474,6 +472,7 @@ public abstract class ProjectManager { * Gets all the project Metadata currently held in memory. * @return */ + public Map getAllProjectMetadata() { for(Project project : _projects.values()) { mergeEmptyUserMetadata(project.getMetadata()); @@ -484,13 +483,14 @@ public abstract class ProjectManager { /** * Gets all the project tags currently held in memory - * + * * @return */ public Map getAllProjectTags() { return _projectsTags; } + /** * Gets the required project from the data store * If project does not already exist in memory, it is loaded from the data store @@ -596,8 +596,9 @@ public abstract class ProjectManager { * * @param ps */ - static protected void preparePreferenceStore(PreferenceStore ps) { + public static void preparePreferenceStore(PreferenceStore ps) { ps.put("scripting.expressions", new TopList(s_expressionHistoryMax)); ps.put("scripting.starred-expressions", new TopList(Integer.MAX_VALUE)); } + } diff --git a/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java b/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java index 5d8885996..0d9a07bc1 100644 --- a/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java +++ b/main/src/com/google/refine/clustering/binning/FingerprintKeyer.java @@ -37,7 +37,7 @@ import java.util.Iterator; import java.util.TreeSet; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; public class FingerprintKeyer extends Keyer { diff --git a/main/src/com/google/refine/commands/Command.java b/main/src/com/google/refine/commands/Command.java index d4466c7f4..0ee9b1da9 100644 --- a/main/src/com/google/refine/commands/Command.java +++ b/main/src/com/google/refine/commands/Command.java @@ -52,11 +52,11 @@ import org.slf4j.LoggerFactory; import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.browsing.Engine; import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.process.Process; import com.google.refine.util.ParsingUtilities; @@ -194,7 +194,7 @@ public abstract class Command { * @return * @throws ServletException */ - protected ProjectMetadata getProjectMetadata(HttpServletRequest request) throws ServletException { + protected ProjectMetadata getMetadata(HttpServletRequest request) throws ServletException { if (request == null) { throw new IllegalArgumentException("parameter 'request' should not be null"); } @@ -312,7 +312,20 @@ public abstract class Command { w.flush(); w.close(); } + + static protected void respondJSONObject( + HttpServletResponse response, JSONObject o) + throws IOException, JSONException { + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type", "application/json"); + response.setHeader("Cache-Control", "no-cache"); + Writer w = response.getWriter(); + w.append(o.toString()); + w.flush(); + w.close(); + } + static protected void respondException(HttpServletResponse response, Exception e) throws IOException, ServletException { diff --git a/main/src/com/google/refine/commands/GetPreferenceCommand.java b/main/src/com/google/refine/commands/GetPreferenceCommand.java index 6780355da..0628efec7 100644 --- a/main/src/com/google/refine/commands/GetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/GetPreferenceCommand.java @@ -54,9 +54,7 @@ public class GetPreferenceCommand extends Command { throws ServletException, IOException { Project project = request.getParameter("project") != null ? getProject(request) : null; - PreferenceStore ps = project != null ? - project.getMetadata().getPreferenceStore() : - ProjectManager.singleton.getPreferenceStore(); + PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); String prefName = request.getParameter("name"); Object pref = ps.get(prefName); diff --git a/main/src/com/google/refine/commands/SetPreferenceCommand.java b/main/src/com/google/refine/commands/SetPreferenceCommand.java index cd0635015..ac5d3cf74 100644 --- a/main/src/com/google/refine/commands/SetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/SetPreferenceCommand.java @@ -52,9 +52,7 @@ public class SetPreferenceCommand extends Command { throws ServletException, IOException { Project project = request.getParameter("project") != null ? getProject(request) : null; - PreferenceStore ps = project != null ? - project.getMetadata().getPreferenceStore() : - ProjectManager.singleton.getPreferenceStore(); + PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); String prefName = request.getParameter("name"); String valueString = request.getParameter("value"); diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index a76a37fd0..950e7eab9 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -63,7 +63,7 @@ public class GetExpressionHistoryCommand extends Command { try { Project project = getProject(request); - List localExpressions = toExpressionList(project.getMetadata().getPreferenceStore().get("scripting.expressions")); + List localExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); localExpressions = localExpressions.size() > 20 ? localExpressions.subList(0, 20) : localExpressions; List globalExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); diff --git a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java index dd7df127c..3723869d8 100644 --- a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java @@ -54,7 +54,7 @@ public class LogExpressionCommand extends Command { Project project = getProject(request); String expression = request.getParameter("expression"); - ((TopList) project.getMetadata().getPreferenceStore().get("scripting.expressions")) + ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) .add(expression); ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) diff --git a/main/src/com/google/refine/commands/project/DeleteProjectCommand.java b/main/src/com/google/refine/commands/project/DeleteProjectCommand.java index 9d146a01e..f69f11d1b 100644 --- a/main/src/com/google/refine/commands/project/DeleteProjectCommand.java +++ b/main/src/com/google/refine/commands/project/DeleteProjectCommand.java @@ -41,8 +41,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; +import com.google.refine.model.medadata.ProjectMetadata; public class DeleteProjectCommand extends Command { diff --git a/main/src/com/google/refine/commands/project/GetMetadataCommand.java b/main/src/com/google/refine/commands/project/GetMetadataCommand.java new file mode 100644 index 000000000..87f797701 --- /dev/null +++ b/main/src/com/google/refine/commands/project/GetMetadataCommand.java @@ -0,0 +1,48 @@ +package com.google.refine.commands.project; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.everit.json.schema.ValidationException; +import org.json.JSONException; + +import com.google.refine.commands.Command; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.MetadataFactory; +import com.google.refine.model.medadata.MetadataFormat; + +public class GetMetadataCommand extends Command { + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + Project project; + MetadataFormat metadataFormat; + try { + project = getProject(request); + metadataFormat = MetadataFormat.valueOf(request.getParameter("metadataFormat")); + } catch (ServletException e) { + respond(response, "error", e.getLocalizedMessage()); + return; + } + + // for now, only the data package metadata is supported. + if (metadataFormat != MetadataFormat.DATAPACKAGE_METADATA) { + respond(response, "error", "metadata format is not supported"); + return; + } + + IMetadata metadata = MetadataFactory.buildDataPackageMetadata(project); + respondJSONObject(response, metadata.getJSON()); + } catch (JSONException e) { + respondException(response, e); + } catch (ValidationException e) { + respondException(response, e); + } + } +} diff --git a/main/src/com/google/refine/commands/project/ImportProjectCommand.java b/main/src/com/google/refine/commands/project/ImportProjectCommand.java index 740b72c9b..15f5c9b14 100644 --- a/main/src/com/google/refine/commands/project/ImportProjectCommand.java +++ b/main/src/com/google/refine/commands/project/ImportProjectCommand.java @@ -51,9 +51,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.ParsingUtilities; public class ImportProjectCommand extends Command { diff --git a/main/src/com/google/refine/commands/project/PackageProjectCommand.java b/main/src/com/google/refine/commands/project/PackageProjectCommand.java new file mode 100644 index 000000000..2a56e6388 --- /dev/null +++ b/main/src/com/google/refine/commands/project/PackageProjectCommand.java @@ -0,0 +1,83 @@ +package com.google.refine.commands.project; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.zip.GZIPOutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.tools.tar.TarOutputStream; + +import com.google.refine.ProjectManager; +import com.google.refine.browsing.Engine; +import com.google.refine.commands.Command; +import com.google.refine.exporters.CsvExporter; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.DataPackageMetadata; +import com.google.refine.model.medadata.PackageExtension; + +public class PackageProjectCommand extends Command { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + ProjectManager.singleton.setBusy(true); + + try { + // get the metadata + String metadata = request.getParameter("metadata"); + InputStream in = IOUtils.toInputStream(metadata, "UTF-8"); + + Project project = getProject(request); + Engine engine = getEngine(request, project); + + // ensure project get saved + DataPackageMetadata dpm = new DataPackageMetadata(); + dpm.loadFromStream(in); + ProjectManager.singleton.ensureProjectSaved(project.id); + + // export project + CsvExporter exporter = new CsvExporter(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Writer outputStreamWriter = new OutputStreamWriter(baos); + exporter.export(project, null, engine, outputStreamWriter); + + OutputStream os = response.getOutputStream(); + try { + PackageExtension.saveZip(dpm.getPackage(), baos, os); + response.setHeader("Content-Type", "application/x-gzip"); + } finally { + outputStreamWriter.close(); + os.close(); + } + } catch (Exception e) { + respondException(response, e); + } finally { + ProjectManager.singleton.setBusy(false); + } + } + + protected void gzipTarToOutputStream(Project project, OutputStream os) throws IOException { + GZIPOutputStream gos = new GZIPOutputStream(os); + try { + tarToOutputStream(project, gos); + } finally { + gos.close(); + } + } + + protected void tarToOutputStream(Project project, OutputStream os) throws IOException { + TarOutputStream tos = new TarOutputStream(os); + try { + ProjectManager.singleton.exportProject(project.id, tos); + } finally { + tos.close(); + } + } +} diff --git a/main/src/com/google/refine/commands/project/RenameProjectCommand.java b/main/src/com/google/refine/commands/project/RenameProjectCommand.java index b8023df4a..ccea3cf99 100644 --- a/main/src/com/google/refine/commands/project/RenameProjectCommand.java +++ b/main/src/com/google/refine/commands/project/RenameProjectCommand.java @@ -39,8 +39,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; +import com.google.refine.model.medadata.ProjectMetadata; public class RenameProjectCommand extends Command { @Override @@ -49,7 +49,7 @@ public class RenameProjectCommand extends Command { try { String name = request.getParameter("name"); - ProjectMetadata pm = getProjectMetadata(request); + ProjectMetadata pm = getMetadata(request); pm.setName(name); diff --git a/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java b/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java index 28399a733..b5b14b648 100644 --- a/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/project/SetProjectMetadataCommand.java @@ -9,15 +9,14 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; public class SetProjectMetadataCommand extends Command { @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - Project project = request.getParameter("project") != null ? getProject(request) : null; String metaName = request.getParameter("name"); String valueString = request.getParameter("value"); @@ -33,7 +32,7 @@ public class SetProjectMetadataCommand extends Command { response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); - meta.setAnyField(metaName, valueString); + meta.setAnyStringField(metaName, valueString); ProjectManager.singleton.saveMetadata(meta, project.id); respond(response, "{ \"code\" : \"ok\" }"); diff --git a/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java b/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java index 2bffa2a9f..00d3e3c61 100644 --- a/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java +++ b/main/src/com/google/refine/commands/project/SetProjectTagsCommand.java @@ -37,9 +37,9 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; public class SetProjectTagsCommand extends Command { @Override diff --git a/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java b/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java new file mode 100644 index 000000000..fbb96a327 --- /dev/null +++ b/main/src/com/google/refine/commands/project/ValidateSchemaCommand.java @@ -0,0 +1,42 @@ +package com.google.refine.commands.project; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.google.refine.ProjectManager; +import com.google.refine.commands.Command; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.validator.ValidateOperation; +import com.google.refine.util.ParsingUtilities; + +public class ValidateSchemaCommand extends Command { + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + ProjectManager.singleton.setBusy(true); + try { + Project project = getProject(request); + JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( + request.getParameter("options")); + + new ValidateOperation(project, optionObj).startProcess(); + + respond(response, "{ \"code\" : \"ok\" }"); + } catch (JSONException e) { + respondException(response, e); + } catch (ServletException e) { + respond(response, "error", e.getLocalizedMessage()); + return; + } finally { + ProjectManager.singleton.setBusy(false); + } + } +} diff --git a/main/src/com/google/refine/commands/row/GetRowsCommand.java b/main/src/com/google/refine/commands/row/GetRowsCommand.java index 32b088660..ca5cdf192 100644 --- a/main/src/com/google/refine/commands/row/GetRowsCommand.java +++ b/main/src/com/google/refine/commands/row/GetRowsCommand.java @@ -180,9 +180,9 @@ public class GetRowsCommand extends Command { } // metadata refresh for row mode and record mode - if (project.getMetadata() != null) { - project.getMetadata().setRowCount(project.rows.size()); - } + if (project.getMetadata() != null) { + project.getMetadata().setRowCount(project.rows.size()); + } } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java index b262c2cb7..786f005c0 100644 --- a/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java +++ b/main/src/com/google/refine/commands/workspace/GetAllProjectMetadataCommand.java @@ -47,8 +47,8 @@ import org.json.JSONException; import org.json.JSONWriter; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.Command; +import com.google.refine.model.medadata.ProjectMetadata; public class GetAllProjectMetadataCommand extends Command { @Override diff --git a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java index 08c31e356..7f392fc46 100644 --- a/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java +++ b/main/src/com/google/refine/exporters/CustomizableTabularExporterUtilities.java @@ -44,7 +44,7 @@ import java.util.Map; import java.util.Properties; import java.util.TimeZone; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/main/src/com/google/refine/exporters/HtmlTableExporter.java b/main/src/com/google/refine/exporters/HtmlTableExporter.java index a4a72de4f..3cb6ee926 100644 --- a/main/src/com/google/refine/exporters/HtmlTableExporter.java +++ b/main/src/com/google/refine/exporters/HtmlTableExporter.java @@ -38,7 +38,7 @@ import java.io.Writer; import java.util.List; import java.util.Properties; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONObject; import com.google.refine.ProjectManager; @@ -103,7 +103,7 @@ public class HtmlTableExporter implements WriterExporter { if (cellData.link != null) { writer.write(""); } writer.write(StringEscapeUtils.escapeXml(cellData.text)); diff --git a/main/src/com/google/refine/expr/functions/ToDate.java b/main/src/com/google/refine/expr/functions/ToDate.java index cc9b21f82..b74655cfe 100644 --- a/main/src/com/google/refine/expr/functions/ToDate.java +++ b/main/src/com/google/refine/expr/functions/ToDate.java @@ -42,7 +42,7 @@ import java.util.GregorianCalendar; import java.util.Locale; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Chomp.java b/main/src/com/google/refine/expr/functions/strings/Chomp.java index 06573940d..8ee9b5ae2 100644 --- a/main/src/com/google/refine/expr/functions/strings/Chomp.java +++ b/main/src/com/google/refine/expr/functions/strings/Chomp.java @@ -35,7 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Diff.java b/main/src/com/google/refine/expr/functions/strings/Diff.java index 0e2c90d25..74a3fecec 100644 --- a/main/src/com/google/refine/expr/functions/strings/Diff.java +++ b/main/src/com/google/refine/expr/functions/strings/Diff.java @@ -37,7 +37,7 @@ import java.util.Calendar; import java.util.Date; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Escape.java b/main/src/com/google/refine/expr/functions/strings/Escape.java index 2374722f9..b25f532de 100644 --- a/main/src/com/google/refine/expr/functions/strings/Escape.java +++ b/main/src/com/google/refine/expr/functions/strings/Escape.java @@ -37,7 +37,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Properties; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONException; import org.json.JSONWriter; @@ -65,13 +65,13 @@ public class Escape implements Function { if (o2 instanceof String) { String mode = ((String) o2).toLowerCase(); if ("html".equals(mode)) { - return StringEscapeUtils.escapeHtml(s); + return StringEscapeUtils.escapeHtml4(s); } else if ("xml".equals(mode)) { - return StringEscapeUtils.escapeXml(s); + return StringEscapeUtils.escapeXml11(s); } else if ("csv".equals(mode)) { return StringEscapeUtils.escapeCsv(s); } else if ("javascript".equals(mode)) { - return StringEscapeUtils.escapeJavaScript(s); + return StringEscapeUtils.escapeEcmaScript(s); } else if ("url".equals(mode)) { try { return URLEncoder.encode(s,"UTF-8"); diff --git a/main/src/com/google/refine/expr/functions/strings/NGram.java b/main/src/com/google/refine/expr/functions/strings/NGram.java index e2ff69fea..4c715a938 100644 --- a/main/src/com/google/refine/expr/functions/strings/NGram.java +++ b/main/src/com/google/refine/expr/functions/strings/NGram.java @@ -35,7 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java index a62b16c28..a376912e5 100644 --- a/main/src/com/google/refine/expr/functions/strings/Reinterpret.java +++ b/main/src/com/google/refine/expr/functions/strings/Reinterpret.java @@ -40,11 +40,11 @@ import org.json.JSONException; import org.json.JSONWriter; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.expr.EvalError; import com.google.refine.grel.ControlFunctionRegistry; import com.google.refine.grel.Function; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; public class Reinterpret implements Function { diff --git a/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java b/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java index ca4f91bce..4c32ff606 100644 --- a/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java +++ b/main/src/com/google/refine/expr/functions/strings/ReplaceChars.java @@ -35,7 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Split.java b/main/src/com/google/refine/expr/functions/strings/Split.java index a1f591321..2532c9cfc 100644 --- a/main/src/com/google/refine/expr/functions/strings/Split.java +++ b/main/src/com/google/refine/expr/functions/strings/Split.java @@ -36,7 +36,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java b/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java index b7942f7ec..85e316974 100644 --- a/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java +++ b/main/src/com/google/refine/expr/functions/strings/SplitByCharType.java @@ -35,7 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java b/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java index 244a3cf2d..e1bb2d7d8 100644 --- a/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java +++ b/main/src/com/google/refine/expr/functions/strings/ToTitlecase.java @@ -35,7 +35,7 @@ package com.google.refine.expr.functions.strings; import java.util.Properties; -import org.apache.commons.lang.WordUtils; +import org.apache.commons.lang3.text.WordUtils; import org.json.JSONException; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/expr/functions/strings/Unescape.java b/main/src/com/google/refine/expr/functions/strings/Unescape.java index e08436a22..6e901b070 100644 --- a/main/src/com/google/refine/expr/functions/strings/Unescape.java +++ b/main/src/com/google/refine/expr/functions/strings/Unescape.java @@ -37,7 +37,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Properties; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONException; import org.json.JSONWriter; @@ -56,13 +56,13 @@ public class Unescape implements Function { String s = (String) o1; String mode = ((String) o2).toLowerCase(); if ("html".equals(mode)) { - return StringEscapeUtils.unescapeHtml(s); + return StringEscapeUtils.unescapeHtml4(s); } else if ("xml".equals(mode)) { return StringEscapeUtils.unescapeXml(s); } else if ("csv".equals(mode)) { return StringEscapeUtils.unescapeCsv(s); } else if ("javascript".equals(mode)) { - return StringEscapeUtils.unescapeJavaScript(s); + return StringEscapeUtils.escapeEcmaScript(s); } else if ("url".equals(mode)) { try { return URLDecoder.decode(s,"UTF-8"); diff --git a/main/src/com/google/refine/grel/controls/IsNumeric.java b/main/src/com/google/refine/grel/controls/IsNumeric.java index 660022e5a..24013793d 100644 --- a/main/src/com/google/refine/grel/controls/IsNumeric.java +++ b/main/src/com/google/refine/grel/controls/IsNumeric.java @@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.grel.controls; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; public class IsNumeric extends IsTest { @Override diff --git a/main/src/com/google/refine/importers/ExcelImporter.java b/main/src/com/google/refine/importers/ExcelImporter.java index 2cd9cfbd2..2e49aa7c8 100644 --- a/main/src/com/google/refine/importers/ExcelImporter.java +++ b/main/src/com/google/refine/importers/ExcelImporter.java @@ -44,7 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLException; import org.apache.poi.common.usermodel.Hyperlink; @@ -60,13 +60,13 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.model.ReconCandidate; import com.google.refine.util.JSONUtilities; @@ -191,7 +191,7 @@ public class ExcelImporter extends TabularImportingParserBase { // value is fileName#sheetIndex fileNameAndSheetIndex = sheetObj.getString("fileNameAndSheetIndex").split("#"); } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } if (!fileNameAndSheetIndex[0].equals(fileSource)) diff --git a/main/src/com/google/refine/importers/FixedWidthImporter.java b/main/src/com/google/refine/importers/FixedWidthImporter.java index 89ca6ad0a..5eb437095 100644 --- a/main/src/com/google/refine/importers/FixedWidthImporter.java +++ b/main/src/com/google/refine/importers/FixedWidthImporter.java @@ -14,10 +14,10 @@ import java.util.List; import org.json.JSONArray; import org.json.JSONObject; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class FixedWidthImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/ImportingParserBase.java b/main/src/com/google/refine/importers/ImportingParserBase.java index b77206a8a..17bad6063 100644 --- a/main/src/com/google/refine/importers/ImportingParserBase.java +++ b/main/src/com/google/refine/importers/ImportingParserBase.java @@ -44,7 +44,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingParser; @@ -52,6 +51,7 @@ import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; abstract public class ImportingParserBase implements ImportingParser { diff --git a/main/src/com/google/refine/importers/JsonImporter.java b/main/src/com/google/refine/importers/JsonImporter.java index 35092e83d..93c66e1d9 100644 --- a/main/src/com/google/refine/importers/JsonImporter.java +++ b/main/src/com/google/refine/importers/JsonImporter.java @@ -49,7 +49,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -57,6 +56,7 @@ import com.google.refine.importers.tree.TreeReaderException; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class JsonImporter extends TreeImportingParserBase { diff --git a/main/src/com/google/refine/importers/LineBasedImporter.java b/main/src/com/google/refine/importers/LineBasedImporter.java index c0e561a77..7b2a2eda2 100644 --- a/main/src/com/google/refine/importers/LineBasedImporter.java +++ b/main/src/com/google/refine/importers/LineBasedImporter.java @@ -10,9 +10,9 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class LineBasedImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/OdsImporter.java b/main/src/com/google/refine/importers/OdsImporter.java index b6e5147dd..dce702252 100644 --- a/main/src/com/google/refine/importers/OdsImporter.java +++ b/main/src/com/google/refine/importers/OdsImporter.java @@ -44,7 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -55,13 +55,13 @@ import org.odftoolkit.odfdom.doc.table.OdfTableRow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Cell; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.Recon.Judgment; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.model.ReconCandidate; import com.google.refine.util.JSONUtilities; @@ -150,7 +150,7 @@ public class OdsImporter extends TabularImportingParserBase { // value is fileName#sheetIndex fileNameAndSheetIndex = sheetObj.getString("fileNameAndSheetIndex").split("#"); } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } if (!fileNameAndSheetIndex[0].equals(fileSource)) diff --git a/main/src/com/google/refine/importers/RdfTripleImporter.java b/main/src/com/google/refine/importers/RdfTripleImporter.java index bd73402bb..6df68cc01 100644 --- a/main/src/com/google/refine/importers/RdfTripleImporter.java +++ b/main/src/com/google/refine/importers/RdfTripleImporter.java @@ -50,7 +50,6 @@ import org.jrdf.parser.RdfReader; import org.jrdf.util.ClosableIterable; import org.json.JSONObject; -import com.google.refine.ProjectMetadata; import com.google.refine.expr.ExpressionUtils; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; @@ -58,6 +57,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; public class RdfTripleImporter extends ImportingParserBase { private RdfReader rdfReader; diff --git a/main/src/com/google/refine/importers/SeparatorBasedImporter.java b/main/src/com/google/refine/importers/SeparatorBasedImporter.java index ec662486e..58900b9af 100644 --- a/main/src/com/google/refine/importers/SeparatorBasedImporter.java +++ b/main/src/com/google/refine/importers/SeparatorBasedImporter.java @@ -49,15 +49,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONObject; import au.com.bytecode.opencsv.CSVParser; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class SeparatorBasedImporter extends TabularImportingParserBase { diff --git a/main/src/com/google/refine/importers/TabularImportingParserBase.java b/main/src/com/google/refine/importers/TabularImportingParserBase.java index c7cdff217..ffb8f58ad 100644 --- a/main/src/com/google/refine/importers/TabularImportingParserBase.java +++ b/main/src/com/google/refine/importers/TabularImportingParserBase.java @@ -41,13 +41,13 @@ import java.util.List; import org.json.JSONObject; -import com.google.refine.ProjectMetadata; import com.google.refine.expr.ExpressionUtils; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; abstract public class TabularImportingParserBase extends ImportingParserBase { diff --git a/main/src/com/google/refine/importers/WikitextImporter.java b/main/src/com/google/refine/importers/WikitextImporter.java index 382abf3bb..568430d93 100644 --- a/main/src/com/google/refine/importers/WikitextImporter.java +++ b/main/src/com/google/refine/importers/WikitextImporter.java @@ -56,13 +56,13 @@ import org.sweble.wikitext.parser.preprocessor.PreprocessedWikitext; import xtc.parser.ParseException; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingJob; import com.google.refine.model.Cell; import com.google.refine.model.Column; import com.google.refine.model.Project; import com.google.refine.model.Recon; import com.google.refine.model.ReconStats; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.model.recon.StandardReconConfig.ColumnDetail; import com.google.refine.util.JSONUtilities; import com.google.refine.model.recon.StandardReconConfig; diff --git a/main/src/com/google/refine/importers/XmlImporter.java b/main/src/com/google/refine/importers/XmlImporter.java index 92cb866d5..3bef0d3ca 100644 --- a/main/src/com/google/refine/importers/XmlImporter.java +++ b/main/src/com/google/refine/importers/XmlImporter.java @@ -51,7 +51,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.tree.ImportColumnGroup; import com.google.refine.importers.tree.TreeImportingParserBase; import com.google.refine.importers.tree.TreeReader; @@ -59,6 +58,7 @@ import com.google.refine.importers.tree.TreeReaderException; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; public class XmlImporter extends TreeImportingParserBase { diff --git a/main/src/com/google/refine/importers/tree/ImportColumnGroup.java b/main/src/com/google/refine/importers/tree/ImportColumnGroup.java index 9b004b1b8..f87c13abe 100644 --- a/main/src/com/google/refine/importers/tree/ImportColumnGroup.java +++ b/main/src/com/google/refine/importers/tree/ImportColumnGroup.java @@ -3,7 +3,7 @@ package com.google.refine.importers.tree; import java.util.LinkedHashMap; import java.util.Map; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; /** * A column group describes a branch in tree structured data diff --git a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java index 9fceab5b1..d54184ab7 100644 --- a/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java +++ b/main/src/com/google/refine/importers/tree/TreeImportingParserBase.java @@ -39,16 +39,16 @@ import java.io.InputStream; import java.io.Reader; import java.util.List; -import org.apache.commons.lang.NotImplementedException; +import org.apache.commons.lang3.NotImplementedException; import org.json.JSONObject; -import com.google.refine.ProjectMetadata; import com.google.refine.importers.ImporterUtilities; import com.google.refine.importers.ImporterUtilities.MultiFileReadingProgress; import com.google.refine.importers.ImportingParserBase; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingUtilities; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; /** @@ -154,7 +154,7 @@ abstract public class TreeImportingParserBase extends ImportingParserBase { JSONObject options, List exceptions ) { - throw new NotImplementedException(); + throw new NotImplementedException("project ID:" + project.id); } /** diff --git a/main/src/com/google/refine/importing/DefaultImportingController.java b/main/src/com/google/refine/importing/DefaultImportingController.java index 40029be91..c226097fb 100644 --- a/main/src/com/google/refine/importing/DefaultImportingController.java +++ b/main/src/com/google/refine/importing/DefaultImportingController.java @@ -271,7 +271,15 @@ public class DefaultImportingController implements ImportingController { throw new ServletException(e); } } - + + /** + * return the job to the front end. + * @param request + * @param response + * @param job + * @throws ServletException + * @throws IOException + */ private void replyWithJobData(HttpServletRequest request, HttpServletResponse response, ImportingJob job) throws ServletException, IOException { diff --git a/main/src/com/google/refine/importing/ImportingJob.java b/main/src/com/google/refine/importing/ImportingJob.java index 0ebd55390..f901cabca 100644 --- a/main/src/com/google/refine/importing/ImportingJob.java +++ b/main/src/com/google/refine/importing/ImportingJob.java @@ -47,8 +47,8 @@ import org.json.JSONWriter; import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.util.JSONUtilities; @@ -139,6 +139,14 @@ public class ImportingJob implements Jsonizable { } } + /** + * TO check if the file record is a metadata file entry + * @param fileRecordObject + * @return JSONObject + */ + public boolean isMetadataFileRecord(JSONObject fileRecordObject) { + return fileRecordObject.has("metaDataFormat"); + } public List getSelectedFileRecords() { List results = new ArrayList(); @@ -208,5 +216,4 @@ public class ImportingJob implements Jsonizable { writer.endObject(); } } - } diff --git a/main/src/com/google/refine/importing/ImportingParser.java b/main/src/com/google/refine/importing/ImportingParser.java index f2d85c0ae..f6896b364 100644 --- a/main/src/com/google/refine/importing/ImportingParser.java +++ b/main/src/com/google/refine/importing/ImportingParser.java @@ -37,8 +37,8 @@ import java.util.List; import org.json.JSONObject; -import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; public interface ImportingParser { /** diff --git a/main/src/com/google/refine/importing/ImportingUtilities.java b/main/src/com/google/refine/importing/ImportingUtilities.java index ffb9e65ba..5f67fcb57 100644 --- a/main/src/com/google/refine/importing/ImportingUtilities.java +++ b/main/src/com/google/refine/importing/ImportingUtilities.java @@ -42,6 +42,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.text.NumberFormat; @@ -49,9 +50,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -65,10 +68,14 @@ import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.util.Streams; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DecompressingHttpClient; import org.apache.http.impl.client.DefaultHttpClient; @@ -82,16 +89,35 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importing.ImportingManager.Format; import com.google.refine.importing.UrlRewriter.Result; +import com.google.refine.model.Column; +import com.google.refine.model.ColumnModel; import com.google.refine.model.Project; +import com.google.refine.model.Row; +import com.google.refine.model.medadata.DataPackageMetadata; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.MetadataFactory; +import com.google.refine.model.medadata.MetadataFormat; +import com.google.refine.model.medadata.PackageExtension; +import com.google.refine.model.medadata.ProjectMetadata; +import com.google.refine.preference.PreferenceStore; import com.google.refine.util.JSONUtilities; +import io.frictionlessdata.datapackage.Package; +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.Schema; +import io.frictionlessdata.tableschema.TypeInferrer; +import io.frictionlessdata.tableschema.exceptions.TypeInferringException; + public class ImportingUtilities { final static protected Logger logger = LoggerFactory.getLogger("importing-utilities"); + private final static String METADATA_FILE_KEY = "metadataFile"; + + private static final int INFER_ROW_LIMIT = 100; + static public interface Progress { public void setProgress(String message, int percent); public boolean isCanceled(); @@ -172,11 +198,11 @@ public class ImportingUtilities { ) throws Exception { JSONArray fileRecords = new JSONArray(); JSONUtilities.safePut(retrievalRecord, "files", fileRecords); + JSONUtilities.safePut(retrievalRecord, "downloadCount", 0); + JSONUtilities.safePut(retrievalRecord, "archiveCount", 0); int clipboardCount = 0; int uploadCount = 0; - int downloadCount = 0; - int archiveCount = 0; // This tracks the total progress, which involves uploading data from the client // as well as downloading data from URLs. @@ -220,7 +246,7 @@ public class ImportingUtilities { List tempFiles = (List)upload.parseRequest(request); progress.setProgress("Uploading data ...", -1); - parts: for (FileItem fileItem : tempFiles) { + for (FileItem fileItem : tempFiles) { if (progress.isCanceled()) { break; } @@ -255,107 +281,27 @@ public class ImportingUtilities { } else if (name.equals("download")) { String urlString = Streams.asString(stream); - URL url = new URL(urlString); - - JSONObject fileRecord = new JSONObject(); - JSONUtilities.safePut(fileRecord, "origin", "download"); - JSONUtilities.safePut(fileRecord, "url", urlString); + download(rawDataDir, retrievalRecord, progress, fileRecords, update, urlString); + processDataPackage(retrievalRecord, fileRecords); + } else if (name.equals("data-package")) { + String urlString = Streams.asString(stream); + List results = null; for (UrlRewriter rewriter : ImportingManager.urlRewriters) { - Result result = rewriter.rewrite(urlString); - if (result != null) { - urlString = result.rewrittenUrl; - url = new URL(urlString); - - JSONUtilities.safePut(fileRecord, "url", urlString); - JSONUtilities.safePut(fileRecord, "format", result.format); - if (!result.download) { - downloadCount++; - JSONUtilities.append(fileRecords, fileRecord); - continue parts; + results = rewriter.rewrite(urlString); + if (results != null) { + for (Result result : results) { + download(rawDataDir, retrievalRecord, progress, fileRecords, + update, result.rewrittenUrl, result.metaDataFormat); } } } - - if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) { - DefaultHttpClient client = new DefaultHttpClient(); - DecompressingHttpClient httpclient = - new DecompressingHttpClient(client); - HttpGet httpGet = new HttpGet(url.toURI()); - httpGet.setHeader("User-Agent", RefineServlet.getUserAgent()); - if ("https".equals(url.getProtocol())) { - // HTTPS only - no sending password in the clear over HTTP - String userinfo = url.getUserInfo(); - if (userinfo != null) { - int s = userinfo.indexOf(':'); - if (s > 0) { - String user = userinfo.substring(0, s); - String pw = userinfo.substring(s + 1, userinfo.length()); - client.getCredentialsProvider().setCredentials( - new AuthScope(url.getHost(), 443), - new UsernamePasswordCredentials(user, pw)); - } - } - } - - HttpResponse response = httpclient.execute(httpGet); - - try { - response.getStatusLine(); - HttpEntity entity = response.getEntity(); - if (entity == null) { - throw new Exception("No content found in " + url.toString()); - } - InputStream stream2 = entity.getContent(); - String encoding = null; - if (entity.getContentEncoding() != null) { - encoding = entity.getContentEncoding().getValue(); - } - JSONUtilities.safePut(fileRecord, "declaredEncoding", encoding); - String contentType = null; - if (entity.getContentType() != null) { - contentType = entity.getContentType().getValue(); - } - JSONUtilities.safePut(fileRecord, "declaredMimeType", contentType); - if (saveStream(stream2, url, rawDataDir, progress, update, - fileRecord, fileRecords, - entity.getContentLength())) { - archiveCount++; - } - downloadCount++; - EntityUtils.consume(entity); - } finally { - httpGet.releaseConnection(); - } - } else { - // Fallback handling for non HTTP connections (only FTP?) - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(5000); - urlConnection.connect(); - InputStream stream2 = urlConnection.getInputStream(); - JSONUtilities.safePut(fileRecord, "declaredEncoding", - urlConnection.getContentEncoding()); - JSONUtilities.safePut(fileRecord, "declaredMimeType", - urlConnection.getContentType()); - try { - if (saveStream(stream2, url, rawDataDir, progress, - update, fileRecord, fileRecords, - urlConnection.getContentLength())) { - archiveCount++; - } - downloadCount++; - } finally { - stream2.close(); - } - } } else { String value = Streams.asString(stream); parameters.put(name, value); // TODO: We really want to store this on the request so it's available for everyone // request.getParameterMap().put(name, value); - } - } else { // is file content String fileName = fileItem.getName(); if (fileName.length() > 0) { @@ -376,9 +322,11 @@ public class ImportingUtilities { JSONUtilities.safePut(fileRecord, "size", saveStreamToFile(stream, file, null)); if (postProcessRetrievedFile(rawDataDir, file, fileRecord, fileRecords, progress)) { - archiveCount++; + JSONUtilities.safeInc(retrievalRecord, "archiveCount"); } + processDataPackage(retrievalRecord, fileRecords); + uploadCount++; } } @@ -392,9 +340,144 @@ public class ImportingUtilities { } JSONUtilities.safePut(retrievalRecord, "uploadCount", uploadCount); - JSONUtilities.safePut(retrievalRecord, "downloadCount", downloadCount); JSONUtilities.safePut(retrievalRecord, "clipboardCount", clipboardCount); - JSONUtilities.safePut(retrievalRecord, "archiveCount", archiveCount); + } + + private static void processDataPackage(JSONObject retrievalRecord, JSONArray fileRecords) { + int dataPackageJSONFileIndex = getDataPackageJSONFile(fileRecords); + if (dataPackageJSONFileIndex >= 0) { + JSONObject dataPackageJSONFile = (JSONObject) fileRecords.get(dataPackageJSONFileIndex); + JSONUtilities.safePut(dataPackageJSONFile, "metaDataFormat", MetadataFormat.DATAPACKAGE_METADATA.name()); + JSONUtilities.safePut(retrievalRecord, METADATA_FILE_KEY, dataPackageJSONFile); + fileRecords.remove(dataPackageJSONFileIndex); + } + } + + private static int getDataPackageJSONFile(JSONArray fileRecords) { + for (int i = 0; i < fileRecords.length(); i++) { + JSONObject file = fileRecords.getJSONObject(i); + if (file.has("archiveFileName") && + file.has("fileName") && + file.get("fileName").equals(DataPackageMetadata.DEFAULT_FILE_NAME)) { + return i; + } + } + return -1; + } + + private static void download(File rawDataDir, JSONObject retrievalRecord, final Progress progress, + JSONArray fileRecords, final SavingUpdate update, String urlString) + throws URISyntaxException, IOException, ClientProtocolException, Exception { + download(rawDataDir, retrievalRecord, progress, fileRecords, update, urlString, null); + } + + /** + * @param rawDataDir + * @param retrievalRecord + * @param progress + * @param fileRecords + * @param update + * @param urlString + * @throws URISyntaxException + * @throws IOException + * @throws ClientProtocolException + * @throws Exception + */ + private static void download(File rawDataDir, JSONObject retrievalRecord, final Progress progress, + JSONArray fileRecords, final SavingUpdate update, String urlString, String metaDataFormat) + throws URISyntaxException, IOException, ClientProtocolException, Exception { + URL url = new URL(urlString); + JSONObject fileRecord = new JSONObject(); + JSONUtilities.safePut(fileRecord, "origin", "download"); + JSONUtilities.safePut(fileRecord, "url", urlString); + + if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) { + DefaultHttpClient client = new DefaultHttpClient(); + DecompressingHttpClient httpclient = + new DecompressingHttpClient(client); + HttpGet httpGet = new HttpGet(url.toURI()); + httpGet.setHeader("User-Agent", RefineServlet.getUserAgent()); + if ("https".equals(url.getProtocol())) { + // HTTPS only - no sending password in the clear over HTTP + String userinfo = url.getUserInfo(); + if (userinfo != null) { + int s = userinfo.indexOf(':'); + if (s > 0) { + String user = userinfo.substring(0, s); + String pw = userinfo.substring(s + 1, userinfo.length()); + client.getCredentialsProvider().setCredentials( + new AuthScope(url.getHost(), 443), + new UsernamePasswordCredentials(user, pw)); + } + } + } + + HttpResponse response = httpclient.execute(httpGet); + + try { + int code = response.getStatusLine().getStatusCode(); + if (code != HttpStatus.SC_OK) { + throw new Exception("HTTP response code: " + code + + " when accessing URL: "+ url.toString()); + } + + HttpEntity entity = response.getEntity(); + if (entity == null) { + throw new Exception("No content found in " + url.toString()); + } + InputStream stream2 = entity.getContent(); + String encoding = null; + if (entity.getContentEncoding() != null) { + encoding = entity.getContentEncoding().getValue(); + } + JSONUtilities.safePut(fileRecord, "declaredEncoding", encoding); + String contentType = null; + if (entity.getContentType() != null) { + contentType = entity.getContentType().getValue(); + } + JSONUtilities.safePut(fileRecord, "declaredMimeType", contentType); + + if (saveStream(stream2, url, rawDataDir, progress, update, + fileRecord, fileRecords, + entity.getContentLength())) { + JSONUtilities.safeInc(retrievalRecord, "archiveCount"); + } + + if (metaDataFormat != null) { + JSONUtilities.safePut(fileRecord, "metaDataFormat", metaDataFormat); + JSONUtilities.safePut(retrievalRecord, METADATA_FILE_KEY, fileRecord); + fileRecords.remove(0); + } + + JSONUtilities.safeInc(retrievalRecord, "downloadCount"); + EntityUtils.consume(entity); + } finally { + httpGet.releaseConnection(); + } + } else { + // Fallback handling for non HTTP connections (only FTP?) + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(5000); + urlConnection.connect(); + InputStream stream2 = urlConnection.getInputStream(); + JSONUtilities.safePut(fileRecord, "declaredEncoding", + urlConnection.getContentEncoding()); + JSONUtilities.safePut(fileRecord, "declaredMimeType", + urlConnection.getContentType()); + try { + if (saveStream(stream2, url, rawDataDir, progress, + update, fileRecord, fileRecords, + urlConnection.getContentLength())) { + JSONUtilities.safeInc(retrievalRecord, "archiveCount"); + } + if (metaDataFormat != null) + JSONUtilities.safePut(fileRecord, "metaDataFormat", metaDataFormat); + + JSONUtilities.safeInc(retrievalRecord, "downloadCount"); + } finally { + stream2.close(); + } + } } private static boolean saveStream(InputStream stream, URL url, File rawDataDir, final Progress progress, @@ -1021,8 +1104,45 @@ public class ImportingUtilities { if (exceptions.size() == 0) { project.update(); // update all internal models, indexes, caches, etc. + boolean hasMetadataFileRecord = ((JSONObject)job.getRetrievalRecord()).has(METADATA_FILE_KEY); + + if (hasMetadataFileRecord) { + JSONObject metadataFileRecord = (JSONObject) job.getRetrievalRecord().get(METADATA_FILE_KEY); + + String metadataFormat = (String)metadataFileRecord.get("metaDataFormat"); + IMetadata metadata = MetadataFactory.buildMetadata(MetadataFormat.valueOf(metadataFormat)); + + String relativePath = metadataFileRecord.getString("location"); + File metadataFile = new File(job.getRawDataDir(), relativePath); + metadata.loadFromFile(metadataFile); + + // process the data package metadata + if (MetadataFormat.valueOf(metadataFormat) == MetadataFormat.DATAPACKAGE_METADATA) { + populateDataPackageMetadata(project, pm, (DataPackageMetadata) metadata); + } + logger.info(metadataFileRecord.get("metaDataFormat") + " metadata is set for project " + project.id); + } + ProjectManager.singleton.registerProject(project, pm); + // infer the column type + if (project.columnModel.columns.get(0).getType().isEmpty()) { + List listCells = new ArrayList(INFER_ROW_LIMIT); + List rows = project.rows + .stream() + .limit(INFER_ROW_LIMIT) + .collect(Collectors.toList()); + rows.forEach(r->listCells.add(r.cells.toArray())); + try { + JSONObject fieldsJSON = TypeInferrer.getInstance().infer(listCells, + project.columnModel.getColumnNames().toArray(new String[0]), + 100); + populateColumnTypes(project.columnModel, fieldsJSON.getJSONArray(Schema.JSON_KEY_FIELDS)); + } catch (TypeInferringException e) { + logger.error("infer column type exception.", ExceptionUtils.getStackTrace(e)); + } + } + job.setProjectID(project.id); job.setState("created-project"); } else { @@ -1032,11 +1152,72 @@ public class ImportingUtilities { job.updating = false; } } + + private static void populateDataPackageMetadata(Project project, ProjectMetadata pmd, DataPackageMetadata metadata) { + // project metadata + JSONObject pkg = metadata.getPackage().getJson(); + + pmd.setName(getDataPackageProperty(pkg, Package.JSON_KEY_NAME)); + pmd.setDescription(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_DESCRIPTION)); + pmd.setTitle(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_TITLE)); + pmd.setHomepage(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_HOMEPAGE)); + pmd.setImage(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_IMAGE)); + pmd.setLicense(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_LICENSE)); + pmd.setVersion(getDataPackageProperty(pkg, PackageExtension.JSON_KEY_VERSION)); + + if (pkg.has(PackageExtension.JSON_KEY_KEYWORKS)) { + String[] tags = pkg.getJSONArray(PackageExtension.JSON_KEY_KEYWORKS).toList().toArray(new String[0]); + pmd.appendTags(tags); + } + + // column model + JSONObject schema = metadata.getPackage().getResources().get(0).getSchema(); + if (schema != null) { + populateColumnTypes(project.columnModel, schema.getJSONArray(Schema.JSON_KEY_FIELDS)); + } + } + + private static String getDataPackageProperty(JSONObject pkg, String key) { + return JSONUtilities.getString(pkg, key, StringUtils.EMPTY); + } + /** + * Populate the column model + * @param columnModel + * @param fieldsJSON + */ + private static void populateColumnTypes(ColumnModel columnModel, JSONArray fieldsJSON) { + int cellIndex = 0; + Iterator iter = fieldsJSON.iterator(); + while(iter.hasNext()){ + JSONObject fieldJsonObj = (JSONObject)iter.next(); + Field field = new Field(fieldJsonObj); + + Column column = columnModel.getColumnByCellIndex(cellIndex); + column.setType(field.getType()); + column.setFormat(field.getFormat()); + column.setDescription(field.getDescription()); + column.setTitle(field.getTitle()); + column.setConstraints(field.getConstraints()); + + cellIndex++; + } + } + /** + * Create project metadata. pull the "USER_NAME" from the PreferenceStore as the creator + * @param optionObj + * @return + */ static public ProjectMetadata createProjectMetadata(JSONObject optionObj) { ProjectMetadata pm = new ProjectMetadata(); + PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); + pm.setName(JSONUtilities.getString(optionObj, "projectName", "Untitled")); pm.setTags(JSONUtilities.getStringArray(optionObj, "projectTags")); + pm.setTitle(JSONUtilities.getString(optionObj, "title", "")); + pm.setHomepage(JSONUtilities.getString(optionObj, "homepage", "")); + pm.setImage(JSONUtilities.getString(optionObj, "image", "")); + pm.setLicense(JSONUtilities.getString(optionObj, "license", "")); String encoding = JSONUtilities.getString(optionObj, "encoding", "UTF-8"); if ("".equals(encoding)) { @@ -1044,6 +1225,12 @@ public class ImportingUtilities { encoding = "UTF-8"; } pm.setEncoding(encoding); + + if (ps.get(PreferenceStore.USER_NAME) != null) { + String creator = (String) ps.get(PreferenceStore.USER_NAME); + pm.setCreator(creator); + } + return pm; } } diff --git a/main/src/com/google/refine/importing/UrlRewriter.java b/main/src/com/google/refine/importing/UrlRewriter.java index 4e6015488..d7332750e 100644 --- a/main/src/com/google/refine/importing/UrlRewriter.java +++ b/main/src/com/google/refine/importing/UrlRewriter.java @@ -33,12 +33,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.importing; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; + +/** + * Given a URL rewrittenUrl, the interface will rewrite it into different URLS based on the rewrittenUrl + * The result will be stored in the Result and can be used for download, parsing etc. + * Typical use is to parse the data package json file. + * @see DataPackageUrlRewriter + */ public interface UrlRewriter { static public class Result { public String rewrittenUrl; public String format; public boolean download; + public String metaDataFormat; + + public Result(String rewrittenUrl, String format, boolean download) { + this.rewrittenUrl = rewrittenUrl; + this.format = format; + this.download = download; + } + + public Result(String rewrittenUrl, String format, boolean download, String metaDataFormat) { + this.rewrittenUrl = rewrittenUrl; + this.format = format; + this.download = download; + this.metaDataFormat = metaDataFormat; + } } - public Result rewrite(String url); + /** + * Parse the url and output the Result + * @param url + * @return + * @throws MalformedURLException + * @throws IOException + */ + public List rewrite(String url) throws MalformedURLException, IOException; + + public boolean filter(String url); } diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index 0ff27e0f5..eb5c54662 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -57,9 +57,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.DataPackageMetadata; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.MetadataFormat; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.preference.TopList; @@ -120,7 +123,6 @@ public class FileProjectManager extends ProjectManager { if (metadata == null) { metadata = ProjectMetadataUtilities.recover(getProjectDir(projectID), projectID); } - if (metadata != null) { _projectsMetadata.put(projectID, metadata); if (_projectsTags == null) { @@ -155,7 +157,7 @@ public class FileProjectManager extends ProjectManager { untar(destDir, inputStream); } } - + protected void untar(File destDir, InputStream inputStream) throws IOException { TarInputStream tin = new TarInputStream(inputStream); TarEntry tarEntry = null; @@ -231,9 +233,19 @@ public class FileProjectManager extends ProjectManager { } @Override - public void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception { + public void saveMetadata(IMetadata metadata, long projectId) throws Exception { File projectDir = getProjectDir(projectId); - ProjectMetadataUtilities.save(metadata, projectDir); + + if (metadata.getFormatName() == MetadataFormat.PROJECT_METADATA) { + Project project = ProjectManager.singleton.getProject(projectId); + ((ProjectMetadata)metadata).setRowCount(project.rows.size()); + ProjectMetadataUtilities.save(metadata, projectDir); + } else if (metadata.getFormatName() == MetadataFormat.DATAPACKAGE_METADATA) { + DataPackageMetadata dp = (DataPackageMetadata)metadata; + dp.writeToFile(new File(projectDir, DataPackageMetadata.DEFAULT_FILE_NAME)); + } + + logger.info("metadata saved in " + metadata.getFormatName()); } @Override @@ -320,8 +332,6 @@ public class FileProjectManager extends ProjectManager { return saveWasNeeded; } - - @Override public void deleteProject(long projectID) { synchronized (this) { @@ -363,8 +373,6 @@ public class FileProjectManager extends ProjectManager { protected boolean loadFromFile(File file) { logger.info("Loading workspace: {}", file.getAbsolutePath()); - _projectsMetadata.clear(); - boolean found = false; if (file.exists() || file.canRead()) { @@ -464,4 +472,4 @@ public class FileProjectManager extends ProjectManager { public HistoryEntryManager getHistoryEntryManager(){ return new FileHistoryEntryManager(); } -} +} \ No newline at end of file diff --git a/main/src/com/google/refine/io/ProjectMetadataUtilities.java b/main/src/com/google/refine/io/ProjectMetadataUtilities.java index d6f3d8b93..6eaf81bbf 100644 --- a/main/src/com/google/refine/io/ProjectMetadataUtilities.java +++ b/main/src/com/google/refine/io/ProjectMetadataUtilities.java @@ -35,7 +35,6 @@ package com.google.refine.io; import java.io.File; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; @@ -44,27 +43,25 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.refine.ProjectMetadata; import com.google.refine.model.Project; - +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.ProjectMetadata; public class ProjectMetadataUtilities { final static Logger logger = LoggerFactory.getLogger("project_metadata_utilities"); - - public static void save(ProjectMetadata projectMeta, File projectDir) throws JSONException, IOException { - File tempFile = new File(projectDir, "metadata.temp.json"); + + public static void save(IMetadata projectMeta, File projectDir) throws JSONException, IOException { + File tempFile = new File(projectDir, ProjectMetadata.TEMP_FILE_NAME); saveToFile(projectMeta, tempFile); - File file = new File(projectDir, "metadata.json"); - File oldFile = new File(projectDir, "metadata.old.json"); + File file = new File(projectDir, ProjectMetadata.DEFAULT_FILE_NAME); + File oldFile = new File(projectDir, ProjectMetadata.OLD_FILE_NAME); if (oldFile.exists()) { oldFile.delete(); @@ -76,12 +73,16 @@ public class ProjectMetadataUtilities { tempFile.renameTo(file); } + + public static void saveTableSchema(Project project, File projectDir) throws JSONException, IOException { - protected static void saveToFile(ProjectMetadata projectMeta, File metadataFile) throws JSONException, IOException { + } + + protected static void saveToFile(IMetadata projectMeta, File metadataFile) throws JSONException, IOException { Writer writer = new OutputStreamWriter(new FileOutputStream(metadataFile)); try { JSONWriter jsonWriter = new JSONWriter(writer); - projectMeta.write(jsonWriter); + projectMeta.write(jsonWriter, false); } finally { writer.close(); } @@ -89,17 +90,17 @@ public class ProjectMetadataUtilities { static public ProjectMetadata load(File projectDir) { try { - return loadFromFile(new File(projectDir, "metadata.json")); + return loadFromFile(new File(projectDir, ProjectMetadata.DEFAULT_FILE_NAME)); } catch (Exception e) { } try { - return loadFromFile(new File(projectDir, "metadata.temp.json")); + return loadFromFile(new File(projectDir, ProjectMetadata.TEMP_FILE_NAME)); } catch (Exception e) { } try { - return loadFromFile(new File(projectDir, "metadata.old.json")); + return loadFromFile(new File(projectDir, ProjectMetadata.OLD_FILE_NAME)); } catch (Exception e) { } @@ -148,14 +149,8 @@ public class ProjectMetadataUtilities { } static protected ProjectMetadata loadFromFile(File metadataFile) throws Exception { - FileReader reader = new FileReader(metadataFile); - try { - JSONTokener tokener = new JSONTokener(reader); - JSONObject obj = (JSONObject) tokener.nextValue(); - - return ProjectMetadata.loadFromJSON(obj); - } finally { - reader.close(); - } + ProjectMetadata projectMetaData = new ProjectMetadata(); + projectMetaData.loadFromFile(metadataFile); + return projectMetaData; } } diff --git a/main/src/com/google/refine/io/ProjectUtilities.java b/main/src/com/google/refine/io/ProjectUtilities.java index 4088cfeb9..f72856f46 100644 --- a/main/src/com/google/refine/io/ProjectUtilities.java +++ b/main/src/com/google/refine/io/ProjectUtilities.java @@ -36,6 +36,8 @@ package com.google.refine.io; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; @@ -45,6 +47,9 @@ import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.DataPackageMetadata; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.MetadataFormat; import com.google.refine.util.Pool; @@ -110,38 +115,63 @@ public class ProjectUtilities { out.close(); } } - - static public Project load(File dir, long id) { + + static public Project loadDataFile(File dir, String dataFile, long id) { try { - File file = new File(dir, "data.zip"); + File file = new File(dir, dataFile); if (file.exists()) { return loadFromFile(file, id); } } catch (Exception e) { e.printStackTrace(); } - - try { - File file = new File(dir, "data.temp.zip"); - if (file.exists()) { - return loadFromFile(file, id); - } - } catch (Exception e) { - e.printStackTrace(); - } - - try { - File file = new File(dir, "data.old.zip"); - if (file.exists()) { - return loadFromFile(file, id); - } - } catch (Exception e) { - e.printStackTrace(); - } - + return null; } - + + static public Project load(File dir, long id) { + Project project =null; + + if ((project = loadDataFile(dir, "data.zip", id)) == null) { + if ((project = loadDataFile(dir, "data.temp.zip", id)) == null) { + project = loadDataFile(dir, "data.old.zip", id); + } + } + return project; + } + + + /** + * scan the folder for json files and read them as metadata + * @param dir + * @param project + */ + public static Map retriveMetadata(File dir) { + // load the metadatas from data folder. + Map metadataMap = new HashMap(); + + File[] jsons = dir.listFiles( + (folder, file) -> { + return file.toLowerCase().endsWith(".json"); + } + ); + + for (File file : jsons) { + // already loaded + if (file.getName().startsWith("metadata.")) + continue; + + DataPackageMetadata metadata = new DataPackageMetadata(); + // load itself + metadata.loadFromFile(file); + + metadataMap.put(MetadataFormat.DATAPACKAGE_METADATA, metadata); + } + + return metadataMap; + + } + static protected Project loadFromFile( File file, long id diff --git a/main/src/com/google/refine/model/Column.java b/main/src/com/google/refine/model/Column.java index 9a6e44bd6..3eafa45db 100644 --- a/main/src/com/google/refine/model/Column.java +++ b/main/src/com/google/refine/model/Column.java @@ -34,10 +34,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model; import java.io.Writer; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; @@ -45,8 +47,14 @@ import org.json.JSONWriter; import com.google.refine.InterProjectModel; import com.google.refine.Jsonizable; import com.google.refine.model.recon.ReconConfig; +import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.TypeInferrer; +import io.frictionlessdata.tableschema.exceptions.ConstraintsException; +import io.frictionlessdata.tableschema.exceptions.InvalidCastException; + public class Column implements Jsonizable { final private int _cellIndex; final private String _originalName; @@ -54,6 +62,13 @@ public class Column implements Jsonizable { private ReconConfig _reconConfig; private ReconStats _reconStats; + // from data package metadata Field.java: + private String type = ""; + private String format = Field.FIELD_FORMAT_DEFAULT; + private String title = ""; + private String description = ""; + private Map constraints = null; + transient protected Map _precomputes; public Column(int cellIndex, String originalName) { @@ -101,6 +116,11 @@ public class Column implements Jsonizable { writer.key("cellIndex"); writer.value(_cellIndex); writer.key("originalName"); writer.value(_originalName); writer.key("name"); writer.value(_name); + writer.key("type"); writer.value(type); + writer.key("format"); writer.value(format); + writer.key("title"); writer.value(title); + writer.key("description"); writer.value(description); + writer.key("constraints"); writer.value(new JSONObject(constraints).toString()); if (_reconConfig != null) { writer.key("reconConfig"); _reconConfig.write(writer, options); @@ -140,6 +160,56 @@ public class Column implements Jsonizable { _precomputes.put(key, value); } + + public String getType() { + return type; + } + + + public void setType(String type) { + this.type = type; + } + + + public String getFormat() { + return format; + } + + + public void setFormat(String format) { + this.format = format; + } + + + public String getTitle() { + return title; + } + + + public void setTitle(String title) { + this.title = title; + } + + + public String getDescription() { + return description; + } + + + public void setDescription(String description) { + this.description = description; + } + + + public Map getConstraints() { + return constraints; + } + + + public void setConstraints(Map constraints) { + this.constraints = constraints; + } + public void save(Writer writer) { JSONWriter jsonWriter = new JSONWriter(writer); try { @@ -154,6 +224,14 @@ public class Column implements Jsonizable { Column column = new Column(obj.getInt("cellIndex"), obj.getString("originalName")); column._name = obj.getString("name"); + column.type = JSONUtilities.getString(obj, Field.JSON_KEY_TYPE, StringUtils.EMPTY); + column.format = JSONUtilities.getString(obj, Field.JSON_KEY_FORMAT, StringUtils.EMPTY); + column.title = JSONUtilities.getString(obj, Field.JSON_KEY_TITLE, StringUtils.EMPTY); + column.description = JSONUtilities.getString(obj, Field.JSON_KEY_DESCRIPTION, StringUtils.EMPTY); + if (obj.has(Field.JSON_KEY_CONSTRAINTS)) { + column.constraints = new JSONObject(obj.getString(Field.JSON_KEY_CONSTRAINTS)).toMap(); + } + if (obj.has("reconConfig")) { column._reconConfig = ReconConfig.reconstruct(obj.getJSONObject("reconConfig")); } @@ -168,4 +246,23 @@ public class Column implements Jsonizable { public String toString() { return _name; } + + public Any castValue(String value) + throws InvalidCastException, ConstraintsException { + if (this.type.isEmpty()) { + throw new InvalidCastException(); + } else { + try { + // Using reflection to invoke appropriate type casting method from the + // TypeInferrer class + String castMethodName = "cast" + (this.type.substring(0, 1).toUpperCase() + this.type.substring(1)); + Method method = TypeInferrer.class.getMethod(castMethodName, String.class, String.class, Map.class); + Object castValue = method.invoke(TypeInferrer.getInstance(), this.format, value, null); + + return (Any) castValue; + } catch (Exception e) { + throw new InvalidCastException(); + } + } + } } diff --git a/main/src/com/google/refine/model/Project.java b/main/src/com/google/refine/model/Project.java index 7d35f29d2..e9a984ebc 100644 --- a/main/src/com/google/refine/model/Project.java +++ b/main/src/com/google/refine/model/Project.java @@ -55,9 +55,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.history.History; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.process.ProcessManager; import com.google.refine.util.ParsingUtilities; import com.google.refine.util.Pool; @@ -77,14 +77,13 @@ public class Project { transient private LocalDateTime _lastSave = LocalDateTime.now(); final static Logger logger = LoggerFactory.getLogger("project"); - + static public long generateID() { return System.currentTimeMillis() + Math.round(Math.random() * 1000000000000L); } public Project() { - id = generateID(); - history = new History(this); + this(generateID()); } protected Project(long id) { @@ -121,10 +120,6 @@ public class Project { this._lastSave = LocalDateTime.now(); } - public ProjectMetadata getMetadata() { - return ProjectManager.singleton.getProjectMetadata(id); - } - public void saveToOutputStream(OutputStream out, Pool pool) throws IOException { for (OverlayModel overlayModel : overlayModels.values()) { try { @@ -258,11 +253,14 @@ public class Project { columnModel.update(); recordModel.update(this); } - - + //wrapper of processManager variable to allow unit testing //TODO make the processManager variable private, and force all calls through this method public ProcessManager getProcessManager() { return this.processManager; } + + public ProjectMetadata getMetadata() { + return ProjectManager.singleton.getProjectMetadata(id); + } } diff --git a/main/src/com/google/refine/model/RecordModel.java b/main/src/com/google/refine/model/RecordModel.java index 2e259283b..47a6e24a7 100644 --- a/main/src/com/google/refine/model/RecordModel.java +++ b/main/src/com/google/refine/model/RecordModel.java @@ -1,303 +1,303 @@ -/* - -Copyright 2010, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -package com.google.refine.model; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.refine.Jsonizable; -import com.google.refine.expr.ExpressionUtils; - -public class RecordModel implements Jsonizable { - final static Logger logger = LoggerFactory.getLogger("RecordModel"); - - final static public class CellDependency { - final public int rowIndex; - final public int cellIndex; - - public CellDependency(int rowIndex, int cellIndex) { - this.rowIndex = rowIndex; - this.cellIndex = cellIndex; - } - - @Override - public String toString() { - return rowIndex+","+cellIndex; - } - } - - final static public class RowDependency { - public int recordIndex; - public CellDependency[] cellDependencies; - public List contextRows; - - @Override - public String toString() { - return "Idx: "+recordIndex+" CellDeps: "+Arrays.toString(cellDependencies)+" Rows:"+contextRows; - } - } - - protected List _rowDependencies; - protected List _records; - - public RowDependency getRowDependency(int rowIndex) { - return _rowDependencies != null && rowIndex >= 0 && rowIndex < _rowDependencies.size() ? - _rowDependencies.get(rowIndex) : null; - } - - public int getRecordCount() { - return _records.size(); - } - - public Record getRecord(int recordIndex) { - return _records != null && recordIndex >= 0 && recordIndex < _records.size() ? - _records.get(recordIndex) : null; - } - - public Record getRecordOfRow(int rowIndex) { - RowDependency rd = getRowDependency(rowIndex); - if (rd != null) { - if (rd.recordIndex < 0) { - rd = getRowDependency(rd.contextRows.get(0)); - } - return getRecord(rd.recordIndex); - } - return null; - } - - @Override - synchronized public void write(JSONWriter writer, Properties options) - throws JSONException { - - writer.object(); - writer.key("hasRecords"); - writer.value( - _records != null && _rowDependencies != null && - _records.size() < _rowDependencies.size()); - writer.endObject(); - } - - static protected class KeyedGroup { - int[] cellIndices; - int keyCellIndex; - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - for (int i:cellIndices) { - sb.append(i).append(','); - } - return "key: " + keyCellIndex + " cells: " + sb.toString(); - } - } - - synchronized public void update(Project project) { - synchronized (project) { - List rows = project.rows; - int rowCount = rows.size(); - - ColumnModel columnModel = project.columnModel; - List keyedGroups = computeKeyedGroups(columnModel); - int groupCount = keyedGroups.size(); - - int[] lastNonBlankRowsByGroup = new int[keyedGroups.size()]; - for (int i = 0; i < lastNonBlankRowsByGroup.length; i++) { - lastNonBlankRowsByGroup[i] = -1; - } - - _rowDependencies = new ArrayList(rowCount); - - int recordIndex = 0; - for (int r = 0; r < rowCount; r++) { - Row row = rows.get(r); - RowDependency rowDependency = new RowDependency(); - - for (int g = 0; g < groupCount; g++) { - KeyedGroup group = keyedGroups.get(g); - - if (!ExpressionUtils.isNonBlankData(row.getCellValue(keyedGroups.get(0).keyCellIndex)) && - !ExpressionUtils.isNonBlankData(row.getCellValue(group.keyCellIndex))) { - int contextRowIndex = lastNonBlankRowsByGroup[g]; - if (contextRowIndex >= 0) { - for (int dependentCellIndex : group.cellIndices) { - if (ExpressionUtils.isNonBlankData(row.getCellValue(dependentCellIndex))) { - setRowDependency( - project, - rowDependency, - dependentCellIndex, - contextRowIndex, - group.keyCellIndex - ); - } - } - } - } else { - lastNonBlankRowsByGroup[g] = r; - } - } - - if (rowDependency.cellDependencies != null && rowDependency.cellDependencies.length > 0) { - rowDependency.recordIndex = -1; - rowDependency.contextRows = new ArrayList(); - for (CellDependency cd : rowDependency.cellDependencies) { - if (cd != null) { - rowDependency.contextRows.add(cd.rowIndex); - } - } - Collections.sort(rowDependency.contextRows); - } else { - rowDependency.recordIndex = recordIndex++; - } - - _rowDependencies.add(rowDependency); - } - - _records = new ArrayList(recordIndex); - if (recordIndex > 0) { - recordIndex = 0; - - int recordRowIndex = 0; - for (int r = 1; r < rowCount; r++) { - RowDependency rd = _rowDependencies.get(r); - if (rd.recordIndex >= 0) { - _records.add(new Record(recordRowIndex, r, recordIndex++)); - - recordIndex = rd.recordIndex; - recordRowIndex = r; - } - } - - _records.add(new Record(recordRowIndex, rowCount, recordIndex++)); - } - } - } - - protected List computeKeyedGroups(ColumnModel columnModel) { - List keyedGroups = new ArrayList(); - - addRootKeyedGroup(columnModel, keyedGroups); - - for (ColumnGroup group : columnModel.columnGroups) { - if (group.keyColumnIndex >= 0) { - KeyedGroup keyedGroup = new KeyedGroup(); - keyedGroup.keyCellIndex = columnModel.columns.get(group.keyColumnIndex).getCellIndex(); - keyedGroup.cellIndices = new int[group.columnSpan - 1]; - - int c = 0; - for (int i = 0; i < group.columnSpan; i++) { - int columnIndex = group.startColumnIndex + i; - if (columnIndex != group.keyColumnIndex && columnIndex < columnModel.columns.size()) { - int cellIndex = columnModel.columns.get(columnIndex).getCellIndex(); - keyedGroup.cellIndices[c++] = cellIndex; - } - } - - keyedGroups.add(keyedGroup); - } - } - - Collections.sort(keyedGroups, new Comparator() { - @Override - public int compare(KeyedGroup o1, KeyedGroup o2) { - return o2.cellIndices.length - o1.cellIndices.length; // larger groups first - } - }); - - dumpKeyedGroups(keyedGroups, columnModel); // for debug - - return keyedGroups; - } - - // debugging helper - private void dumpKeyedGroups(List groups, ColumnModel columnModel) { - for (KeyedGroup g : groups) { - String keyColName = columnModel.getColumnByCellIndex(g.keyCellIndex).getName(); - StringBuffer sb = new StringBuffer(); - for (int ci : g.cellIndices) { - Column col = columnModel.getColumnByCellIndex(ci); - if (col != null) { - // Old projects have col 0 slot empty - sb.append(col.getName()).append(','); - } - } - logger.trace("KeyedGroup " + keyColName + "::" + sb.toString()); - } - } - - protected void addRootKeyedGroup(ColumnModel columnModel, List keyedGroups) { - int count = columnModel.getMaxCellIndex() + 1; - if (count > 0 && columnModel.getKeyColumnIndex() < columnModel.columns.size()) { - KeyedGroup rootKeyedGroup = new KeyedGroup(); - - rootKeyedGroup.cellIndices = new int[count - 1]; - rootKeyedGroup.keyCellIndex = columnModel.columns.get(columnModel.getKeyColumnIndex()).getCellIndex(); - - for (int i = 0; i < count; i++) { - if (i < rootKeyedGroup.keyCellIndex) { - rootKeyedGroup.cellIndices[i] = i; - } else if (i > rootKeyedGroup.keyCellIndex) { - rootKeyedGroup.cellIndices[i - 1] = i; - } - } - keyedGroups.add(rootKeyedGroup); - } - } - - protected void setRowDependency( - Project project, - RowDependency rowDependency, - int cellIndex, - int contextRowIndex, - int contextCellIndex - ) { - if (rowDependency.cellDependencies == null) { - int count = project.columnModel.getMaxCellIndex() + 1; - - rowDependency.cellDependencies = new CellDependency[count]; - } - - rowDependency.cellDependencies[cellIndex] = - new CellDependency(contextRowIndex, contextCellIndex); - } - -} +/* + +Copyright 2010, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +package com.google.refine.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.refine.Jsonizable; +import com.google.refine.expr.ExpressionUtils; + +public class RecordModel implements Jsonizable { + final static Logger logger = LoggerFactory.getLogger("RecordModel"); + + final static public class CellDependency { + final public int rowIndex; + final public int cellIndex; + + public CellDependency(int rowIndex, int cellIndex) { + this.rowIndex = rowIndex; + this.cellIndex = cellIndex; + } + + @Override + public String toString() { + return rowIndex+","+cellIndex; + } + } + + final static public class RowDependency { + public int recordIndex; + public CellDependency[] cellDependencies; + public List contextRows; + + @Override + public String toString() { + return "Idx: "+recordIndex+" CellDeps: "+Arrays.toString(cellDependencies)+" Rows:"+contextRows; + } + } + + protected List _rowDependencies; + protected List _records; + + public RowDependency getRowDependency(int rowIndex) { + return _rowDependencies != null && rowIndex >= 0 && rowIndex < _rowDependencies.size() ? + _rowDependencies.get(rowIndex) : null; + } + + public int getRecordCount() { + return _records.size(); + } + + public Record getRecord(int recordIndex) { + return _records != null && recordIndex >= 0 && recordIndex < _records.size() ? + _records.get(recordIndex) : null; + } + + public Record getRecordOfRow(int rowIndex) { + RowDependency rd = getRowDependency(rowIndex); + if (rd != null) { + if (rd.recordIndex < 0) { + rd = getRowDependency(rd.contextRows.get(0)); + } + return getRecord(rd.recordIndex); + } + return null; + } + + @Override + synchronized public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("hasRecords"); + writer.value( + _records != null && _rowDependencies != null && + _records.size() < _rowDependencies.size()); + writer.endObject(); + } + + static protected class KeyedGroup { + int[] cellIndices; + int keyCellIndex; + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i:cellIndices) { + sb.append(i).append(','); + } + return "key: " + keyCellIndex + " cells: " + sb.toString(); + } + } + + synchronized public void update(Project project) { + synchronized (project) { + List rows = project.rows; + int rowCount = rows.size(); + + ColumnModel columnModel = project.columnModel; + List keyedGroups = computeKeyedGroups(columnModel); + int groupCount = keyedGroups.size(); + + int[] lastNonBlankRowsByGroup = new int[keyedGroups.size()]; + for (int i = 0; i < lastNonBlankRowsByGroup.length; i++) { + lastNonBlankRowsByGroup[i] = -1; + } + + _rowDependencies = new ArrayList(rowCount); + + int recordIndex = 0; + for (int r = 0; r < rowCount; r++) { + Row row = rows.get(r); + RowDependency rowDependency = new RowDependency(); + + for (int g = 0; g < groupCount; g++) { + KeyedGroup group = keyedGroups.get(g); + + if (!ExpressionUtils.isNonBlankData(row.getCellValue(keyedGroups.get(0).keyCellIndex)) && + !ExpressionUtils.isNonBlankData(row.getCellValue(group.keyCellIndex))) { + int contextRowIndex = lastNonBlankRowsByGroup[g]; + if (contextRowIndex >= 0) { + for (int dependentCellIndex : group.cellIndices) { + if (ExpressionUtils.isNonBlankData(row.getCellValue(dependentCellIndex))) { + setRowDependency( + project, + rowDependency, + dependentCellIndex, + contextRowIndex, + group.keyCellIndex + ); + } + } + } + } else { + lastNonBlankRowsByGroup[g] = r; + } + } + + if (rowDependency.cellDependencies != null && rowDependency.cellDependencies.length > 0) { + rowDependency.recordIndex = -1; + rowDependency.contextRows = new ArrayList(); + for (CellDependency cd : rowDependency.cellDependencies) { + if (cd != null) { + rowDependency.contextRows.add(cd.rowIndex); + } + } + Collections.sort(rowDependency.contextRows); + } else { + rowDependency.recordIndex = recordIndex++; + } + + _rowDependencies.add(rowDependency); + } + + _records = new ArrayList(recordIndex); + if (recordIndex > 0) { + recordIndex = 0; + + int recordRowIndex = 0; + for (int r = 1; r < rowCount; r++) { + RowDependency rd = _rowDependencies.get(r); + if (rd.recordIndex >= 0) { + _records.add(new Record(recordRowIndex, r, recordIndex++)); + + recordIndex = rd.recordIndex; + recordRowIndex = r; + } + } + + _records.add(new Record(recordRowIndex, rowCount, recordIndex++)); + } + } + } + + protected List computeKeyedGroups(ColumnModel columnModel) { + List keyedGroups = new ArrayList(); + + addRootKeyedGroup(columnModel, keyedGroups); + + for (ColumnGroup group : columnModel.columnGroups) { + if (group.keyColumnIndex >= 0) { + KeyedGroup keyedGroup = new KeyedGroup(); + keyedGroup.keyCellIndex = columnModel.columns.get(group.keyColumnIndex).getCellIndex(); + keyedGroup.cellIndices = new int[group.columnSpan - 1]; + + int c = 0; + for (int i = 0; i < group.columnSpan; i++) { + int columnIndex = group.startColumnIndex + i; + if (columnIndex != group.keyColumnIndex && columnIndex < columnModel.columns.size()) { + int cellIndex = columnModel.columns.get(columnIndex).getCellIndex(); + keyedGroup.cellIndices[c++] = cellIndex; + } + } + + keyedGroups.add(keyedGroup); + } + } + + Collections.sort(keyedGroups, new Comparator() { + @Override + public int compare(KeyedGroup o1, KeyedGroup o2) { + return o2.cellIndices.length - o1.cellIndices.length; // larger groups first + } + }); + + dumpKeyedGroups(keyedGroups, columnModel); // for debug + + return keyedGroups; + } + + // debugging helper + private void dumpKeyedGroups(List groups, ColumnModel columnModel) { + for (KeyedGroup g : groups) { + String keyColName = columnModel.getColumnByCellIndex(g.keyCellIndex).getName(); + StringBuffer sb = new StringBuffer(); + for (int ci : g.cellIndices) { + Column col = columnModel.getColumnByCellIndex(ci); + if (col != null) { + // Old projects have col 0 slot empty + sb.append(col.getName()).append(','); + } + } + logger.trace("KeyedGroup " + keyColName + "::" + sb.toString()); + } + } + + protected void addRootKeyedGroup(ColumnModel columnModel, List keyedGroups) { + int count = columnModel.getMaxCellIndex() + 1; + if (count > 0 && columnModel.getKeyColumnIndex() < columnModel.columns.size()) { + KeyedGroup rootKeyedGroup = new KeyedGroup(); + + rootKeyedGroup.cellIndices = new int[count - 1]; + rootKeyedGroup.keyCellIndex = columnModel.columns.get(columnModel.getKeyColumnIndex()).getCellIndex(); + + for (int i = 0; i < count; i++) { + if (i < rootKeyedGroup.keyCellIndex) { + rootKeyedGroup.cellIndices[i] = i; + } else if (i > rootKeyedGroup.keyCellIndex) { + rootKeyedGroup.cellIndices[i - 1] = i; + } + } + keyedGroups.add(rootKeyedGroup); + } + } + + protected void setRowDependency( + Project project, + RowDependency rowDependency, + int cellIndex, + int contextRowIndex, + int contextCellIndex + ) { + if (rowDependency.cellDependencies == null) { + int count = project.columnModel.getMaxCellIndex() + 1; + + rowDependency.cellDependencies = new CellDependency[count]; + } + + rowDependency.cellDependencies[cellIndex] = + new CellDependency(contextRowIndex, contextCellIndex); + } + +} diff --git a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java index f3a6afcee..752ba9f51 100644 --- a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java +++ b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java @@ -62,6 +62,21 @@ public class ColumnAdditionChange extends ColumnChange { newCells.toArray(_newCells); } + + public String getColumnName() { + return _columnName; + } + + + public int getColumnIndex() { + return _columnIndex; + } + + + public int getNewCellIndex() { + return _newCellIndex; + } + @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnMoveChange.java b/main/src/com/google/refine/model/changes/ColumnMoveChange.java index de394c8a5..817e3eb36 100644 --- a/main/src/com/google/refine/model/changes/ColumnMoveChange.java +++ b/main/src/com/google/refine/model/changes/ColumnMoveChange.java @@ -58,6 +58,18 @@ public class ColumnMoveChange extends ColumnChange { _newColumnIndex = index; } + public int getOldColumnIndex() { + return _oldColumnIndex; + } + + public String getColumnName() { + return _columnName; + } + + public int getNewColumnIndex() { + return _newColumnIndex; + } + @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java index 70a2b0636..c7ecc1f92 100644 --- a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java +++ b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java @@ -54,11 +54,15 @@ public class ColumnRemovalChange extends ColumnChange { protected Column _oldColumn; protected CellAtRow[] _oldCells; protected List _oldColumnGroups; - + public ColumnRemovalChange(int index) { _oldColumnIndex = index; } + public int getOldColumnIndex() { + return _oldColumnIndex; + } + @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnReorderChange.java b/main/src/com/google/refine/model/changes/ColumnReorderChange.java index bdf714998..e29d01ade 100644 --- a/main/src/com/google/refine/model/changes/ColumnReorderChange.java +++ b/main/src/com/google/refine/model/changes/ColumnReorderChange.java @@ -57,6 +57,11 @@ public class ColumnReorderChange extends ColumnChange { _columnNames = columnNames; } + + public List getColumnNames() { + return _columnNames; + } + @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/changes/ColumnSplitChange.java b/main/src/com/google/refine/model/changes/ColumnSplitChange.java index bb49a4c4a..adf50cc64 100644 --- a/main/src/com/google/refine/model/changes/ColumnSplitChange.java +++ b/main/src/com/google/refine/model/changes/ColumnSplitChange.java @@ -54,7 +54,7 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; -public class ColumnSplitChange implements Change { +public class ColumnSplitChange extends ColumnChange { final protected String _columnName; final protected List _columnNames; @@ -118,6 +118,21 @@ public class ColumnSplitChange implements Change { _newRows = newRows; } + + public List getColumnNames() { + return _columnNames; + } + + + public boolean isRemoveOriginalColumn() { + return _removeOriginalColumn; + } + + + public int getColumnIndex() { + return _columnIndex; + } + @Override public void apply(Project project) { synchronized (project) { diff --git a/main/src/com/google/refine/model/medadata/AbstractMetadata.java b/main/src/com/google/refine/model/medadata/AbstractMetadata.java new file mode 100644 index 000000000..8ae7c3041 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/AbstractMetadata.java @@ -0,0 +1,73 @@ +package com.google.refine.model.medadata; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.Properties; + +import org.apache.commons.beanutils.PropertyUtils; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +public abstract class AbstractMetadata implements IMetadata { + private MetadataFormat formatName = MetadataFormat.UNKNOWN; + + protected LocalDateTime written = null; + protected LocalDateTime _modified; + + public MetadataFormat getFormatName() { + return formatName; + } + + + public void setFormatName(MetadataFormat formatName) { + this.formatName = formatName; + } + + @Override + public abstract void loadFromJSON(JSONObject obj); + + @Override + public abstract void loadFromFile(File metadataFile); + + @Override + public abstract void writeToFile(File metadataFile); + + @Override + public boolean isDirty() { + return written == null || _modified.isAfter(written); + } + + @Override + public LocalDateTime getModified() { + return _modified; + } + + @Override + public void updateModified() { + _modified = LocalDateTime.now(); + } + + /** + * @param jsonWriter + * writer to save metadatea to + * @param onlyIfDirty + * true to not write unchanged metadata + * @throws JSONException + */ + @Override + public void write(JSONWriter jsonWriter, boolean onlyIfDirty) throws JSONException { + if (!onlyIfDirty || isDirty()) { + Properties options = new Properties(); + options.setProperty("mode", "save"); + + write(jsonWriter, options); + } + } + + protected static boolean propertyExists(Object bean, String property) { + return PropertyUtils.isReadable(bean, property) && + PropertyUtils.isWriteable(bean, property); + } + +} diff --git a/main/src/com/google/refine/model/medadata/DataPackageMetadata.java b/main/src/com/google/refine/model/medadata/DataPackageMetadata.java new file mode 100644 index 000000000..ba7b27118 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/DataPackageMetadata.java @@ -0,0 +1,130 @@ +package com.google.refine.model.medadata; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.everit.json.schema.ValidationException; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.frictionlessdata.datapackage.Package; +import io.frictionlessdata.datapackage.Resource; +import io.frictionlessdata.datapackage.exceptions.DataPackageException; + + +public class DataPackageMetadata extends AbstractMetadata { + private final static Logger logger = LoggerFactory.getLogger(DataPackageMetadata.class); + + public static final String DEFAULT_FILE_NAME = "datapackage.json"; + + private Package _pkg; + + public DataPackageMetadata() { + setFormatName(MetadataFormat.DATAPACKAGE_METADATA); + + _pkg = PackageExtension.buildPackageFromTemplate(); + } + + @Override + public void loadFromJSON(JSONObject obj) { + try { + _pkg = new Package(obj); + } catch (ValidationException | DataPackageException | IOException e) { + logger.error("Load from JSONObject failed" + obj.toString(4), + ExceptionUtils.getStackTrace(e)); + } + + logger.info("Data Package metadata loaded"); + } + + @Override + public void loadFromFile(File metadataFile) { + String jsonString = null; + try { + jsonString = FileUtils.readFileToString(metadataFile); + } catch (IOException e) { + logger.error("Load data package failed when reading from file: " + metadataFile.getAbsolutePath(), + ExceptionUtils.getStackTrace(e)); + } + + loadFromJSON(new JSONObject(jsonString)); + } + + /** + * Write the package to a json file. + */ + @Override + public void writeToFile(File metadataFile) { + try { + this._pkg.save(metadataFile.getAbsolutePath()); + } catch (IOException e) { + logger.error("IO exception when writing to file " + metadataFile.getAbsolutePath(), + ExceptionUtils.getStackTrace(e)); + } catch (DataPackageException e) { + logger.error("Data package exception when writing to file " + metadataFile.getAbsolutePath(), + ExceptionUtils.getStackTrace(e)); + } + } + + @Override + public void write(JSONWriter jsonWriter, Properties options) + throws JSONException { + StringWriter sw = new StringWriter(); + _pkg.getJson().write(sw); + jsonWriter = new JSONWriter(sw); + } + + @Override + public void loadFromStream(InputStream inputStream) { + try { + this._pkg = new Package(IOUtils.toString(inputStream)); + } catch (ValidationException e) { + logger.error("validation failed", ExceptionUtils.getStackTrace(e)); + } catch (DataPackageException e) { + logger.error("Data package excpetion when loading from stream", ExceptionUtils.getStackTrace(e)); + } catch (IOException e) { + logger.error("IO exception when loading from stream", ExceptionUtils.getStackTrace(e)); + } + } + + public List getResourcePaths() { + List listResources = new ArrayList(); + + for (Resource resource : _pkg.getResources()) { + listResources.add((String) resource.getPath()); + } + + return listResources; + } + + @Override + public JSONObject getJSON() { + return _pkg.getJson(); + } + + public Package getPackage() { + return _pkg; + } + + @Override + public List validate() { + try { + _pkg.validate(); + } catch (ValidationException | IOException | DataPackageException e) { + logger.error("validate json failed", ExceptionUtils.getStackTrace(e)); + } + + return _pkg.getErrors(); + } +} diff --git a/main/src/com/google/refine/model/medadata/DataPackageUrlRewriter.java b/main/src/com/google/refine/model/medadata/DataPackageUrlRewriter.java new file mode 100644 index 000000000..eefe1313c --- /dev/null +++ b/main/src/com/google/refine/model/medadata/DataPackageUrlRewriter.java @@ -0,0 +1,44 @@ +package com.google.refine.model.medadata; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import com.google.refine.importing.UrlRewriter; + + +public class DataPackageUrlRewriter implements UrlRewriter { + @Override + public List rewrite(String url) throws MalformedURLException, IOException { + List listResult = new ArrayList(); + + if (!filter(url)) + return listResult; + + listResult.add(new Result(url, "json", true, MetadataFormat.DATAPACKAGE_METADATA.name())); + + DataPackageMetadata meta = new DataPackageMetadata(); + meta.loadFromStream(new URL(url).openStream()); + // Import the data files. + for (String path : meta.getResourcePaths()) { + String fileURL = getBaseURL(url) + "/" + path; + listResult.add(new Result(fileURL, + "", // leave to guesser. "text/line-based/*sv" + true)); + } + + return listResult; + } + + @Override + public boolean filter(String url) { + return url.endsWith(DataPackageMetadata.DEFAULT_FILE_NAME); + } + + private String getBaseURL(String url) { + return url.replaceFirst(DataPackageMetadata.DEFAULT_FILE_NAME, ""); + } + +} diff --git a/main/src/com/google/refine/model/medadata/IMetadata.java b/main/src/com/google/refine/model/medadata/IMetadata.java new file mode 100644 index 000000000..1c759de5c --- /dev/null +++ b/main/src/com/google/refine/model/medadata/IMetadata.java @@ -0,0 +1,44 @@ +package com.google.refine.model.medadata; + +import java.io.File; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.util.List; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.google.refine.Jsonizable; +/** + * Interface to import/export metadata + */ +public interface IMetadata extends Jsonizable { + public void loadFromJSON(JSONObject obj); + + public void loadFromFile(File metadataFile); + + public void loadFromStream(InputStream inputStream); + + public void writeToFile(File metadataFile); + + /** + * @param jsonWriter writer to save metadatea to + * @param onlyIfDirty true to not write unchanged metadata + * @throws JSONException + */ + public void write(JSONWriter jsonWriter, boolean onlyIfDirty); + + public MetadataFormat getFormatName(); + public void setFormatName(MetadataFormat format); + + public LocalDateTime getModified(); + + public void updateModified(); + + public boolean isDirty(); + + public JSONObject getJSON(); + + public List validate(); +} diff --git a/main/src/com/google/refine/model/medadata/MetadataFactory.java b/main/src/com/google/refine/model/medadata/MetadataFactory.java new file mode 100644 index 000000000..500b69148 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/MetadataFactory.java @@ -0,0 +1,82 @@ +package com.google.refine.model.medadata; + +import java.io.IOException; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.everit.json.schema.ValidationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.refine.model.Project; +import com.google.refine.util.JSONUtilities; +import com.google.refine.util.ParsingUtilities; + +import io.frictionlessdata.datapackage.Package; +import io.frictionlessdata.datapackage.Resource; +import io.frictionlessdata.datapackage.exceptions.DataPackageException; + +public class MetadataFactory { + private final static Logger logger = LoggerFactory.getLogger(MetadataFactory.class); + + /** + * Build metadata based on the format + * @param format + * @return + */ + public static IMetadata buildMetadata(MetadataFormat format) { + IMetadata metadata = null; + if (format == MetadataFormat.PROJECT_METADATA) { + metadata = new ProjectMetadata(); + } else if (format == MetadataFormat.DATAPACKAGE_METADATA) { + metadata = new DataPackageMetadata(); + } + + return metadata; + } + + /** + * build an empty Data Package Metadata + * @return + */ + public static DataPackageMetadata buildDataPackageMetadata() { + return (DataPackageMetadata) buildMetadata(MetadataFormat.DATAPACKAGE_METADATA); + } + + /** + * Build an empty data package metadata, then populate the fields from the Project Metadata + * @param project + * @return + */ + public static DataPackageMetadata buildDataPackageMetadata(Project project) { + DataPackageMetadata dpm = buildDataPackageMetadata(); + ProjectMetadata pmd = project.getMetadata(); + Package pkg = dpm.getPackage(); + Resource resource = SchemaExtension.createResource(project.getMetadata().getName(), + project.columnModel); + try { + pkg.addResource(resource); + + putValue(pkg, Package.JSON_KEY_NAME, pmd.getName()); + putValue(pkg, PackageExtension.JSON_KEY_LAST_UPDATED, ParsingUtilities.localDateToString(pmd.getModified())); + putValue(pkg, PackageExtension.JSON_KEY_DESCRIPTION, pmd.getDescription()); + putValue(pkg, PackageExtension.JSON_KEY_TITLE, pmd.getTitle()); + putValue(pkg, PackageExtension.JSON_KEY_HOMEPAGE, pmd.getHomepage()); + putValue(pkg, PackageExtension.JSON_KEY_IMAGE, pmd.getImage()); + putValue(pkg, PackageExtension.JSON_KEY_LICENSE, pmd.getLicense()); + + pkg.removeProperty(PackageExtension.JSON_KEY_KEYWORKS); + pkg.addProperty(PackageExtension.JSON_KEY_KEYWORKS, JSONUtilities.arrayToJSONArray(pmd.getTags())); + } catch (ValidationException | IOException | DataPackageException e) { + logger.error(ExceptionUtils.getStackTrace(e)); + } + + return dpm; + } + + private static void putValue(Package pkg, String key, String value) throws DataPackageException { + if(pkg.getJson().has(key)) { + pkg.removeProperty(key); + } + pkg.addProperty(key, value); + } +} diff --git a/main/src/com/google/refine/model/medadata/MetadataFormat.java b/main/src/com/google/refine/model/medadata/MetadataFormat.java new file mode 100644 index 000000000..e6db73d9c --- /dev/null +++ b/main/src/com/google/refine/model/medadata/MetadataFormat.java @@ -0,0 +1,24 @@ +package com.google.refine.model.medadata; + + +/** + * A list of supported metadata format + * + */ +public enum MetadataFormat { + UNKNOWN("UNKNOWN"), + PROJECT_METADATA("PROJECT_METADATA"), + DATAPACKAGE_METADATA("DATAPACKAGE_METADATA"), + CSVW_METADATA("CSVW_METADATA"); + + private final String format; + + private MetadataFormat(final String format) { + this.format = format; + } + + @Override + public String toString() { + return format; + } +} diff --git a/main/src/com/google/refine/model/medadata/PackageExtension.java b/main/src/com/google/refine/model/medadata/PackageExtension.java new file mode 100644 index 000000000..1d8da5cc8 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/PackageExtension.java @@ -0,0 +1,88 @@ +package com.google.refine.model.medadata; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang3.StringUtils; +import org.everit.json.schema.ValidationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.frictionlessdata.datapackage.Package; +import io.frictionlessdata.datapackage.exceptions.DataPackageException; + +/** + * This class contains some methods which is not included in the official "Data Package" repo for now. + * Some methods can be removed after the official library provide the corresponding function. + */ +public class PackageExtension { + private final static Logger logger = LoggerFactory.getLogger(PackageExtension.class); + + private static final int JSON_INDENT_FACTOR = 4; + + public static final String JSON_KEY_LAST_UPDATED = "last_updated"; + public static final String JSON_KEY_DESCRIPTION = "description"; + public static final String JSON_KEY_KEYWORKS = "keywords"; + public static final String JSON_KEY_TITLE = "title"; + public static final String JSON_KEY_HOMEPAGE = "homepage"; + public static final String JSON_KEY_IMAGE = "image"; + public static final String JSON_KEY_LICENSE = "license"; + public static final String JSON_KEY_VERSION = "version"; + + public static String DATAPACKAGE_TEMPLATE_FILE = "schemas/datapackage-template.json"; + + /** + * Do the package since the final spec for the compression/bundle are not settled yet. + * https://github.com/frictionlessdata/datapackage-js/issues/93 + * + * @param pkg Package + * @param dataByteArrayOutputStream ByteArrayOutputStream + * @param destOs OutputStream + * @throws IOException + * @throws FileNotFoundException + * @see Package#saveZip(String outputFilePath) + */ + public static void saveZip(Package pkg, final ByteArrayOutputStream dataByteArrayOutputStream, final OutputStream destOs) throws FileNotFoundException, IOException { + try(ZipOutputStream zos = new ZipOutputStream(destOs)){ + // json file + ZipEntry entry = new ZipEntry(DataPackageMetadata.DEFAULT_FILE_NAME); + zos.putNextEntry(entry); + zos.write(pkg.getJson().toString(JSON_INDENT_FACTOR).getBytes()); + zos.closeEntry(); + // default data file to data.csv or given path(can only handle one file because files cannot be restored) + String path = (String) pkg.getResources().get(0).getPath(); + entry = new ZipEntry(StringUtils.isBlank(path) ? "data.csv" : path); + zos.putNextEntry(entry); + zos.write(dataByteArrayOutputStream.toByteArray()); + zos.closeEntry(); + } + } + + /** + * To build a Package object from a template file contains empty metadata + * + * @param templateFile + */ + public static Package buildPackageFromTemplate() { + try { + ClassLoader classLoader = PackageExtension.class.getClassLoader(); + File file = new File(classLoader.getResource(DATAPACKAGE_TEMPLATE_FILE).getFile()); + return new Package(FileUtils.readFileToString(file), false); + } catch (ValidationException e) { + logger.error("validation failed", ExceptionUtils.getStackTrace(e)); + } catch (DataPackageException e) { + logger.error("DataPackage Exception", ExceptionUtils.getStackTrace(e)); + } catch (IOException e) { + logger.error("IOException when build package from template", ExceptionUtils.getStackTrace(e)); + } + + return null; + } +} diff --git a/main/src/com/google/refine/ProjectMetadata.java b/main/src/com/google/refine/model/medadata/ProjectMetadata.java similarity index 59% rename from main/src/com/google/refine/ProjectMetadata.java rename to main/src/com/google/refine/model/medadata/ProjectMetadata.java index ba7997c54..eda957211 100644 --- a/main/src/com/google/refine/ProjectMetadata.java +++ b/main/src/com/google/refine/model/medadata/ProjectMetadata.java @@ -31,10 +31,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.google.refine; +package com.google.refine.model.medadata; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.io.Serializable; -import java.lang.reflect.Field; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.InvocationTargetException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; @@ -43,49 +52,64 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.json.JSONTokener; import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.refine.ProjectManager; import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; import com.google.refine.util.JSONUtilities; import com.google.refine.util.ParsingUtilities; -public class ProjectMetadata implements Jsonizable { +public class ProjectMetadata extends AbstractMetadata { + final public static String DEFAULT_FILE_NAME = "metadata.json"; + final public static String TEMP_FILE_NAME = "metadata.temp.json"; + final public static String OLD_FILE_NAME = "metadata.old.json"; + private final LocalDateTime _created; - private LocalDateTime _modified; - private LocalDateTime written = null; private String _name = ""; private String _password = ""; private String _encoding = ""; private int _encodingConfidence; - + private int _rowCount; + // user metadata + private JSONArray _userMetadata = new JSONArray();; + + // _tags maps to keywords of the data package metadata private String[] _tags = new String[0]; - private String _creator = ""; private String _contributors = ""; - private String _subject = ""; // Several refine projects may be linked - private String _description = ""; // free form of comment - private int _rowCount; // at the creation. Essential for cleaning old projects too heavy - + private String _subject = ""; // Several refine projects may be linked + private String _description = ""; // free form of comment + // import options is an array for 1-n data sources private JSONArray _importOptionMetadata = new JSONArray(); - - // user metadata - private JSONArray _userMetadata = new JSONArray(); + private Map _customMetadata = new HashMap(); private PreferenceStore _preferenceStore = new PreferenceStore(); + + // below 5 fields are from data package metadata: + private String title = ""; + private String homepage; + private String image = ""; + private String license = ""; + private String version = ""; private final static Logger logger = LoggerFactory.getLogger("project_metadata"); protected ProjectMetadata(LocalDateTime date) { + setFormatName(MetadataFormat.PROJECT_METADATA); _created = date; preparePreferenceStore(_preferenceStore); } @@ -100,7 +124,12 @@ public class ProjectMetadata implements Jsonizable { _modified = modified; _name = name; } - + + public void setRowCount(int rowCount) { + this._rowCount = rowCount; + updateModified(); + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -116,16 +145,16 @@ public class ProjectMetadata implements Jsonizable { writer.endArray(); writer.key("created"); writer.value(ParsingUtilities.localDateToString(_created)); writer.key("modified"); writer.value(ParsingUtilities.localDateToString(_modified)); - writer.key("creator"); - writer.value(_creator); - writer.key("contributors"); - writer.value(_contributors); - writer.key("subject"); - writer.value(_subject); - writer.key("description"); - writer.value(_description); - writer.key("rowCount"); - writer.value(_rowCount); + writer.key("creator"); writer.value(_creator); + writer.key("contributors"); writer.value(_contributors); + writer.key("subject"); writer.value(_subject); + writer.key("description"); writer.value(_description); + writer.key("rowCount"); writer.value(_rowCount); + writer.key("title"); writer.value(title); + writer.key("homepage"); writer.value(homepage); + writer.key("image"); writer.value(image); + writer.key("license"); writer.value(license); + writer.key("version"); writer.value(version); writer.key("customMetadata"); writer.object(); @@ -178,64 +207,47 @@ public class ProjectMetadata implements Jsonizable { return "save".equals(options.getProperty("mode")); } - public boolean isDirty() { - return written == null || _modified.isAfter(written); - } - public void write(JSONWriter jsonWriter) throws JSONException { write(jsonWriter, false); } - /** - * @param jsonWriter - * writer to save metadatea to - * @param onlyIfDirty - * true to not write unchanged metadata - * @throws JSONException - */ - public void write(JSONWriter jsonWriter, boolean onlyIfDirty) - throws JSONException { - if (!onlyIfDirty || isDirty()) { - Properties options = new Properties(); - options.setProperty("mode", "save"); + public void loadFromJSON(JSONObject obj) { + extractModifiedLocalTime(obj); - write(jsonWriter, options); - } - } + this._name = JSONUtilities.getString(obj, "name", ""); + this._password = JSONUtilities.getString(obj, "password", ""); - static public ProjectMetadata loadFromJSON(JSONObject obj) { - // TODO: Is this correct? It's using modified date for creation date - ProjectMetadata pm = new ProjectMetadata(JSONUtilities.getLocalDate(obj, "modified", LocalDateTime.now())); + this._encoding = JSONUtilities.getString(obj, "encoding", ""); + this._encodingConfidence = JSONUtilities.getInt(obj, "encodingConfidence", 0); - pm._modified = JSONUtilities.getLocalDate(obj, "modified", LocalDateTime.now()); - pm._name = JSONUtilities.getString(obj, "name", ""); - pm._password = JSONUtilities.getString(obj, "password", ""); + this._creator = JSONUtilities.getString(obj, "creator", ""); + this._contributors = JSONUtilities.getString(obj, "contributors", ""); + this._subject = JSONUtilities.getString(obj, "subject", ""); + this._description = JSONUtilities.getString(obj, "description", ""); + this._rowCount = JSONUtilities.getInt(obj, "rowCount", 0); + + this.title = JSONUtilities.getString(obj, "title", ""); + this.homepage = JSONUtilities.getString(obj, "homepage", ""); + this.image = JSONUtilities.getString(obj, "image", ""); + this.license = JSONUtilities.getString(obj, "license", ""); + this.version = JSONUtilities.getString(obj, "version", ""); - pm._encoding = JSONUtilities.getString(obj, "encoding", ""); - pm._encodingConfidence = JSONUtilities.getInt(obj, "encodingConfidence", 0); - - pm._creator = JSONUtilities.getString(obj, "creator", ""); - pm._contributors = JSONUtilities.getString(obj, "contributors", ""); - pm._subject = JSONUtilities.getString(obj, "subject", ""); - pm._description = JSONUtilities.getString(obj, "description", ""); - pm._rowCount = JSONUtilities.getInt(obj, "rowCount", 0); - - pm._tags = JSONUtilities.getStringArray(obj, "tags"); + this._tags = JSONUtilities.getStringArray(obj, "tags"); if (obj.has("preferences") && !obj.isNull("preferences")) { try { - pm._preferenceStore.load(obj.getJSONObject("preferences")); + this._preferenceStore.load(obj.getJSONObject("preferences")); } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility try { - ((TopList) pm._preferenceStore.get("scripting.expressions")).load(obj.getJSONArray("expressions")); + ((TopList) this._preferenceStore.get("scripting.expressions")).load(obj.getJSONArray("expressions")); } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } @@ -243,41 +255,48 @@ public class ProjectMetadata implements Jsonizable { try { JSONObject obj2 = obj.getJSONObject("customMetadata"); - @SuppressWarnings("unchecked") Iterator keys = obj2.keys(); while (keys.hasNext()) { String key = keys.next(); Object value = obj2.get(key); if (value != null && value instanceof Serializable) { - pm._customMetadata.put(key, (Serializable) value); + this._customMetadata.put(key, (Serializable) value); } } } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } if (obj.has("importOptionMetadata") && !obj.isNull("importOptionMetadata")) { try { JSONArray jsonArray = obj.getJSONArray("importOptionMetadata"); - pm._importOptionMetadata = jsonArray; + this._importOptionMetadata = jsonArray; } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } if (obj.has(PreferenceStore.USER_METADATA_KEY) && !obj.isNull(PreferenceStore.USER_METADATA_KEY)) { try { JSONArray jsonArray = obj.getJSONArray(PreferenceStore.USER_METADATA_KEY); - pm._userMetadata = jsonArray; + this._userMetadata = jsonArray; } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } - pm.written = LocalDateTime.now(); // Mark it as not needing writing until modified + this.written = LocalDateTime.now(); // Mark it as not needing writing until modified - return pm; + } + + private void extractModifiedLocalTime(JSONObject obj) { + String modified = JSONUtilities.getString(obj, "modified", LocalDateTime.now().toString()); + if (modified.endsWith("Z")) { + this._modified = ParsingUtilities.stringToDate(modified).toLocalDateTime(); + } else { + this._modified = ParsingUtilities.stringToLocalDate(modified); + } } static protected void preparePreferenceStore(PreferenceStore ps) { @@ -288,25 +307,7 @@ public class ProjectMetadata implements Jsonizable { public LocalDateTime getCreated() { return _created; } - - public void setName(String name) { - this._name = name; - updateModified(); - } - - public String getName() { - return _name; - } - - public void setEncoding(String encoding) { - this._encoding = encoding; - updateModified(); - } - - public String getEncoding() { - return _encoding; - } - + public void setEncodingConfidence(int confidence) { this._encodingConfidence = confidence; updateModified(); @@ -342,6 +343,11 @@ public class ProjectMetadata implements Jsonizable { updateModified(); } + public void appendTags(String[] tags) { + String[] mergedTags = (String[])ArrayUtils.addAll(this._tags, tags); + setTags(mergedTags); + } + public String[] getTags() { if (_tags == null) this._tags = new String[0]; return _tags; @@ -380,21 +386,39 @@ public class ProjectMetadata implements Jsonizable { } updateModified(); } - + public JSONArray getImportOptionMetadata() { return _importOptionMetadata; } - + public void setImportOptionMetadata(JSONArray jsonArray) { _importOptionMetadata = jsonArray; updateModified(); } - + public void appendImportOptionMetadata(JSONObject obj) { _importOptionMetadata.put(obj); updateModified(); } + + public String getEncoding() { + return _encoding; + } + public void setName(String name) { + this._name = name; + updateModified(); + } + + public String getName() { + return _name; + } + + public void setEncoding(String encoding) { + this._encoding = encoding; + updateModified(); + } + public String getCreator() { return _creator; } @@ -404,6 +428,7 @@ public class ProjectMetadata implements Jsonizable { updateModified(); } + public String getContributors() { return _contributors; } @@ -413,6 +438,7 @@ public class ProjectMetadata implements Jsonizable { updateModified(); } + public String getSubject() { return _subject; } @@ -421,7 +447,7 @@ public class ProjectMetadata implements Jsonizable { this._subject = subject; updateModified(); } - + public String getDescription() { return _description; } @@ -430,25 +456,70 @@ public class ProjectMetadata implements Jsonizable { this._description = description; updateModified(); } - - public int getRowCount() { - return _rowCount; + + + public String getTitle() { + return title; } - public void setRowCount(int rowCount) { - this._rowCount = rowCount; + + public void setTitle(String title) { + this.title = title; updateModified(); } + + public String getHomepage() { + return homepage; + } + + + public void setHomepage(String homepage) { + this.homepage = homepage; + updateModified(); + } + + + public String getImage() { + return image; + } + + + public void setImage(String image) { + this.image = image; + updateModified(); + } + + + public String getLicense() { + return license; + } + + + public void setLicense(String license) { + this.license = license; + updateModified(); + } + + public String getVersion() { + return version; + } + + + public void setVersion(String version) { + this.version = version; + updateModified(); + } + public JSONArray getUserMetadata() { return _userMetadata; } - + public void setUserMetadata(JSONArray userMetadata) { this._userMetadata = userMetadata; } - - private void updateUserMetadata(String metaName, String valueString) { + + private void updateUserMetadata(String metaName, String valueString) { for (int i = 0; i < _userMetadata.length(); i++) { try { JSONObject obj = _userMetadata.getJSONObject(i); @@ -456,25 +527,80 @@ public class ProjectMetadata implements Jsonizable { obj.put("value", valueString); } } catch (JSONException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + logger.error(ExceptionUtils.getStackTrace(e)); } } } - - public void setAnyField(String metaName, String valueString) { - Class metaClass = this.getClass(); - try { - Field metaField = metaClass.getDeclaredField("_" + metaName); - if (metaName.equals("tags")) { - metaField.set(this, valueString.split(",")); - } else { - metaField.set(this, valueString); + + public void setAnyStringField(String metaName, String valueString) { + if (propertyExists(this, metaName)) { + try { + if (metaName.equals("tags")) { + BeanUtils.setProperty(this, metaName, valueString.split(",")); + } else + BeanUtils.setProperty(this, metaName, valueString); + } catch (IllegalAccessException | InvocationTargetException ite) { + logger.error(ExceptionUtils.getStackTrace(ite)); } - } catch (NoSuchFieldException e) { + } else { updateUserMetadata(metaName, valueString); - } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { - logger.error(ExceptionUtils.getFullStackTrace(e)); + } + } + + @Override + public void loadFromFile(File metadataFile) { + InputStream targetStream = null; + try { + targetStream = FileUtils.openInputStream(metadataFile); + } catch (IOException e) { + logger.error(ExceptionUtils.getStackTrace(e)); + } + loadFromStream(targetStream); + } + + @Override + public void writeToFile(File metadataFile) { + Writer writer = null; + try { + writer = new OutputStreamWriter(new FileOutputStream(metadataFile)); + + JSONWriter jsonWriter = new JSONWriter(writer); + write(jsonWriter, false); + } catch (FileNotFoundException e) { + logger.error(ExceptionUtils.getStackTrace(e)); + } finally { + try { + writer.close(); + } catch (IOException e) { + logger.error(ExceptionUtils.getStackTrace(e)); + } } } + @Override + public void loadFromStream(InputStream inputStream) { + try (InputStreamReader reader = new InputStreamReader(inputStream)) { + JSONTokener tokener = new JSONTokener(reader); + JSONObject obj = (JSONObject) tokener.nextValue(); + + this.loadFromJSON(obj); + } catch (IOException e) { + logger.error(ExceptionUtils.getStackTrace(e)); + } + } + + @Override + public JSONObject getJSON() { + StringWriter writer = new StringWriter(); + JSONWriter jsonWriter = new JSONWriter(writer); + writeWithoutOption(jsonWriter); + + return new JSONObject(jsonWriter.toString()); + } + + @Override + public List validate() { + return null; + } + } diff --git a/main/src/com/google/refine/model/medadata/SchemaExtension.java b/main/src/com/google/refine/model/medadata/SchemaExtension.java new file mode 100644 index 000000000..8c3afd6bc --- /dev/null +++ b/main/src/com/google/refine/model/medadata/SchemaExtension.java @@ -0,0 +1,64 @@ +package com.google.refine.model.medadata; + +import com.google.refine.model.Column; +import com.google.refine.model.ColumnModel; + +import io.frictionlessdata.datapackage.Resource; +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.Schema; + +/** + * This class contains some methods which is not included in the official "table schema" repo for now. + * Some methods can be removed after the official library provide the corresponding function. + */ +public class SchemaExtension { + private static final String DEFAULT_RESOURCE_PATH = "data/"; + private static final String DEFAULT_RESOURCE_SUFFIX = ".csv"; + + /** + * insert the field to schema at specified position + * @param schema + * @param field + * @param position + */ + public static void insertField(Schema schema, Field field, int position) { + schema.getFields().add(position, field); + } + + /** + * Remove the filed from the schema at specified position + * @param schema + * @param index + * @return + */ + public static Field removeField(Schema schema, int index) { + return schema.getFields().remove(index); + } + + /** + * Create a resource by name, get the schema information from the ColumnModel + * @param resourceName + * @param columnModel + * @return + * @see ColumnModel + */ + public static Resource createResource(String resourceName, ColumnModel columnModel) { + // populate the data package schema from the openrefine column model + Schema schema = new Schema(); + for (Column column : columnModel.columns) { + schema.addField(new Field(column.getName(), + column.getType(), + column.getFormat(), + column.getTitle(), + column.getDescription(), + column.getConstraints())); + } + + Resource resource = new Resource(resourceName, + DEFAULT_RESOURCE_PATH + resourceName + DEFAULT_RESOURCE_SUFFIX, + schema.getJson()); + + return resource; + } + +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidateOperation.java b/main/src/com/google/refine/model/medadata/validator/ValidateOperation.java new file mode 100644 index 000000000..a7bbdcb55 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidateOperation.java @@ -0,0 +1,32 @@ +package com.google.refine.model.medadata.validator; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.google.refine.model.AbstractOperation; +import com.google.refine.model.Project; + +public class ValidateOperation extends AbstractOperation { + private Project project; + private JSONObject options; + + public ValidateOperation(Project project, JSONObject options) { + this.project = project; + this.options = options; + } + + public JSONObject startProcess() { + return ValidatorInspector.inspect(project, options); + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + // TODO Auto-generated method stub + + } + +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidatorConfig.java b/main/src/com/google/refine/model/medadata/validator/ValidatorConfig.java new file mode 100644 index 000000000..7b5642aa1 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidatorConfig.java @@ -0,0 +1,6 @@ +package com.google.refine.model.medadata.validator; + + +public class ValidatorConfig { + +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidatorExceptions.java b/main/src/com/google/refine/model/medadata/validator/ValidatorExceptions.java new file mode 100644 index 000000000..c4cf5ea27 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidatorExceptions.java @@ -0,0 +1,6 @@ +package com.google.refine.model.medadata.validator; + + +public class ValidatorExceptions { + +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidatorInspector.java b/main/src/com/google/refine/model/medadata/validator/ValidatorInspector.java new file mode 100644 index 000000000..ca7972cc8 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidatorInspector.java @@ -0,0 +1,102 @@ +package com.google.refine.model.medadata.validator; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.refine.model.Column; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.validator.checks.TypeorFormatError; +import com.google.refine.model.medadata.validator.checks.Validator; +import com.google.refine.util.JSONUtilities; + +public class ValidatorInspector { + private final static Logger logger = LoggerFactory.getLogger(ValidatorInspector.class); + + /** + * Return a report contains the validate result + * @param project + * @param options + * @return + */ + public static JSONObject inspect(Project project, JSONObject options) { + List columnNames; + String COLUMN_NAMES_KEY = "columnNames"; + Map> columnToCheckersMap = new HashMap>(); + JSONArray validateReport = new JSONArray(); + + logger.info("starting inspect with options:" + options.toString()); + columnNames = JSONUtilities.toStringList(options.getJSONArray(COLUMN_NAMES_KEY)); + + // build the check items + List validatorList = null; + for(String columnName : columnNames) { + validatorList = compileChecks(project, columnName, options); + if (validatorList.size() >= 0) + columnToCheckersMap.put(columnName, validatorList); + } + logger.info("=========================================================="); + logger.info("Inspector finished the checks compile. will do following check:"); + for (Entry> entry : columnToCheckersMap.entrySet()) { + logger.info("Column Name: " + entry.getKey()); + for (Validator v : entry.getValue()) { + logger.info("\t Validator: " + v.getClass().getSimpleName()); + } + } + logger.info("=========================================================="); + + // do the inspect in another loop: + for(String columnName : columnNames) { + List validators = columnToCheckersMap.get(columnName); + if (validators != null) { + for (Validator validator : validators) { + JSONArray result = validator.validate(); + if (result != null && result.length() > 0) + JSONUtilities.concatArray(validateReport, result); + } + } + } + logger.info("Inspector finished the validation."); + + return new JSONObject().put("validation-reports", (Object)validateReport); + } + + private static List compileChecks(Project project, String columnName, JSONObject options) { + Map constraintHandlersMap = ValidatorRegistry.getInstance().getConstraintHandlersMap(); + + Column column = project.columnModel.getColumnByName(columnName); + List validatorList = new ArrayList(); + + int columnIndex = project.columnModel.getColumnIndexByName(columnName); + + validatorList.add(new TypeorFormatError(project, columnIndex, options)); + + + if (column.getConstraints() != null) { + for (Entry entry : column.getConstraints().entrySet()) { + Class clazz = constraintHandlersMap.get(entry.getKey()); + try { + Constructor c = clazz.getConstructor(Project.class, int.class, JSONObject.class); + validatorList.add(c.newInstance(project, columnIndex, options)); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + logger.error("failed to do compileChecks:" + ExceptionUtils.getStackTrace(e)); + } + } + } + + return validatorList; + } + + +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidatorRegistry.java b/main/src/com/google/refine/model/medadata/validator/ValidatorRegistry.java new file mode 100644 index 000000000..3fe9d4e65 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidatorRegistry.java @@ -0,0 +1,41 @@ +package com.google.refine.model.medadata.validator; + +import java.util.HashMap; +import java.util.Map; + +import com.google.refine.model.medadata.validator.checks.EnumerableConstraint; +import com.google.refine.model.medadata.validator.checks.MaximumConstraint; +import com.google.refine.model.medadata.validator.checks.MaximumLengthConstraint; +import com.google.refine.model.medadata.validator.checks.MinimumConstraint; +import com.google.refine.model.medadata.validator.checks.MinimumLengthConstraint; +import com.google.refine.model.medadata.validator.checks.PatternConstraint; +import com.google.refine.model.medadata.validator.checks.RequiredConstraint; + +import io.frictionlessdata.tableschema.Field; + +public class ValidatorRegistry { + private static ValidatorRegistry instance = null; + private Map constraintHandlersMap = null; + + private ValidatorRegistry() { + constraintHandlersMap = new HashMap(); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_ENUM,EnumerableConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_MAXIMUM, MaximumConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_MAX_LENGTH, MaximumLengthConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_MINIMUM, MinimumConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_MIN_LENGTH, MinimumLengthConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_PATTERN, PatternConstraint.class); + constraintHandlersMap.put(Field.CONSTRAINT_KEY_REQUIRED, RequiredConstraint.class); + } + + public static ValidatorRegistry getInstance() { + if (instance == null) + instance = new ValidatorRegistry(); + + return instance; + } + + public Map getConstraintHandlersMap() { + return constraintHandlersMap; + } +} diff --git a/main/src/com/google/refine/model/medadata/validator/ValidatorSpec.java b/main/src/com/google/refine/model/medadata/validator/ValidatorSpec.java new file mode 100644 index 000000000..f32084615 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/ValidatorSpec.java @@ -0,0 +1,28 @@ +package com.google.refine.model.medadata.validator; + +import java.util.Locale; +import java.util.ResourceBundle; + +public class ValidatorSpec { + private static String VALIDATOR_RESOURCE_BUNDLE = "validator-resource-bundle"; + + private static ValidatorSpec instance = null; + private ResourceBundle bundle; + + private ValidatorSpec() { + Locale locale = new Locale("en", "US"); + bundle = ResourceBundle.getBundle(VALIDATOR_RESOURCE_BUNDLE, locale); + } + + public static ValidatorSpec getInstance() { + if (instance == null) + instance = new ValidatorSpec(); + + return instance; + } + + public String getMessage(String code) { + return bundle.getString(code); + } + +} diff --git a/main/src/com/google/refine/model/medadata/validator/checks/AbstractValidator.java b/main/src/com/google/refine/model/medadata/validator/checks/AbstractValidator.java new file mode 100644 index 000000000..85b587280 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/AbstractValidator.java @@ -0,0 +1,122 @@ +package com.google.refine.model.medadata.validator.checks; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.text.StrSubstitutor; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.refine.model.Cell; +import com.google.refine.model.Column; +import com.google.refine.model.Project; +import com.google.refine.model.Row; +import com.google.refine.model.medadata.validator.ValidatorSpec; + +public abstract class AbstractValidator implements Validator { + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + protected Project project; + protected int cellIndex; + protected JSONObject options; + protected Column column; + protected String code; + + protected JSONArray jsonErros = null; + + protected Map lookup = new HashMap(6); + + /** + * Constructor + * @param project + * @param cellIndex + * @param options + */ + public AbstractValidator(Project project, int cellIndex, JSONObject options) { + this.project = project; + this.cellIndex = cellIndex; + this.options = options; + this.column = project.columnModel.getColumnByCellIndex(cellIndex); + } + + @Override + public JSONArray validate() { + for (int rowIndex = 0;rowIndex < project.rows.size();rowIndex++) { + Row row = project.rows.get(rowIndex); + Cell cell = row.getCell(cellIndex); + if (filter(cell)) + continue; + + boolean checkResult = checkCell(cell); + if (!checkResult) { + addError(formatErrorMessage(cell, rowIndex + 1)); + } + } + return jsonErros; + } + + @Override + public JSONObject formatErrorMessage(Cell cell, int rowIndex) { + String message = null; + message = ValidatorSpec.getInstance().getMessage(code); + String formattedMessage = format(message, cell.value.toString(), rowIndex, cellIndex, code); + JSONObject json = new JSONObject(); + json.put("code", code); + json.put("message", formattedMessage); + json.put("row-number", rowIndex); + json.put("column-number", cellIndex); + + return json; + } + + /** + * MessageFormat.format cannot take the named parameters. + * @param message + * @param value + * @param rowIndex + * @param cellIndex + * @param code + * @return + */ + private String format(String message, String value, int rowIndex, int cellIndex, String code) { + lookup.put("value", value); + lookup.put("row_number", Integer.toString(rowIndex)); + lookup.put("column_number", Integer.toString(cellIndex)); + lookup.put("constraint", code); + customizedFormat(); + + return new StrSubstitutor(lookup).replace(message); + } + + /* + * Empty body since default there is no customized Format + * @see com.google.refine.model.medadata.validator.checks.Validator#customizedFormat() + */ + @Override + public void customizedFormat() { + } + + /** + * will skip the cell if return true + */ + @Override + public boolean filter(Cell cell) { + return cell == null || cell.value == null; + } + + @Override + public boolean checkCell(Cell cell) { + return false; + } + + @Override + public void addError(JSONObject result) { + if (jsonErros == null) + jsonErros = new JSONArray(); + + jsonErros.put(result); + } + +} diff --git a/main/src/com/google/refine/model/medadata/validator/checks/BlankHeader.java b/main/src/com/google/refine/model/medadata/validator/checks/BlankHeader.java new file mode 100644 index 000000000..1f4fb39c4 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/BlankHeader.java @@ -0,0 +1,11 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class BlankHeader extends AbstractValidator { + public BlankHeader(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/BlankRow.java b/main/src/com/google/refine/model/medadata/validator/checks/BlankRow.java new file mode 100644 index 000000000..6f7262923 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/BlankRow.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class BlankRow extends AbstractValidator { + + public BlankRow(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/DuplicateHeader.java b/main/src/com/google/refine/model/medadata/validator/checks/DuplicateHeader.java new file mode 100644 index 000000000..957320423 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/DuplicateHeader.java @@ -0,0 +1,11 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class DuplicateHeader extends AbstractValidator { + public DuplicateHeader(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/DuplicateRow.java b/main/src/com/google/refine/model/medadata/validator/checks/DuplicateRow.java new file mode 100644 index 000000000..3cab2a56b --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/DuplicateRow.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class DuplicateRow extends AbstractValidator { + + public DuplicateRow(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/EnumerableConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/EnumerableConstraint.java new file mode 100644 index 000000000..e76f4e667 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/EnumerableConstraint.java @@ -0,0 +1,28 @@ +package com.google.refine.model.medadata.validator.checks; + +import java.util.List; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; + +public class EnumerableConstraint extends AbstractValidator { + private List enumList; + + @SuppressWarnings("unchecked") + public EnumerableConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "enumerable-constraint"; + + enumList = (List) column.getConstraints().get(Field.CONSTRAINT_KEY_ENUM); + } + + @Override + public boolean checkCell(Cell cell) { + // XXX: deal with recon + return enumList.contains(cell.value); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/ExtraHeader.java b/main/src/com/google/refine/model/medadata/validator/checks/ExtraHeader.java new file mode 100644 index 000000000..d32608f94 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/ExtraHeader.java @@ -0,0 +1,11 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class ExtraHeader extends AbstractValidator { + public ExtraHeader(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/ExtraValue.java b/main/src/com/google/refine/model/medadata/validator/checks/ExtraValue.java new file mode 100644 index 000000000..79e1a6751 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/ExtraValue.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class ExtraValue extends AbstractValidator { + + public ExtraValue(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MaximumConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/MaximumConstraint.java new file mode 100644 index 000000000..4b4e2df36 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MaximumConstraint.java @@ -0,0 +1,39 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.exceptions.ConstraintsException; +import io.frictionlessdata.tableschema.exceptions.InvalidCastException; + +@SuppressWarnings("rawtypes") +public class MaximumConstraint extends AbstractValidator { + private String threshold; + + public MaximumConstraint(Project project, int cellIndex, JSONObject options) throws InvalidCastException, ConstraintsException { + super(project, cellIndex, options); + this.code = "maximum-constraint"; + threshold = (String)column.getConstraints() + .get(Field.CONSTRAINT_KEY_MAXIMUM); + } + + @SuppressWarnings("unchecked") + @Override + public boolean checkCell(Cell cell) { + boolean valid = true; + + try { + Comparable value = column.castValue(cell.value.toString()); + // return this - threshold + if (value.compareTo(column.castValue(threshold)) > 0) + valid = false; + } catch (InvalidCastException | ConstraintsException e) { + valid = false; + } + + return valid; + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MaximumLengthConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/MaximumLengthConstraint.java new file mode 100644 index 000000000..076ec29ef --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MaximumLengthConstraint.java @@ -0,0 +1,26 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; + +public class MaximumLengthConstraint extends AbstractValidator { + private int maxLength; + + public MaximumLengthConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "maximum-length-constraint"; + + maxLength = (int) column.getConstraints() + .get(Field.CONSTRAINT_KEY_MAX_LENGTH); + } + + @Override + public boolean checkCell(Cell cell) { + return cell.value.toString().length() <= maxLength; + } + +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MinimumConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/MinimumConstraint.java new file mode 100644 index 000000000..c01d3bd12 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MinimumConstraint.java @@ -0,0 +1,39 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.exceptions.ConstraintsException; +import io.frictionlessdata.tableschema.exceptions.InvalidCastException; + +@SuppressWarnings("rawtypes") +public class MinimumConstraint extends AbstractValidator { +private String threshold; + + public MinimumConstraint(Project project, int cellIndex, JSONObject options) throws InvalidCastException, ConstraintsException { + super(project, cellIndex, options); + this.code = "minimum-constraint"; + threshold = (String)column.getConstraints() + .get(Field.CONSTRAINT_KEY_MINIMUM); + } + + @SuppressWarnings("unchecked") + @Override + public boolean checkCell(Cell cell) { + boolean valid = true; + + try { + Comparable value = column.castValue(cell.value.toString()); + // return this - threshold + if (value.compareTo(column.castValue(threshold)) < 0) + valid = false; + } catch (InvalidCastException | ConstraintsException e) { + valid = false; + } + + return valid; + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MinimumLengthConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/MinimumLengthConstraint.java new file mode 100644 index 000000000..f8e423f1e --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MinimumLengthConstraint.java @@ -0,0 +1,35 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; + +public class MinimumLengthConstraint extends AbstractValidator { + private int minLength; + + public MinimumLengthConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "minimum-length-constrain"; + + minLength = (int)column.getConstraints() + .get(Field.CONSTRAINT_KEY_MIN_LENGTH); + } + + @Override + public boolean filter(Cell cell) { + return true; + } + + @Override + public boolean checkCell(Cell cell) { + if (cell == null || cell.value == null) + return false; + + return cell.value.toString().length() >= minLength; + } + + +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MissingHeader.java b/main/src/com/google/refine/model/medadata/validator/checks/MissingHeader.java new file mode 100644 index 000000000..8574ebe65 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MissingHeader.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class MissingHeader extends AbstractValidator { + + public MissingHeader(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/MissingValue.java b/main/src/com/google/refine/model/medadata/validator/checks/MissingValue.java new file mode 100644 index 000000000..6e730ba8e --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/MissingValue.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class MissingValue extends AbstractValidator { + + public MissingValue(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/NonMatchingHeader.java b/main/src/com/google/refine/model/medadata/validator/checks/NonMatchingHeader.java new file mode 100644 index 000000000..110403c6e --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/NonMatchingHeader.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class NonMatchingHeader extends AbstractValidator { + + public NonMatchingHeader(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/PatternConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/PatternConstraint.java new file mode 100644 index 000000000..52798b9c6 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/PatternConstraint.java @@ -0,0 +1,30 @@ +package com.google.refine.model.medadata.validator.checks; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.Field; + +public class PatternConstraint extends AbstractValidator { + private String regexPattern; + + public PatternConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "pattern-constraint"; + + this.regexPattern = (String)column.getConstraints().get(Field.CONSTRAINT_KEY_PATTERN); + } + + @Override + public boolean checkCell(Cell cell) { + Pattern pattern = Pattern.compile(regexPattern); + Matcher matcher = pattern.matcher((String)cell.value); + + return matcher.matches(); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/RequiredConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/RequiredConstraint.java new file mode 100644 index 000000000..7813b9506 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/RequiredConstraint.java @@ -0,0 +1,26 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.apache.commons.lang3.StringUtils; +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +public class RequiredConstraint extends AbstractValidator { + + public RequiredConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "required-constraint"; + } + + @Override + public boolean filter(Cell cell) { + // always check + return false; + } + + @Override + public boolean checkCell(Cell cell) { + return StringUtils.isNotBlank(cell.value.toString()); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/TypeorFormatError.java b/main/src/com/google/refine/model/medadata/validator/checks/TypeorFormatError.java new file mode 100644 index 000000000..6aaefcd27 --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/TypeorFormatError.java @@ -0,0 +1,49 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Cell; +import com.google.refine.model.Project; + +import io.frictionlessdata.tableschema.exceptions.ConstraintsException; +import io.frictionlessdata.tableschema.exceptions.InvalidCastException; + +public class TypeorFormatError extends AbstractValidator { + private String type; + private String format; + + public TypeorFormatError(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "type-or-format-error"; + + this.type = column.getType(); + this.format = column.getFormat(); + } + + @Override + public boolean checkCell(Cell cell) { + boolean valid = true; + + try { + column.castValue(cell.value.toString()); + } catch (InvalidCastException | ConstraintsException e) { + // patch for issue: https://github.com/frictionlessdata/tableschema-java/issues/21 + if ("number".equals(type)) { + try { + column.castValue(cell.value.toString() + ".0"); + } catch (InvalidCastException | ConstraintsException e1) { + valid = false; + } + } else + valid = false; + } + + return valid; + } + + @Override + public void customizedFormat() { + lookup.put("field_type", type); + lookup.put("field_format", format); + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/UniqueConstraint.java b/main/src/com/google/refine/model/medadata/validator/checks/UniqueConstraint.java new file mode 100644 index 000000000..1f562362d --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/UniqueConstraint.java @@ -0,0 +1,12 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONObject; + +import com.google.refine.model.Project; + +public class UniqueConstraint extends AbstractValidator { + public UniqueConstraint(Project project, int cellIndex, JSONObject options) { + super(project, cellIndex, options); + this.code = "unique-constraint"; + } +} \ No newline at end of file diff --git a/main/src/com/google/refine/model/medadata/validator/checks/Validator.java b/main/src/com/google/refine/model/medadata/validator/checks/Validator.java new file mode 100644 index 000000000..ad064657a --- /dev/null +++ b/main/src/com/google/refine/model/medadata/validator/checks/Validator.java @@ -0,0 +1,36 @@ +package com.google.refine.model.medadata.validator.checks; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.google.refine.model.Cell; + +public interface Validator { + /** + * Given the options and cell index, apply the validate operation. + * @return + */ + public JSONArray validate(); + + /** + * Skip if cell is incomplete + * @return + */ + public boolean filter(Cell cell); + + /** + * check the cell against the table schema + * @param cell + * @return false if fails the validation / check. Otherwise return true + */ + public boolean checkCell(Cell cell); + + /** + * Add error into the report for return + */ + public void addError(JSONObject result); + + public JSONObject formatErrorMessage(Cell cell, int rowIndex); + + public void customizedFormat(); +} diff --git a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java index 0ddce01d3..07f994842 100644 --- a/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java +++ b/main/src/com/google/refine/model/recon/ReconciledDataExtensionJob.java @@ -184,7 +184,7 @@ public class ReconciledDataExtensionJob { String str = val.getString("str"); storeCell(rows, rowindex, colindex, str); } else if (val.has("float")) { - float v = Float.parseFloat(val.getString("float")); + float v = val.getBigDecimal("float").floatValue(); storeCell(rows, rowindex, colindex, v); } else if (val.has("int")) { int v = Integer.parseInt(val.getString("int")); diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index d6f02548c..0c7f5ea7b 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -48,7 +48,7 @@ import java.util.List; import java.util.Properties; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java index 9b614f60e..83d2fdbca 100644 --- a/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/google/refine/operations/cell/MultiValuedCellSplitOperation.java @@ -38,7 +38,7 @@ import java.util.List; import java.util.Properties; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java index 63f2787af..553673798 100644 --- a/main/src/com/google/refine/operations/column/ColumnSplitOperation.java +++ b/main/src/com/google/refine/operations/column/ColumnSplitOperation.java @@ -39,7 +39,7 @@ import java.util.List; import java.util.Properties; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java index 9771e52d5..3e16c9847 100644 --- a/main/src/com/google/refine/operations/recon/ExtendDataOperation.java +++ b/main/src/com/google/refine/operations/recon/ExtendDataOperation.java @@ -41,7 +41,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java index 9c02e6ad7..6ad392b3e 100644 --- a/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconCopyAcrossColumnsOperation.java @@ -41,7 +41,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 314bfefbf..e44656c6d 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -50,6 +50,9 @@ import com.google.refine.RefineServlet; public class PreferenceStore implements Jsonizable { public static final String USER_METADATA_KEY = "userMetadata"; + // use to populate "creator" filed in metadata. https://github.com/OpenRefine/OpenRefine/issues/1393 + public static final String USER_NAME = "username"; + private boolean dirty = false; protected Map _prefs = new HashMap(); diff --git a/main/src/com/google/refine/util/JSONUtilities.java b/main/src/com/google/refine/util/JSONUtilities.java index 0ac6f66b2..87e4c321c 100644 --- a/main/src/com/google/refine/util/JSONUtilities.java +++ b/main/src/com/google/refine/util/JSONUtilities.java @@ -37,6 +37,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -125,6 +126,10 @@ public class JSONUtilities { } } + static public JSONArray arrayToJSONArray(String[] array) { + return new JSONArray(Arrays.asList(array)); + } + static public int[] getIntArray(JSONObject obj, String key) { try { JSONArray a = obj.getJSONArray(key); @@ -276,6 +281,15 @@ public class JSONUtilities { } } + static public void safeInc(JSONObject obj, String key) { + try { + int currentValue = obj.getInt(key); + safePut(obj, key, currentValue + 1); + } catch (JSONException e) { + e.printStackTrace(); + } + } + static public void safePut(JSONObject obj, String key, long value) { try { obj.put(key, value); @@ -353,4 +367,11 @@ public class JSONUtilities { return list; } + + static public void concatArray(JSONArray destArray, JSONArray srcArray) + throws JSONException { + for (int i = 0; i < srcArray.length(); i++) { + destArray.put(srcArray.get(i)); + } + } } diff --git a/main/src/com/google/refine/util/JSObject.java b/main/src/com/google/refine/util/JSObject.java index 06bb8bd56..18d22fef1 100644 --- a/main/src/com/google/refine/util/JSObject.java +++ b/main/src/com/google/refine/util/JSObject.java @@ -39,7 +39,7 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.Properties; -import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringEscapeUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -157,7 +157,7 @@ public class JSObject extends Properties { writeJSONObject(writer, (JSONObject) o); } else { - writer.print("\"" + StringEscapeUtils.escapeJavaScript(o.toString()) + "\""); + writer.print("\"" + StringEscapeUtils.escapeEcmaScript(o.toString()) + "\""); } } } diff --git a/main/src/com/google/refine/util/ParsingUtilities.java b/main/src/com/google/refine/util/ParsingUtilities.java index a4f56e445..1cca2b98b 100644 --- a/main/src/com/google/refine/util/ParsingUtilities.java +++ b/main/src/com/google/refine/util/ParsingUtilities.java @@ -38,7 +38,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; -import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDateTime; import java.time.OffsetDateTime; @@ -56,16 +55,6 @@ import org.json.JSONObject; import org.json.JSONTokener; public class ParsingUtilities { - - static final private ThreadLocal ISO8601_FORMAT = new ThreadLocal() { - - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - } - - }; - static public Properties parseUrlParameters(HttpServletRequest request) { Properties options = new Properties(); @@ -198,8 +187,7 @@ public class ParsingUtilities { if (s.endsWith("Z")) { // UTC time Instant instant = Instant.parse(s); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); - } else { + } else return LocalDateTime.parse(s, DateTimeFormatter.ISO_LOCAL_DATE_TIME); - } } } diff --git a/main/src/validator-resource-bundle.properties b/main/src/validator-resource-bundle.properties new file mode 100644 index 000000000..ca059b67d --- /dev/null +++ b/main/src/validator-resource-bundle.properties @@ -0,0 +1,13 @@ +schema-error=Table Schema error: ${error_message} +non-matching-header=Header in column ${column_number} doesn't match field name ${field_name} in the schema +extra-header=There is an extra header in column ${column_number} +missing-header=There is a missing header in column ${column_number} +type-or-format-error=The value ${value} in row ${row_number} and column ${column_number} is not type ${field_type} and format ${field_format} +required-constraint=Column ${column_number} is a required field, but row ${row_number} has no value +pattern-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the pattern constraint of ${constraint} +unique-constraint=Rows ${row_numbers} has unique constraint violation in column ${column_number} +enumerable-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the given enumeration: ${constraint} +minimum-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the minimum constraint of ${constraint} +maximum-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the maximum constraint of ${constraint} +minimum-length-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the minimum length constraint of ${constraint} +maximum-length-constraint=The value ${value} in row ${row_number} and column ${column_number} does not conform to the maximum length constraint of ${constraint} diff --git a/main/tests/data/datapackage-sample.json b/main/tests/data/datapackage-sample.json new file mode 100644 index 000000000..6ed88f3e7 --- /dev/null +++ b/main/tests/data/datapackage-sample.json @@ -0,0 +1,44 @@ +{ + "image": "http://assets.okfn.org/p/opendatahandbook/img/data-wrench.png", + "license": "PDDL-1.0", + "last_updated": "2011-09-21", + "keywords": [ + "GDP", + "World", + "Gross Domestic Product", + "Time series" + ], + "sources": [{ + "web": "http://data.worldbank.org/indicator/NY.GDP.MKTP.CD", + "name": "World Bank and OECD", + "title": "World Bank and OECD" + }], + "name": "gdp", + "description": "Country, regional and world GDP in current US Dollars ($). Regional means collections of countries e.g. Europe & Central Asia. Data is sourced from the World Bank and turned into a standard normalized CSV.", + "resources": [{ + "schema": {"fields": [ + { + "name": "Country Name", + "type": "string" + }, + { + "name": "Country Code", + "type": "string", + "foreignkey": "iso-3-geo-codes/id" + }, + { + "name": "Year", + "type": "year" + }, + { + "name": "Value", + "description": "GDP in current USD", + "type": "number" + } + ]}, + "path": "data/gdp.csv", + "name": "gdp" + }], + "title": "Country, Regional and World GDP (Gross Domestic Product)", + "version": "2011" +} \ No newline at end of file diff --git a/main/tests/data/gdp.csv b/main/tests/data/gdp.csv new file mode 100644 index 000000000..da7de60ba --- /dev/null +++ b/main/tests/data/gdp.csv @@ -0,0 +1,11543 @@ +Country Name,Country Code,Year,Value +Arab World,ARB,1968,25760683041.0826 +Arab World,ARB,1969,28434203615.4795 +Arab World,ARB,1970,31385499664.0635 +Arab World,ARB,1971,36426909888.3884 +Arab World,ARB,1972,43316056615.451 +Arab World,ARB,1973,55018394945.576 +Arab World,ARB,1974,105145803084.364 +Arab World,ARB,1975,116337021938.327 +Arab World,ARB,1976,144846175400.471 +Arab World,ARB,1977,167308327683.573 +Arab World,ARB,1978,183555544342.167 +Arab World,ARB,1979,248646206366.973 +Arab World,ARB,1980,338177454717.499 +Arab World,ARB,1981,348592795413.075 +Arab World,ARB,1982,324328753765.261 +Arab World,ARB,1983,303962539723.043 +Arab World,ARB,1984,307940771858.505 +Arab World,ARB,1985,303893618415.505 +Arab World,ARB,1986,289029150639.407 +Arab World,ARB,1987,312681678329.895 +Arab World,ARB,1988,307503035642.479 +Arab World,ARB,1989,322325140494.687 +Arab World,ARB,1990,446877161735.167 +Arab World,ARB,1991,439779177858.364 +Arab World,ARB,1992,471163515480.256 +Arab World,ARB,1993,476513630630.268 +Arab World,ARB,1994,487526906280.526 +Arab World,ARB,1995,523759898288.293 +Arab World,ARB,1996,578231297763.478 +Arab World,ARB,1997,613279452474.103 +Arab World,ARB,1998,591525594021.399 +Arab World,ARB,1999,643889670873.196 +Arab World,ARB,2000,735025140336.255 +Arab World,ARB,2001,723282816382.445 +Arab World,ARB,2002,729051715403.984 +Arab World,ARB,2003,823110541431.167 +Arab World,ARB,2004,963862340520.581 +Arab World,ARB,2005,1184661549595.13 +Arab World,ARB,2006,1404113530800.68 +Arab World,ARB,2007,1637573196970.62 +Arab World,ARB,2008,2077706582271.06 +Arab World,ARB,2009,1795472295052.32 +Arab World,ARB,2010,2109224213446 +Arab World,ARB,2011,2501942770389.97 +Arab World,ARB,2012,2740536188974.17 +Arab World,ARB,2013,2838294388723.79 +Arab World,ARB,2014,2904404570076.29 +Arab World,ARB,2015,2561129553776.39 +Arab World,ARB,2016,2500931669252.23 +Caribbean small states,CSS,1960,1922640775.37204 +Caribbean small states,CSS,1961,2080830143.04221 +Caribbean small states,CSS,1962,2195684581.07261 +Caribbean small states,CSS,1963,2331959438.21902 +Caribbean small states,CSS,1964,2519261152.97369 +Caribbean small states,CSS,1965,2712715412.87482 +Caribbean small states,CSS,1966,2942141442.47693 +Caribbean small states,CSS,1967,3158211274.70685 +Caribbean small states,CSS,1968,3140469906.3566 +Caribbean small states,CSS,1969,3417668655.56627 +Caribbean small states,CSS,1970,3760199658.87297 +Caribbean small states,CSS,1971,4088013918.53147 +Caribbean small states,CSS,1972,4732543297.55318 +Caribbean small states,CSS,1973,5169932102.82734 +Caribbean small states,CSS,1974,6720764011.57956 +Caribbean small states,CSS,1975,7864013356.29591 +Caribbean small states,CSS,1976,8070017845.29298 +Caribbean small states,CSS,1977,9382602731.01335 +Caribbean small states,CSS,1978,9571657513.65075 +Caribbean small states,CSS,1979,10966585159.6649 +Caribbean small states,CSS,1980,13453485464.7329 +Caribbean small states,CSS,1981,14842851376.6236 +Caribbean small states,CSS,1982,16495461075.5827 +Caribbean small states,CSS,1983,16712010846.6962 +Caribbean small states,CSS,1984,15923806275.1117 +Caribbean small states,CSS,1985,15742679785.309 +Caribbean small states,CSS,1986,14358714160.1057 +Caribbean small states,CSS,1987,15429015788.2553 +Caribbean small states,CSS,1988,16357329644.5497 +Caribbean small states,CSS,1989,16756727132.51 +Caribbean small states,CSS,1990,17873417057.5917 +Caribbean small states,CSS,1991,17682124581.2842 +Caribbean small states,CSS,1992,17403218746.3421 +Caribbean small states,CSS,1993,18271706185.3177 +Caribbean small states,CSS,1994,19289595454.1442 +Caribbean small states,CSS,1995,21134882108.6249 +Caribbean small states,CSS,1996,23041766083.4574 +Caribbean small states,CSS,1997,25732062006.8942 +Caribbean small states,CSS,1998,28249810016.98 +Caribbean small states,CSS,1999,30022260633.4195 +Caribbean small states,CSS,2000,32252030400.7358 +Caribbean small states,CSS,2001,33172149746.0103 +Caribbean small states,CSS,2002,34944596086.0711 +Caribbean small states,CSS,2003,37495408032.2944 +Caribbean small states,CSS,2004,41173138191.6472 +Caribbean small states,CSS,2005,46649069646.0953 +Caribbean small states,CSS,2006,52393433350.716 +Caribbean small states,CSS,2007,58257681979.3301 +Caribbean small states,CSS,2008,66480563576.5929 +Caribbean small states,CSS,2009,55930530970.8562 +Caribbean small states,CSS,2010,60772694299.858 +Caribbean small states,CSS,2011,65739442150.8813 +Caribbean small states,CSS,2012,67860562821.0636 +Caribbean small states,CSS,2013,68729777391.3784 +Caribbean small states,CSS,2014,68744227741.6518 +Caribbean small states,CSS,2015,66799701061.8327 +Caribbean small states,CSS,2016,63540193020.0893 +Central Europe and the Baltics,CEB,1990,256113714527.618 +Central Europe and the Baltics,CEB,1991,242631767248.709 +Central Europe and the Baltics,CEB,1992,259823093659.716 +Central Europe and the Baltics,CEB,1993,273915105741.891 +Central Europe and the Baltics,CEB,1994,310702556423.306 +Central Europe and the Baltics,CEB,1995,386114777052.74 +Central Europe and the Baltics,CEB,1996,412629652592.241 +Central Europe and the Baltics,CEB,1997,408895193163.935 +Central Europe and the Baltics,CEB,1998,447448444539.62 +Central Europe and the Baltics,CEB,1999,433914932035.509 +Central Europe and the Baltics,CEB,2000,427550058634.753 +Central Europe and the Baltics,CEB,2001,468161745109.393 +Central Europe and the Baltics,CEB,2002,527146030956.314 +Central Europe and the Baltics,CEB,2003,634284039973.081 +Central Europe and the Baltics,CEB,2004,762451562237.799 +Central Europe and the Baltics,CEB,2005,885747879466.35 +Central Europe and the Baltics,CEB,2006,1001942855597.53 +Central Europe and the Baltics,CEB,2007,1260957147846.53 +Central Europe and the Baltics,CEB,2008,1523196377519.86 +Central Europe and the Baltics,CEB,2009,1279854250277.72 +Central Europe and the Baltics,CEB,2010,1312750149554.56 +Central Europe and the Baltics,CEB,2011,1446220607413.34 +Central Europe and the Baltics,CEB,2012,1350778814230.21 +Central Europe and the Baltics,CEB,2013,1421351670726.71 +Central Europe and the Baltics,CEB,2014,1461972726743.52 +Central Europe and the Baltics,CEB,2015,1281539342884.75 +Central Europe and the Baltics,CEB,2016,1303382786630.62 +Early-demographic dividend,EAR,1960,152222021503.101 +Early-demographic dividend,EAR,1961,153174173789.089 +Early-demographic dividend,EAR,1962,158795369827.794 +Early-demographic dividend,EAR,1963,167975897835.712 +Early-demographic dividend,EAR,1964,192426156455.164 +Early-demographic dividend,EAR,1965,209993963772.447 +Early-demographic dividend,EAR,1966,207316686431.051 +Early-demographic dividend,EAR,1967,217587076275.313 +Early-demographic dividend,EAR,1968,235705718659.736 +Early-demographic dividend,EAR,1969,263417168820.022 +Early-demographic dividend,EAR,1970,278414463364.508 +Early-demographic dividend,EAR,1971,300750846441.857 +Early-demographic dividend,EAR,1972,330264782812.664 +Early-demographic dividend,EAR,1973,422538233529.836 +Early-demographic dividend,EAR,1974,592504417822.073 +Early-demographic dividend,EAR,1975,636292930399.372 +Early-demographic dividend,EAR,1976,694401920707.909 +Early-demographic dividend,EAR,1977,777069860599.993 +Early-demographic dividend,EAR,1978,860276042756.762 +Early-demographic dividend,EAR,1979,1045208440796.38 +Early-demographic dividend,EAR,1980,1289757085834.86 +Early-demographic dividend,EAR,1981,1441144663708.07 +Early-demographic dividend,EAR,1982,1371908131842.89 +Early-demographic dividend,EAR,1983,1385300584420.83 +Early-demographic dividend,EAR,1984,1365815981597.72 +Early-demographic dividend,EAR,1985,1397858695204.75 +Early-demographic dividend,EAR,1986,1418211765048.27 +Early-demographic dividend,EAR,1987,1429315977542.63 +Early-demographic dividend,EAR,1988,1535871536563.05 +Early-demographic dividend,EAR,1989,1568562659306.28 +Early-demographic dividend,EAR,1990,1806505172134.77 +Early-demographic dividend,EAR,1991,1912921517302.44 +Early-demographic dividend,EAR,1992,2098149661879.33 +Early-demographic dividend,EAR,1993,2302453002964.44 +Early-demographic dividend,EAR,1994,2408912031539.9 +Early-demographic dividend,EAR,1995,2468961701917.03 +Early-demographic dividend,EAR,1996,2694453298131.29 +Early-demographic dividend,EAR,1997,2878903970242.92 +Early-demographic dividend,EAR,1998,2839864195429.24 +Early-demographic dividend,EAR,1999,3010697292749.06 +Early-demographic dividend,EAR,2000,3265108230891.93 +Early-demographic dividend,EAR,2001,3224441922892.92 +Early-demographic dividend,EAR,2002,3131166808367.24 +Early-demographic dividend,EAR,2003,3500675725433.46 +Early-demographic dividend,EAR,2004,4066546525118.83 +Early-demographic dividend,EAR,2005,4742611342049.54 +Early-demographic dividend,EAR,2006,5428145324754.82 +Early-demographic dividend,EAR,2007,6446032068048.83 +Early-demographic dividend,EAR,2008,7272012608284.4 +Early-demographic dividend,EAR,2009,6990930969841.42 +Early-demographic dividend,EAR,2010,8490184886018.92 +Early-demographic dividend,EAR,2011,9567687630587.59 +Early-demographic dividend,EAR,2012,9956217405201.38 +Early-demographic dividend,EAR,2013,10199668619019.7 +Early-demographic dividend,EAR,2014,10514807961576.6 +Early-demographic dividend,EAR,2015,10225383730055.9 +Early-demographic dividend,EAR,2016,10378321855929.9 +East Asia & Pacific,EAS,1960,153406062445.133 +East Asia & Pacific,EAS,1961,153851906489.076 +East Asia & Pacific,EAS,1962,157422860957.598 +East Asia & Pacific,EAS,1963,175666653928.707 +East Asia & Pacific,EAS,1964,201828758065.12 +East Asia & Pacific,EAS,1965,224795305298.806 +East Asia & Pacific,EAS,1966,251316895422.914 +East Asia & Pacific,EAS,1967,272311886780.484 +East Asia & Pacific,EAS,1968,300037540836.51 +East Asia & Pacific,EAS,1969,345620520780.581 +East Asia & Pacific,EAS,1970,406892268832.737 +East Asia & Pacific,EAS,1971,451555305929.632 +East Asia & Pacific,EAS,1972,560418537433.307 +East Asia & Pacific,EAS,1973,738629607846.873 +East Asia & Pacific,EAS,1974,850486001086.155 +East Asia & Pacific,EAS,1975,931183199853.372 +East Asia & Pacific,EAS,1976,1023624295308.86 +East Asia & Pacific,EAS,1977,1220099418673.47 +East Asia & Pacific,EAS,1978,1539413405469.08 +East Asia & Pacific,EAS,1979,1671803883927.95 +East Asia & Pacific,EAS,1980,1806920411252.29 +East Asia & Pacific,EAS,1981,1994776943312.9 +East Asia & Pacific,EAS,1982,1953473277429.83 +East Asia & Pacific,EAS,1983,2073066401462.35 +East Asia & Pacific,EAS,1984,2223992929693.57 +East Asia & Pacific,EAS,1985,2358172144946.55 +East Asia & Pacific,EAS,1986,3076109459284.79 +East Asia & Pacific,EAS,1987,3598365917263.22 +East Asia & Pacific,EAS,1988,4330848600314.32 +East Asia & Pacific,EAS,1989,4529251580451.43 +East Asia & Pacific,EAS,1990,4740125610961.6 +East Asia & Pacific,EAS,1991,5337495034346.36 +East Asia & Pacific,EAS,1992,5827466927803.02 +East Asia & Pacific,EAS,1993,6542241886332.86 +East Asia & Pacific,EAS,1994,7302165972072.7 +East Asia & Pacific,EAS,1995,8297217618291.42 +East Asia & Pacific,EAS,1996,7993854682092.77 +East Asia & Pacific,EAS,1997,7649008381580.38 +East Asia & Pacific,EAS,1998,6857782846050.01 +East Asia & Pacific,EAS,1999,7656256420658.01 +East Asia & Pacific,EAS,2000,8283672555565.95 +East Asia & Pacific,EAS,2001,7705159083109.51 +East Asia & Pacific,EAS,2002,7827298972846.93 +East Asia & Pacific,EAS,2003,8605351856004.54 +East Asia & Pacific,EAS,2004,9651082222195.5 +East Asia & Pacific,EAS,2005,10292825485348.7 +East Asia & Pacific,EAS,2006,10913330711044.6 +East Asia & Pacific,EAS,2007,12205786067031.7 +East Asia & Pacific,EAS,2008,14097329803496.3 +East Asia & Pacific,EAS,2009,14526049741278.9 +East Asia & Pacific,EAS,2010,16934259897815.9 +East Asia & Pacific,EAS,2011,19633645544446.8 +East Asia & Pacific,EAS,2012,21013112141456.7 +East Asia & Pacific,EAS,2013,21256469783768.7 +East Asia & Pacific,EAS,2014,21894085979174.9 +East Asia & Pacific,EAS,2015,21765291253881.4 +East Asia & Pacific,EAS,2016,22477425046152.2 +East Asia & Pacific (excluding high income),EAP,1960,80259949708.256 +East Asia & Pacific (excluding high income),EAP,1961,70454320784.1637 +East Asia & Pacific (excluding high income),EAP,1962,64561374187.0283 +East Asia & Pacific (excluding high income),EAP,1963,69911007473.5442 +East Asia & Pacific (excluding high income),EAP,1964,81054694801.5609 +East Asia & Pacific (excluding high income),EAP,1965,94592399250.3341 +East Asia & Pacific (excluding high income),EAP,1966,103552673128.584 +East Asia & Pacific (excluding high income),EAP,1967,100339273081.733 +East Asia & Pacific (excluding high income),EAP,1968,101275421779.252 +East Asia & Pacific (excluding high income),EAP,1969,113721619713.104 +East Asia & Pacific (excluding high income),EAP,1970,126769627751.232 +East Asia & Pacific (excluding high income),EAP,1971,136328570880.601 +East Asia & Pacific (excluding high income),EAP,1972,154659093609.397 +East Asia & Pacific (excluding high income),EAP,1973,194723705741.74 +East Asia & Pacific (excluding high income),EAP,1974,219684982687.941 +East Asia & Pacific (excluding high income),EAP,1975,246972833579.966 +East Asia & Pacific (excluding high income),EAP,1976,250679070877.618 +East Asia & Pacific (excluding high income),EAP,1977,289679258049.107 +East Asia & Pacific (excluding high income),EAP,1978,280440164773.063 +East Asia & Pacific (excluding high income),EAP,1979,324841171790.876 +East Asia & Pacific (excluding high income),EAP,1980,374815806190.863 +East Asia & Pacific (excluding high income),EAP,1981,399965066634.494 +East Asia & Pacific (excluding high income),EAP,1982,419766288759.248 +East Asia & Pacific (excluding high income),EAP,1983,440469714741.303 +East Asia & Pacific (excluding high income),EAP,1984,478158198678.127 +East Asia & Pacific (excluding high income),EAP,1985,524014062044.045 +East Asia & Pacific (excluding high income),EAP,1986,522534774843.578 +East Asia & Pacific (excluding high income),EAP,1987,516086961052.224 +East Asia & Pacific (excluding high income),EAP,1988,572406468163.312 +East Asia & Pacific (excluding high income),EAP,1989,618643709376.269 +East Asia & Pacific (excluding high income),EAP,1990,663045725610.49 +East Asia & Pacific (excluding high income),EAP,1991,719584447233.343 +East Asia & Pacific (excluding high income),EAP,1992,806358557827.083 +East Asia & Pacific (excluding high income),EAP,1993,885238781446.321 +East Asia & Pacific (excluding high income),EAP,1994,1064868940113.18 +East Asia & Pacific (excluding high income),EAP,1995,1314307625271.26 +East Asia & Pacific (excluding high income),EAP,1996,1509620351019.71 +East Asia & Pacific (excluding high income),EAP,1997,1563661684670.21 +East Asia & Pacific (excluding high income),EAP,1998,1433164072949.29 +East Asia & Pacific (excluding high income),EAP,1999,1576476091414.92 +East Asia & Pacific (excluding high income),EAP,2000,1737704956830.78 +East Asia & Pacific (excluding high income),EAP,2001,1848846696904.54 +East Asia & Pacific (excluding high income),EAP,2002,2046255878039.6 +East Asia & Pacific (excluding high income),EAP,2003,2315970352098 +East Asia & Pacific (excluding high income),EAP,2004,2685679579693.63 +East Asia & Pacific (excluding high income),EAP,2005,3105942817285.98 +East Asia & Pacific (excluding high income),EAP,2006,3737485223150.79 +East Asia & Pacific (excluding high income),EAP,2007,4727397727396.91 +East Asia & Pacific (excluding high income),EAP,2008,5984384402421.37 +East Asia & Pacific (excluding high income),EAP,2009,6493261436292.97 +East Asia & Pacific (excluding high income),EAP,2010,7875013124582.93 +East Asia & Pacific (excluding high income),EAP,2011,9625870808891.42 +East Asia & Pacific (excluding high income),EAP,2012,10738363479428.9 +East Asia & Pacific (excluding high income),EAP,2013,11854913554643.5 +East Asia & Pacific (excluding high income),EAP,2014,12748307082155.9 +East Asia & Pacific (excluding high income),EAP,2015,13267645915189.5 +East Asia & Pacific (excluding high income),EAP,2016,13511178026303.6 +East Asia & Pacific (IDA & IBRD countries),TEA,1960,80087763368.4641 +East Asia & Pacific (IDA & IBRD countries),TEA,1961,70303171030.6136 +East Asia & Pacific (IDA & IBRD countries),TEA,1962,64422866914.6763 +East Asia & Pacific (IDA & IBRD countries),TEA,1963,69761023321.6503 +East Asia & Pacific (IDA & IBRD countries),TEA,1964,80880803448.8805 +East Asia & Pacific (IDA & IBRD countries),TEA,1965,94389464672.6492 +East Asia & Pacific (IDA & IBRD countries),TEA,1966,103330515554.021 +East Asia & Pacific (IDA & IBRD countries),TEA,1967,100124009401.253 +East Asia & Pacific (IDA & IBRD countries),TEA,1968,101058149724.505 +East Asia & Pacific (IDA & IBRD countries),TEA,1969,113477646105.785 +East Asia & Pacific (IDA & IBRD countries),TEA,1970,126497661493.109 +East Asia & Pacific (IDA & IBRD countries),TEA,1971,136036097265.624 +East Asia & Pacific (IDA & IBRD countries),TEA,1972,154327294457.505 +East Asia & Pacific (IDA & IBRD countries),TEA,1973,194305953646.402 +East Asia & Pacific (IDA & IBRD countries),TEA,1974,219213679712.873 +East Asia & Pacific (IDA & IBRD countries),TEA,1975,246442988390.718 +East Asia & Pacific (IDA & IBRD countries),TEA,1976,250141274481.86 +East Asia & Pacific (IDA & IBRD countries),TEA,1977,289057792282.702 +East Asia & Pacific (IDA & IBRD countries),TEA,1978,279838520171.011 +East Asia & Pacific (IDA & IBRD countries),TEA,1979,324144271125.13 +East Asia & Pacific (IDA & IBRD countries),TEA,1980,374011692034.316 +East Asia & Pacific (IDA & IBRD countries),TEA,1981,399106998306.283 +East Asia & Pacific (IDA & IBRD countries),TEA,1982,418865739717.139 +East Asia & Pacific (IDA & IBRD countries),TEA,1983,439524749434.869 +East Asia & Pacific (IDA & IBRD countries),TEA,1984,477132378074.312 +East Asia & Pacific (IDA & IBRD countries),TEA,1985,522889864188.566 +East Asia & Pacific (IDA & IBRD countries),TEA,1986,521413750588.998 +East Asia & Pacific (IDA & IBRD countries),TEA,1987,514979769667.717 +East Asia & Pacific (IDA & IBRD countries),TEA,1988,571178451263.419 +East Asia & Pacific (IDA & IBRD countries),TEA,1989,617316497032.628 +East Asia & Pacific (IDA & IBRD countries),TEA,1990,661623255038.025 +East Asia & Pacific (IDA & IBRD countries),TEA,1991,718040680851.845 +East Asia & Pacific (IDA & IBRD countries),TEA,1992,804628629897.439 +East Asia & Pacific (IDA & IBRD countries),TEA,1993,883339627183.539 +East Asia & Pacific (IDA & IBRD countries),TEA,1994,1062584414819.77 +East Asia & Pacific (IDA & IBRD countries),TEA,1995,1311487964653.74 +East Asia & Pacific (IDA & IBRD countries),TEA,1996,1506381674647.97 +East Asia & Pacific (IDA & IBRD countries),TEA,1997,1560307070281.15 +East Asia & Pacific (IDA & IBRD countries),TEA,1998,1430089422679.27 +East Asia & Pacific (IDA & IBRD countries),TEA,1999,1573093985533.5 +East Asia & Pacific (IDA & IBRD countries),TEA,2000,1733976957283.78 +East Asia & Pacific (IDA & IBRD countries),TEA,2001,1844880258516.11 +East Asia & Pacific (IDA & IBRD countries),TEA,2002,2041865926249.22 +East Asia & Pacific (IDA & IBRD countries),TEA,2003,2311056516099.72 +East Asia & Pacific (IDA & IBRD countries),TEA,2004,2680080452885.16 +East Asia & Pacific (IDA & IBRD countries),TEA,2005,3099556641923.49 +East Asia & Pacific (IDA & IBRD countries),TEA,2006,3729909801279.21 +East Asia & Pacific (IDA & IBRD countries),TEA,2007,4717923246206.8 +East Asia & Pacific (IDA & IBRD countries),TEA,2008,5972485978440.58 +East Asia & Pacific (IDA & IBRD countries),TEA,2009,6480284114182.45 +East Asia & Pacific (IDA & IBRD countries),TEA,2010,7859520533899.79 +East Asia & Pacific (IDA & IBRD countries),TEA,2011,9607063801205.78 +East Asia & Pacific (IDA & IBRD countries),TEA,2012,10717379224740.4 +East Asia & Pacific (IDA & IBRD countries),TEA,2013,11831819367549.7 +East Asia & Pacific (IDA & IBRD countries),TEA,2014,12723521658445.1 +East Asia & Pacific (IDA & IBRD countries),TEA,2015,13241873807583.3 +East Asia & Pacific (IDA & IBRD countries),TEA,2016,13484932862978.8 +Euro area,EMU,1960,245389523535.21 +Euro area,EMU,1961,270108736771.728 +Euro area,EMU,1962,299749528685.376 +Euro area,EMU,1963,336271770003.717 +Euro area,EMU,1964,374010191933.27 +Euro area,EMU,1965,408119028178.097 +Euro area,EMU,1966,445040235612.184 +Euro area,EMU,1967,483441345246.615 +Euro area,EMU,1968,518263505475.995 +Euro area,EMU,1969,572532268216.495 +Euro area,EMU,1970,641460637395.971 +Euro area,EMU,1971,727045243334.751 +Euro area,EMU,1972,878371965947.911 +Euro area,EMU,1973,1140215331077.93 +Euro area,EMU,1974,1292913189870.35 +Euro area,EMU,1975,1499292682301.1 +Euro area,EMU,1976,1564518129278.76 +Euro area,EMU,1977,1779460900157.27 +Euro area,EMU,1978,2179044584488.07 +Euro area,EMU,1979,2639765077757.45 +Euro area,EMU,1980,2956735717812.24 +Euro area,EMU,1981,2569819070205.93 +Euro area,EMU,1982,2487970498872.87 +Euro area,EMU,1983,2427189312535.1 +Euro area,EMU,1984,2328259732922.51 +Euro area,EMU,1985,2392054029846.51 +Euro area,EMU,1986,3357238823395.49 +Euro area,EMU,1987,4152743228203.74 +Euro area,EMU,1988,4567318804504.65 +Euro area,EMU,1989,4665607905988.66 +Euro area,EMU,1990,5871693989817.08 +Euro area,EMU,1991,6104530124284.34 +Euro area,EMU,1992,6734901870233.99 +Euro area,EMU,1993,6168663044953.83 +Euro area,EMU,1994,6515506760178.52 +Euro area,EMU,1995,7520106864481.86 +Euro area,EMU,1996,7611726452029.66 +Euro area,EMU,1997,6959484673611.01 +Euro area,EMU,1998,7151028055866.01 +Euro area,EMU,1999,7119223020204.08 +Euro area,EMU,2000,6486948965622.98 +Euro area,EMU,2001,6593233923750.33 +Euro area,EMU,2002,7173603214645.71 +Euro area,EMU,2003,8850599071571.01 +Euro area,EMU,2004,10151814034876.7 +Euro area,EMU,2005,10535328496601.9 +Euro area,EMU,2006,11184406192078.3 +Euro area,EMU,2007,12877397931377.4 +Euro area,EMU,2008,14115366559756.8 +Euro area,EMU,2009,12905452856781.1 +Euro area,EMU,2010,12642935603562.1 +Euro area,EMU,2011,13622723195115.4 +Euro area,EMU,2012,12637588983379.4 +Euro area,EMU,2013,13187495064380.7 +Euro area,EMU,2014,13457720442907.5 +Euro area,EMU,2015,11616144612366.3 +Euro area,EMU,2016,11885664082849.1 +Europe & Central Asia,ECS,1960,432763685324.509 +Europe & Central Asia,ECS,1961,460668876592.491 +Europe & Central Asia,ECS,1962,503638735647.907 +Europe & Central Asia,ECS,1963,555368983066.662 +Europe & Central Asia,ECS,1964,615028489294.961 +Europe & Central Asia,ECS,1965,669257339022.057 +Europe & Central Asia,ECS,1966,727080705610.445 +Europe & Central Asia,ECS,1967,782273534888.326 +Europe & Central Asia,ECS,1968,815868539007.526 +Europe & Central Asia,ECS,1969,895741081122.038 +Europe & Central Asia,ECS,1970,1007609884842.09 +Europe & Central Asia,ECS,1971,1136379130354.99 +Europe & Central Asia,ECS,1972,1361730567491.87 +Europe & Central Asia,ECS,1973,1729501999343.51 +Europe & Central Asia,ECS,1974,1954079227218.94 +Europe & Central Asia,ECS,1975,2282879504237.62 +Europe & Central Asia,ECS,1976,2372796286718.28 +Europe & Central Asia,ECS,1977,2689034117521.4 +Europe & Central Asia,ECS,1978,3282122941201.44 +Europe & Central Asia,ECS,1979,4015364706047.03 +Europe & Central Asia,ECS,1980,4548343163223.59 +Europe & Central Asia,ECS,1981,4048271618267.42 +Europe & Central Asia,ECS,1982,3900963906539.6 +Europe & Central Asia,ECS,1983,3784300665660.48 +Europe & Central Asia,ECS,1984,3637246299961.42 +Europe & Central Asia,ECS,1985,3764269446867.66 +Europe & Central Asia,ECS,1986,5137673243594.37 +Europe & Central Asia,ECS,1987,6348859470242.99 +Europe & Central Asia,ECS,1988,7067497880251.27 +Europe & Central Asia,ECS,1989,7224451847727.19 +Europe & Central Asia,ECS,1990,8837798957217.56 +Europe & Central Asia,ECS,1991,9118254483722.14 +Europe & Central Asia,ECS,1992,9780068883431.27 +Europe & Central Asia,ECS,1993,8987910993879.63 +Europe & Central Asia,ECS,1994,9400417935058.64 +Europe & Central Asia,ECS,1995,10827903895370.2 +Europe & Central Asia,ECS,1996,11055076580949 +Europe & Central Asia,ECS,1997,10489769869606.2 +Europe & Central Asia,ECS,1998,10749669669893.6 +Europe & Central Asia,ECS,1999,10628573427395.1 +Europe & Central Asia,ECS,2000,10011304103592.3 +Europe & Central Asia,ECS,2001,10112904613806.8 +Europe & Central Asia,ECS,2002,11061551679319.4 +Europe & Central Asia,ECS,2003,13475936343306.8 +Europe & Central Asia,ECS,2004,15710079754567.4 +Europe & Central Asia,ECS,2005,16731221185836.3 +Europe & Central Asia,ECS,2006,18108863489937 +Europe & Central Asia,ECS,2007,21160525702403.2 +Europe & Central Asia,ECS,2008,23218568155419.7 +Europe & Central Asia,ECS,2009,20419024790312.5 +Europe & Central Asia,ECS,2010,20905471026131.4 +Europe & Central Asia,ECS,2011,23146206945497.4 +Europe & Central Asia,ECS,2012,22278308473166.2 +Europe & Central Asia,ECS,2013,23253753489878.5 +Europe & Central Asia,ECS,2014,23602629398500.7 +Europe & Central Asia,ECS,2015,20278407939904.2 +Europe & Central Asia,ECS,2016,20162858489508.1 +Europe & Central Asia (excluding high income),ECA,1989,903702469910.52 +Europe & Central Asia (excluding high income),ECA,1990,960438672723.367 +Europe & Central Asia (excluding high income),ECA,1991,926765119090.884 +Europe & Central Asia (excluding high income),ECA,1992,853278424758.789 +Europe & Central Asia (excluding high income),ECA,1993,838260559328.055 +Europe & Central Asia (excluding high income),ECA,1994,727687093069.718 +Europe & Central Asia (excluding high income),ECA,1995,776931366529.155 +Europe & Central Asia (excluding high income),ECA,1996,787851671889.667 +Europe & Central Asia (excluding high income),ECA,1997,820131784781.875 +Europe & Central Asia (excluding high income),ECA,1998,771871770861.159 +Europe & Central Asia (excluding high income),ECA,1999,650450056519.407 +Europe & Central Asia (excluding high income),ECA,2000,720049109208.474 +Europe & Central Asia (excluding high income),ECA,2001,717065633312.417 +Europe & Central Asia (excluding high income),ECA,2002,820427017878.696 +Europe & Central Asia (excluding high income),ECA,2003,1037515255499.23 +Europe & Central Asia (excluding high income),ECA,2004,1367586660092.33 +Europe & Central Asia (excluding high income),ECA,2005,1726468996323.24 +Europe & Central Asia (excluding high income),ECA,2006,2114341890534.89 +Europe & Central Asia (excluding high income),ECA,2007,2727633767388.62 +Europe & Central Asia (excluding high income),ECA,2008,3372528990767.71 +Europe & Central Asia (excluding high income),ECA,2009,2655132038891.56 +Europe & Central Asia (excluding high income),ECA,2010,3156252483058.18 +Europe & Central Asia (excluding high income),ECA,2011,3871963192958.71 +Europe & Central Asia (excluding high income),ECA,2012,4070879223563.86 +Europe & Central Asia (excluding high income),ECA,2013,4302720557394.26 +Europe & Central Asia (excluding high income),ECA,2014,4078799138447.73 +Europe & Central Asia (excluding high income),ECA,2015,3120102822297.1 +Europe & Central Asia (excluding high income),ECA,2016,2979118476324.24 +Europe & Central Asia (IDA & IBRD countries),TEC,1989,960328174371.057 +Europe & Central Asia (IDA & IBRD countries),TEC,1990,1020619449300.74 +Europe & Central Asia (IDA & IBRD countries),TEC,1991,1007801660268.39 +Europe & Central Asia (IDA & IBRD countries),TEC,1992,944312695547.955 +Europe & Central Asia (IDA & IBRD countries),TEC,1993,931235788654.179 +Europe & Central Asia (IDA & IBRD countries),TEC,1994,837243545767.996 +Europe & Central Asia (IDA & IBRD countries),TEC,1995,918930607816.217 +Europe & Central Asia (IDA & IBRD countries),TEC,1996,947704910874.353 +Europe & Central Asia (IDA & IBRD countries),TEC,1997,979132756086.026 +Europe & Central Asia (IDA & IBRD countries),TEC,1998,946228594056.486 +Europe & Central Asia (IDA & IBRD countries),TEC,1999,820213773405.425 +Europe & Central Asia (IDA & IBRD countries),TEC,2000,891934707791.111 +Europe & Central Asia (IDA & IBRD countries),TEC,2001,907586896655.439 +Europe & Central Asia (IDA & IBRD countries),TEC,2002,1019107655133.6 +Europe & Central Asia (IDA & IBRD countries),TEC,2003,1255033897823.74 +Europe & Central Asia (IDA & IBRD countries),TEC,2004,1622688912935.72 +Europe & Central Asia (IDA & IBRD countries),TEC,2005,2032603631916.98 +Europe & Central Asia (IDA & IBRD countries),TEC,2006,2459168320833.04 +Europe & Central Asia (IDA & IBRD countries),TEC,2007,3156883414983.23 +Europe & Central Asia (IDA & IBRD countries),TEC,2008,3906344780241.39 +Europe & Central Asia (IDA & IBRD countries),TEC,2009,3094928199271.03 +Europe & Central Asia (IDA & IBRD countries),TEC,2010,3635573611967.41 +Europe & Central Asia (IDA & IBRD countries),TEC,2011,4400783138334.08 +Europe & Central Asia (IDA & IBRD countries),TEC,2012,4571223504946.21 +Europe & Central Asia (IDA & IBRD countries),TEC,2013,4826935346702.26 +Europe & Central Asia (IDA & IBRD countries),TEC,2014,4623950916968.12 +Europe & Central Asia (IDA & IBRD countries),TEC,2015,3597439604363.69 +Europe & Central Asia (IDA & IBRD countries),TEC,2016,3448627156740.36 +European Union,EUU,1960,358939666615.47 +European Union,EUU,1961,390789544218.134 +European Union,EUU,1962,426908194104.211 +European Union,EUU,1963,470297095519.743 +European Union,EUU,1964,521197684985.034 +European Union,EUU,1965,567590518505.608 +European Union,EUU,1966,615283909698.108 +European Union,EUU,1967,661166979382.423 +European Union,EUU,1968,687213740362.304 +European Union,EUU,1969,754796434973.419 +European Union,EUU,1970,855234352054.266 +European Union,EUU,1971,967419657510.242 +European Union,EUU,1972,1158320102742.09 +European Union,EUU,1973,1470725772176.78 +European Union,EUU,1974,1652902769120.73 +European Union,EUU,1975,1926973312297.35 +European Union,EUU,1976,1995730917312.52 +European Union,EUU,1977,2260041856810.23 +European Union,EUU,1978,2769687171486.68 +European Union,EUU,1979,3382589603382.52 +European Union,EUU,1980,3860946303423.78 +European Union,EUU,1981,3416278760871.41 +European Union,EUU,1982,3287910701007.99 +European Union,EUU,1983,3186966976981.42 +European Union,EUU,1984,3059979571007.95 +European Union,EUU,1985,3162521224924.48 +European Union,EUU,1986,4336668252551.86 +European Union,EUU,1987,5365914989685.94 +European Union,EUU,1988,5985449350585.64 +European Union,EUU,1989,6111509859371.48 +European Union,EUU,1990,7578533627539.12 +European Union,EUU,1991,7865147971074.68 +European Union,EUU,1992,8570482000033.34 +European Union,EUU,1993,7814819013689.57 +European Union,EUU,1994,8298433649328.58 +European Union,EUU,1995,9610497311406.19 +European Union,EUU,1996,9824668960664.23 +European Union,EUU,1997,9273364401458.35 +European Union,EUU,1998,9589846268503.63 +European Union,EUU,1999,9576780993379.78 +European Union,EUU,2000,8899281080301.74 +European Union,EUU,2001,9000712583377.4 +European Union,EUU,2002,9811088515429.67 +European Union,EUU,2003,11945762088043.2 +European Union,EUU,2004,13795554923350 +European Union,EUU,2005,14426590936518.2 +European Union,EUU,2006,15388732742870.8 +European Union,EUU,2007,17781304404686.5 +European Union,EUU,2008,19117797795887.7 +European Union,EUU,2009,17080879375428 +European Union,EUU,2010,16977855795546.3 +European Union,EUU,2011,18340538607136.1 +European Union,EUU,2012,17271715977529.1 +European Union,EUU,2013,18002706275463.5 +European Union,EUU,2014,18588239232261 +European Union,EUU,2015,16334844026788 +European Union,EUU,2016,16397979816576.1 +Fragile and conflict affected situations,FCS,2000,212661618000.573 +Fragile and conflict affected situations,FCS,2001,196781933108.681 +Fragile and conflict affected situations,FCS,2002,190816468796.57 +Fragile and conflict affected situations,FCS,2003,217472506931.578 +Fragile and conflict affected situations,FCS,2004,247331719330.617 +Fragile and conflict affected situations,FCS,2005,300124282952.738 +Fragile and conflict affected situations,FCS,2006,351606441448.304 +Fragile and conflict affected situations,FCS,2007,435172555818.384 +Fragile and conflict affected situations,FCS,2008,561422238512.442 +Fragile and conflict affected situations,FCS,2009,523959040574.02 +Fragile and conflict affected situations,FCS,2010,624219448362.822 +Fragile and conflict affected situations,FCS,2011,676660621845.22 +Fragile and conflict affected situations,FCS,2012,730528738068.19 +Fragile and conflict affected situations,FCS,2013,781048126926.108 +Fragile and conflict affected situations,FCS,2014,821766296573.443 +Fragile and conflict affected situations,FCS,2015,750921360242.507 +Fragile and conflict affected situations,FCS,2016,736492620797.34 +Heavily indebted poor countries (HIPC),HPC,1960,17566642115.4168 +Heavily indebted poor countries (HIPC),HPC,1961,18033526303.1068 +Heavily indebted poor countries (HIPC),HPC,1962,19660722938.5933 +Heavily indebted poor countries (HIPC),HPC,1963,23797854828.0912 +Heavily indebted poor countries (HIPC),HPC,1964,21181173056.3962 +Heavily indebted poor countries (HIPC),HPC,1965,24791433536.9807 +Heavily indebted poor countries (HIPC),HPC,1966,27037002542.0683 +Heavily indebted poor countries (HIPC),HPC,1967,26469517421.1298 +Heavily indebted poor countries (HIPC),HPC,1968,27687706183.1679 +Heavily indebted poor countries (HIPC),HPC,1969,30902141055.3267 +Heavily indebted poor countries (HIPC),HPC,1970,32389167090.0469 +Heavily indebted poor countries (HIPC),HPC,1971,34920433870.4235 +Heavily indebted poor countries (HIPC),HPC,1972,37813701276.9785 +Heavily indebted poor countries (HIPC),HPC,1973,45584823246.267 +Heavily indebted poor countries (HIPC),HPC,1974,56142116082.6774 +Heavily indebted poor countries (HIPC),HPC,1975,63535307034.3364 +Heavily indebted poor countries (HIPC),HPC,1976,67559791246.943 +Heavily indebted poor countries (HIPC),HPC,1977,79909125894.0715 +Heavily indebted poor countries (HIPC),HPC,1978,90789385371.85 +Heavily indebted poor countries (HIPC),HPC,1979,101664820366.851 +Heavily indebted poor countries (HIPC),HPC,1980,106677929490.771 +Heavily indebted poor countries (HIPC),HPC,1981,106633807023.73 +Heavily indebted poor countries (HIPC),HPC,1982,106403185666.529 +Heavily indebted poor countries (HIPC),HPC,1983,100261185483.72 +Heavily indebted poor countries (HIPC),HPC,1984,100078815923.674 +Heavily indebted poor countries (HIPC),HPC,1985,104994491996.922 +Heavily indebted poor countries (HIPC),HPC,1986,120358284739.616 +Heavily indebted poor countries (HIPC),HPC,1987,132550820434.308 +Heavily indebted poor countries (HIPC),HPC,1988,132065171231.102 +Heavily indebted poor countries (HIPC),HPC,1989,127152957339.515 +Heavily indebted poor countries (HIPC),HPC,1990,129590021510.749 +Heavily indebted poor countries (HIPC),HPC,1991,133299444700.789 +Heavily indebted poor countries (HIPC),HPC,1992,121796046071.449 +Heavily indebted poor countries (HIPC),HPC,1993,123961926712.477 +Heavily indebted poor countries (HIPC),HPC,1994,110357996127.295 +Heavily indebted poor countries (HIPC),HPC,1995,126157292697.297 +Heavily indebted poor countries (HIPC),HPC,1996,132123113216.448 +Heavily indebted poor countries (HIPC),HPC,1997,138643799979.895 +Heavily indebted poor countries (HIPC),HPC,1998,142823908564.672 +Heavily indebted poor countries (HIPC),HPC,1999,143030868524.954 +Heavily indebted poor countries (HIPC),HPC,2000,155061199539.282 +Heavily indebted poor countries (HIPC),HPC,2001,147407334553.846 +Heavily indebted poor countries (HIPC),HPC,2002,160216529979.782 +Heavily indebted poor countries (HIPC),HPC,2003,182328184670.128 +Heavily indebted poor countries (HIPC),HPC,2004,209456626079.117 +Heavily indebted poor countries (HIPC),HPC,2005,242142895089.303 +Heavily indebted poor countries (HIPC),HPC,2006,289296463304.802 +Heavily indebted poor countries (HIPC),HPC,2007,344296287547.737 +Heavily indebted poor countries (HIPC),HPC,2008,414897655686.46 +Heavily indebted poor countries (HIPC),HPC,2009,421736724661.502 +Heavily indebted poor countries (HIPC),HPC,2010,463157748195.383 +Heavily indebted poor countries (HIPC),HPC,2011,518080704387.585 +Heavily indebted poor countries (HIPC),HPC,2012,558428816750.537 +Heavily indebted poor countries (HIPC),HPC,2013,604887195078.331 +Heavily indebted poor countries (HIPC),HPC,2014,643085647289.931 +Heavily indebted poor countries (HIPC),HPC,2015,635445735588.403 +Heavily indebted poor countries (HIPC),HPC,2016,641483025657.911 +High income,HIC,1960,1060243880168.7 +High income,HIC,1961,1121981243040.71 +High income,HIC,1962,1211776607405.32 +High income,HIC,1963,1304603063142.08 +High income,HIC,1964,1424584016309.32 +High income,HIC,1965,1546689929989.83 +High income,HIC,1966,1696346036809.99 +High income,HIC,1967,1819327353188.27 +High income,HIC,1968,1971265014235.61 +High income,HIC,1969,2163798867287.21 +High income,HIC,1970,2379635398065.42 +High income,HIC,1971,2640680118163.63 +High income,HIC,1972,3063716011733.77 +High income,HIC,1973,3706329864579 +High income,HIC,1974,4181857989922.81 +High income,HIC,1975,4663456510499.43 +High income,HIC,1976,5079507752415.01 +High income,HIC,1977,5751828019898.84 +High income,HIC,1978,6888147385510.59 +High income,HIC,1979,7965334539289.59 +High income,HIC,1980,8898498285406.06 +High income,HIC,1981,9036558177457.95 +High income,HIC,1982,8949612375739.48 +High income,HIC,1983,9239819279588.91 +High income,HIC,1984,9637983479337.74 +High income,HIC,1985,10132406784514.8 +High income,HIC,1986,12297564072616.7 +High income,HIC,1987,14242430872936.9 +High income,HIC,1988,16042589882344.5 +High income,HIC,1989,16805389434609.4 +High income,HIC,1990,18896462178031 +High income,HIC,1991,19983111824868.1 +High income,HIC,1992,21499618272513.5 +High income,HIC,1993,21696143760634 +High income,HIC,1994,23254026236811.5 +High income,HIC,1995,25821731647568.2 +High income,HIC,1996,26052438147494.1 +High income,HIC,1997,25624851684656.3 +High income,HIC,1998,25710064575645.4 +High income,HIC,1999,27011881987743.9 +High income,HIC,2000,27571498060078.4 +High income,HIC,2001,27308139048338.7 +High income,HIC,2002,28461009762104.4 +High income,HIC,2003,31909785738810.1 +High income,HIC,2004,35519515046236.5 +High income,HIC,2005,37558565439921.7 +High income,HIC,2006,39635947402724.5 +High income,HIC,2007,43320749778521.8 +High income,HIC,2008,46007526813566.5 +High income,HIC,2009,43117491018121.2 +High income,HIC,2010,45187761310741.6 +High income,HIC,2011,48762979397332.6 +High income,HIC,2012,48790077028762.4 +High income,HIC,2013,49316266632359.8 +High income,HIC,2014,50308250490810.1 +High income,HIC,2015,47409525372420.8 +High income,HIC,2016,48407640157423.4 +IBRD only,IBD,1960,294792529250.207 +IBRD only,IBD,1961,281626215408.776 +IBRD only,IBD,1962,293934441536.983 +IBRD only,IBD,1963,313396206080.027 +IBRD only,IBD,1964,354919270653.881 +IBRD only,IBD,1965,389878012188.969 +IBRD only,IBD,1966,402017322061.603 +IBRD only,IBD,1967,413014336037.993 +IBRD only,IBD,1968,436571843248.962 +IBRD only,IBD,1969,488040628514.822 +IBRD only,IBD,1970,529362750187.336 +IBRD only,IBD,1971,578582492654.098 +IBRD only,IBD,1972,651149122217.479 +IBRD only,IBD,1973,837821911282.808 +IBRD only,IBD,1974,1057251132019.3 +IBRD only,IBD,1975,1142724094139.65 +IBRD only,IBD,1976,1246289423374.27 +IBRD only,IBD,1977,1413532715597.07 +IBRD only,IBD,1978,1524704140806.03 +IBRD only,IBD,1979,1825690390932.99 +IBRD only,IBD,1980,2139762149345.92 +IBRD only,IBD,1981,2321258403803.81 +IBRD only,IBD,1982,2302549053326.87 +IBRD only,IBD,1983,2272103495406.6 +IBRD only,IBD,1984,2313687727936.92 +IBRD only,IBD,1985,2439461778036.01 +IBRD only,IBD,1986,2553168739556.33 +IBRD only,IBD,1987,2616094413959.71 +IBRD only,IBD,1988,2844737806054.1 +IBRD only,IBD,1989,3045326136048.95 +IBRD only,IBD,1990,3443776644827.72 +IBRD only,IBD,1991,3711451063868.31 +IBRD only,IBD,1992,3696285768627.5 +IBRD only,IBD,1993,3965845725257.7 +IBRD only,IBD,1994,4343949156182.07 +IBRD only,IBD,1995,4877267746552.34 +IBRD only,IBD,1996,5322354990131.63 +IBRD only,IBD,1997,5633308770924 +IBRD only,IBD,1998,5473749235787.22 +IBRD only,IBD,1999,5316743211058.67 +IBRD only,IBD,2000,5778989842384.42 +IBRD only,IBD,2001,5856302815575.35 +IBRD only,IBD,2002,5947536549262.23 +IBRD only,IBD,2003,6716225139151.19 +IBRD only,IBD,2004,7990347950856.02 +IBRD only,IBD,2005,9549735974950.61 +IBRD only,IBD,2006,11321411711668.7 +IBRD only,IBD,2007,14088931626236.9 +IBRD only,IBD,2008,16926584187094.4 +IBRD only,IBD,2009,16425341705202.5 +IBRD only,IBD,2010,19954364488950.4 +IBRD only,IBD,2011,23607619466961.8 +IBRD only,IBD,2012,25002131466488.6 +IBRD only,IBD,2013,26486061975152.6 +IBRD only,IBD,2014,27385523724212.7 +IBRD only,IBD,2015,25878328332858.1 +IBRD only,IBD,2016,25924292415039.1 +IDA & IBRD total,IBT,1960,332410539293.112 +IDA & IBRD total,IBT,1961,321985771144.331 +IDA & IBRD total,IBT,1962,337685120265.7 +IDA & IBRD total,IBT,1963,362761033613.715 +IDA & IBRD total,IBT,1964,402977587836.774 +IDA & IBRD total,IBT,1965,444428542057.831 +IDA & IBRD total,IBT,1966,461258734546.45 +IDA & IBRD total,IBT,1967,472865842237.292 +IDA & IBRD total,IBT,1968,499660160465.74 +IDA & IBRD total,IBT,1969,559287041398.569 +IDA & IBRD total,IBT,1970,612186629071.988 +IDA & IBRD total,IBT,1971,661686153516.207 +IDA & IBRD total,IBT,1972,737610959339.937 +IDA & IBRD total,IBT,1973,936838994091.702 +IDA & IBRD total,IBT,1974,1191684644882.95 +IDA & IBRD total,IBT,1975,1303667274673.25 +IDA & IBRD total,IBT,1976,1413816096264.77 +IDA & IBRD total,IBT,1977,1596341785085 +IDA & IBRD total,IBT,1978,1730854109299.48 +IDA & IBRD total,IBT,1979,2065313058061.8 +IDA & IBRD total,IBT,1980,2422283170989.76 +IDA & IBRD total,IBT,1981,2610827592142.73 +IDA & IBRD total,IBT,1982,2582656721626.52 +IDA & IBRD total,IBT,1983,2522667584587.84 +IDA & IBRD total,IBT,1984,2556908680047.68 +IDA & IBRD total,IBT,1985,2691625504690.32 +IDA & IBRD total,IBT,1986,2813180853749.35 +IDA & IBRD total,IBT,1987,2897841130486.82 +IDA & IBRD total,IBT,1988,3135683945829.85 +IDA & IBRD total,IBT,1989,3336319692781.06 +IDA & IBRD total,IBT,1990,3753855345937.29 +IDA & IBRD total,IBT,1991,4028757715172.53 +IDA & IBRD total,IBT,1992,4004458417669.02 +IDA & IBRD total,IBT,1993,4264177499395.29 +IDA & IBRD total,IBT,1994,4630909142217.15 +IDA & IBRD total,IBT,1995,5209713498214.82 +IDA & IBRD total,IBT,1996,5688958786196.36 +IDA & IBRD total,IBT,1997,6012285279839.32 +IDA & IBRD total,IBT,1998,5850703459189.88 +IDA & IBRD total,IBT,1999,5702543484501.18 +IDA & IBRD total,IBT,2000,6204623716453.03 +IDA & IBRD total,IBT,2001,6271139335707.81 +IDA & IBRD total,IBT,2002,6392053928474.98 +IDA & IBRD total,IBT,2003,7219473737910.63 +IDA & IBRD total,IBT,2004,8575492654333.95 +IDA & IBRD total,IBT,2005,10227019071857.2 +IDA & IBRD total,IBT,2006,12135265896478.6 +IDA & IBRD total,IBT,2007,15039672145151.6 +IDA & IBRD total,IBT,2008,18069265699993 +IDA & IBRD total,IBT,2009,17550676210066 +IDA & IBRD total,IBT,2010,21396210578999.2 +IDA & IBRD total,IBT,2011,25246476428292.6 +IDA & IBRD total,IBT,2012,26768123725809.4 +IDA & IBRD total,IBT,2013,28404378612941.1 +IDA & IBRD total,IBT,2014,29459720089842 +IDA & IBRD total,IBT,2015,27894376853304.5 +IDA & IBRD total,IBT,2016,27911770057428.9 +IDA blend,IDB,1960,12528091853.1585 +IDA blend,IDB,1961,13388928377.9155 +IDA blend,IDB,1962,14310570026.0649 +IDA blend,IDB,1963,15136261036.8151 +IDA blend,IDB,1964,16547083675.0911 +IDA blend,IDB,1965,18008427704.7256 +IDA blend,IDB,1966,19548468193.7723 +IDA blend,IDB,1967,19670828004.2858 +IDA blend,IDB,1968,20910846571.8878 +IDA blend,IDB,1969,23861812085.1294 +IDA blend,IDB,1970,32843393663.0869 +IDA blend,IDB,1971,30365264329.5773 +IDA blend,IDB,1972,33936248295.21 +IDA blend,IDB,1973,36073763303.9852 +IDA blend,IDB,1974,52387318527.9086 +IDA blend,IDB,1975,60251909395.5155 +IDA blend,IDB,1976,73264439498.9809 +IDA blend,IDB,1977,76793603162.5652 +IDA blend,IDB,1978,83188559519.2582 +IDA blend,IDB,1979,102363089138.532 +IDA blend,IDB,1980,131669829698.641 +IDA blend,IDB,1981,135610723887.684 +IDA blend,IDB,1982,127708517011.63 +IDA blend,IDB,1983,106285802122.516 +IDA blend,IDB,1984,99724892442.8074 +IDA blend,IDB,1985,99654429284.9044 +IDA blend,IDB,1986,96843172567.8211 +IDA blend,IDB,1987,107048715951.938 +IDA blend,IDB,1988,114678605164.99 +IDA blend,IDB,1989,117241208130.828 +IDA blend,IDB,1990,124515366242.566 +IDA blend,IDB,1991,128087577902.076 +IDA blend,IDB,1992,129464158157.523 +IDA blend,IDB,1993,117459126359.094 +IDA blend,IDB,1994,117901745281.71 +IDA blend,IDB,1995,139685272955.961 +IDA blend,IDB,1996,155752080707.91 +IDA blend,IDB,1997,157340845858.204 +IDA blend,IDB,1998,150468042836.428 +IDA blend,IDB,1999,157062060341.58 +IDA blend,IDB,2000,174891573406.934 +IDA blend,IDB,2001,168921966719.703 +IDA blend,IDB,2002,183712405328.485 +IDA blend,IDB,2003,209404819444.115 +IDA blend,IDB,2004,252474835319.475 +IDA blend,IDB,2005,297634375913.672 +IDA blend,IDB,2006,373661921221.27 +IDA blend,IDB,2007,427256953306.27 +IDA blend,IDB,2008,508512182149.602 +IDA blend,IDB,2009,473469947548.861 +IDA blend,IDB,2010,699996618179.802 +IDA blend,IDB,2011,802831759834.01 +IDA blend,IDB,2012,883071662424.879 +IDA blend,IDB,2013,960383402110.485 +IDA blend,IDB,2014,1043383926479.73 +IDA blend,IDB,2015,976614588892.231 +IDA blend,IDB,2016,914220211373.289 +IDA only,IDX,1960,26900729558.6756 +IDA only,IDX,1961,28202127747.3091 +IDA only,IDX,1962,30578919823.2805 +IDA only,IDX,1963,35608750994.9935 +IDA only,IDX,1964,32782637428.41 +IDA only,IDX,1965,38049648216.3678 +IDA only,IDX,1966,41260252648.3372 +IDA only,IDX,1967,41803467079.1778 +IDA only,IDX,1968,43857842843.3742 +IDA only,IDX,1969,49232891560.4311 +IDA only,IDX,1970,51155937980.7403 +IDA only,IDX,1971,54433112942.909 +IDA only,IDX,1972,53913727572.5046 +IDA only,IDX,1973,65130587108.3052 +IDA only,IDX,1974,84317852974.6352 +IDA only,IDX,1975,103845586044.62 +IDA only,IDX,1976,95540888530.4483 +IDA only,IDX,1977,108030645862.408 +IDA only,IDX,1978,125870174760.378 +IDA only,IDX,1979,139556026001.644 +IDA only,IDX,1980,151420555888.676 +IDA only,IDX,1981,154577110449.62 +IDA only,IDX,1982,153716825855.11 +IDA only,IDX,1983,147442512236.276 +IDA only,IDX,1984,147495091462.227 +IDA only,IDX,1985,157306474735.099 +IDA only,IDX,1986,168977242488.592 +IDA only,IDX,1987,180063158863.859 +IDA only,IDX,1988,181385498558.729 +IDA only,IDX,1989,179072082631.41 +IDA only,IDX,1990,188126607992.926 +IDA only,IDX,1991,191081249885.044 +IDA only,IDX,1992,179808280295.291 +IDA only,IDX,1993,181679334834.709 +IDA only,IDX,1994,167877722801.344 +IDA only,IDX,1995,191639298395.647 +IDA only,IDX,1996,209648120648.985 +IDA only,IDX,1997,220284365616.801 +IDA only,IDX,1998,226082116332.62 +IDA only,IDX,1999,228981957026.655 +IDA only,IDX,2000,251151822827.442 +IDA only,IDX,2001,246099126238.948 +IDA only,IDX,2002,261187520893.639 +IDA only,IDX,2003,294249141169.591 +IDA only,IDX,2004,332732438424.107 +IDA only,IDX,2005,379223704355.932 +IDA only,IDX,2006,439386921175.794 +IDA only,IDX,2007,521840470219.516 +IDA only,IDX,2008,632814903358.774 +IDA only,IDX,2009,653724047017.456 +IDA only,IDX,2010,739442152602.564 +IDA only,IDX,2011,829706713781.067 +IDA only,IDX,2012,875853724368.38 +IDA only,IDX,2013,952302996802.463 +IDA only,IDX,2014,1028027058553.17 +IDA only,IDX,2015,1040940192004.62 +IDA only,IDX,2016,1077908367748.55 +IDA total,IDA,1960,38748692260.3948 +IDA total,IDA,1961,40905486343.7645 +IDA total,IDA,1962,44123855995.0844 +IDA total,IDA,1963,49688700780.7972 +IDA total,IDA,1964,48638830926.4057 +IDA total,IDA,1965,55127127619.5494 +IDA total,IDA,1966,59801429749.3153 +IDA total,IDA,1967,60439331470.9625 +IDA total,IDA,1968,63710108686.0779 +IDA total,IDA,1969,71945084444.5374 +IDA total,IDA,1970,83611704212.3582 +IDA total,IDA,1971,83933783702.5892 +IDA total,IDA,1972,87371340568.4539 +IDA total,IDA,1973,100144499811.812 +IDA total,IDA,1974,135889407708.479 +IDA total,IDA,1975,162649110156.035 +IDA total,IDA,1976,169321323255.879 +IDA total,IDA,1977,184780649645.364 +IDA total,IDA,1978,208345111898.598 +IDA total,IDA,1979,242195946786.616 +IDA total,IDA,1980,285548847107.09 +IDA total,IDA,1981,292801265885.592 +IDA total,IDA,1982,283456512539.266 +IDA total,IDA,1983,254398227877.098 +IDA total,IDA,1984,247369742089.672 +IDA total,IDA,1985,256654502726.648 +IDA total,IDA,1986,264781775186.289 +IDA total,IDA,1987,286234708513.801 +IDA total,IDA,1988,295577043063.381 +IDA total,IDA,1989,295978940818.795 +IDA total,IDA,1990,312339707016.851 +IDA total,IDA,1991,318967140383.491 +IDA total,IDA,1992,309553959926.279 +IDA total,IDA,1993,298741566135.181 +IDA total,IDA,1994,285802386263.917 +IDA total,IDA,1995,331562738922.137 +IDA total,IDA,1996,365804847537.744 +IDA total,IDA,1997,377740987931.319 +IDA total,IDA,1998,376129203724.069 +IDA total,IDA,1999,385846241612.534 +IDA total,IDA,2000,425955016165.44 +IDA total,IDA,2001,414877779648.671 +IDA total,IDA,2002,444822239206.007 +IDA total,IDA,2003,503607352753.133 +IDA total,IDA,2004,585417780901.716 +IDA total,IDA,2005,677263856840.947 +IDA total,IDA,2006,814002488452.235 +IDA total,IDA,2007,949952688725.4 +IDA total,IDA,2008,1141761566655.15 +IDA total,IDA,2009,1125176003190.5 +IDA total,IDA,2010,1444980672769.83 +IDA total,IDA,2011,1639584122424.2 +IDA total,IDA,2012,1768118438213.61 +IDA total,IDA,2013,1922693336373.33 +IDA total,IDA,2014,2082520619431.07 +IDA total,IDA,2015,2025758505542.6 +IDA total,IDA,2016,1996430776919.24 +Late-demographic dividend,LTE,1960,170979834687.82 +Late-demographic dividend,LTE,1961,157897071090.677 +Late-demographic dividend,LTE,1962,165672797274.762 +Late-demographic dividend,LTE,1963,179542413759.862 +Late-demographic dividend,LTE,1964,198102076676.436 +Late-demographic dividend,LTE,1965,220983844815.084 +Late-demographic dividend,LTE,1966,245370863668.602 +Late-demographic dividend,LTE,1967,247715535734.439 +Late-demographic dividend,LTE,1968,253063859646.871 +Late-demographic dividend,LTE,1969,282834192565.336 +Late-demographic dividend,LTE,1970,321365344911.656 +Late-demographic dividend,LTE,1971,357842300708.806 +Late-demographic dividend,LTE,1972,410662881425.586 +Late-demographic dividend,LTE,1973,521687954591.208 +Late-demographic dividend,LTE,1974,614358488944.055 +Late-demographic dividend,LTE,1975,675062859870.315 +Late-demographic dividend,LTE,1976,736553700531.906 +Late-demographic dividend,LTE,1977,854920620708.272 +Late-demographic dividend,LTE,1978,890798665710.268 +Late-demographic dividend,LTE,1979,1064378208589.85 +Late-demographic dividend,LTE,1980,1206585272167.42 +Late-demographic dividend,LTE,1981,1279073780899.5 +Late-demographic dividend,LTE,1982,1308692614317.31 +Late-demographic dividend,LTE,1983,1210824718313.28 +Late-demographic dividend,LTE,1984,1274947279487.52 +Late-demographic dividend,LTE,1985,1362593298859.71 +Late-demographic dividend,LTE,1986,1449305917334.82 +Late-demographic dividend,LTE,1987,1527784692119.54 +Late-demographic dividend,LTE,1988,1682824251759.88 +Late-demographic dividend,LTE,1989,1907361656034.27 +Late-demographic dividend,LTE,1990,2027228504115.95 +Late-demographic dividend,LTE,1991,2230277776370.29 +Late-demographic dividend,LTE,1992,2079905732735.5 +Late-demographic dividend,LTE,1993,2155921522368 +Late-demographic dividend,LTE,1994,2468839439179.73 +Late-demographic dividend,LTE,1995,3032807636908.79 +Late-demographic dividend,LTE,1996,3325672519645.58 +Late-demographic dividend,LTE,1997,3480271526233.09 +Late-demographic dividend,LTE,1998,3351316496248.07 +Late-demographic dividend,LTE,1999,3096106154774.71 +Late-demographic dividend,LTE,2000,3403220871015.89 +Late-demographic dividend,LTE,2001,3517771351799.08 +Late-demographic dividend,LTE,2002,3726423996249.01 +Late-demographic dividend,LTE,2003,4249229634687.67 +Late-demographic dividend,LTE,2004,5107491089896.68 +Late-demographic dividend,LTE,2005,6161761848491.52 +Late-demographic dividend,LTE,2006,7436786145930.92 +Late-demographic dividend,LTE,2007,9366206761782.71 +Late-demographic dividend,LTE,2008,11644623639987.3 +Late-demographic dividend,LTE,2009,11256631749196.5 +Late-demographic dividend,LTE,2010,13512634949047.9 +Late-demographic dividend,LTE,2011,16461624017478 +Late-demographic dividend,LTE,2012,17588592847258.8 +Late-demographic dividend,LTE,2013,18943439059235.6 +Late-demographic dividend,LTE,2014,19696765765637.5 +Late-demographic dividend,LTE,2015,18442948166730.4 +Late-demographic dividend,LTE,2016,18428970585288.9 +Latin America & Caribbean,LCN,1960,81335701189.6428 +Latin America & Caribbean,LCN,1961,86401548189.3568 +Latin America & Caribbean,LCN,1962,99481669694.8621 +Latin America & Caribbean,LCN,1963,100098935911.675 +Latin America & Caribbean,LCN,1964,111187567574.716 +Latin America & Caribbean,LCN,1965,119770844951.528 +Latin America & Caribbean,LCN,1966,131441042298.551 +Latin America & Caribbean,LCN,1967,134656950399.366 +Latin America & Caribbean,LCN,1968,145003712535.205 +Latin America & Caribbean,LCN,1969,162478343090.837 +Latin America & Caribbean,LCN,1970,176599027868.457 +Latin America & Caribbean,LCN,1971,197516005457.39 +Latin America & Caribbean,LCN,1972,222012459414.042 +Latin America & Caribbean,LCN,1973,290635423997.013 +Latin America & Caribbean,LCN,1974,377414609202.896 +Latin America & Caribbean,LCN,1975,395907967425.139 +Latin America & Caribbean,LCN,1976,440234859237.179 +Latin America & Caribbean,LCN,1977,484661330903.231 +Latin America & Caribbean,LCN,1978,549446058073.142 +Latin America & Caribbean,LCN,1979,653954905333.575 +Latin America & Caribbean,LCN,1980,775694200782.059 +Latin America & Caribbean,LCN,1981,893319180188.671 +Latin America & Caribbean,LCN,1982,835598635135.828 +Latin America & Caribbean,LCN,1983,742131362504.011 +Latin America & Caribbean,LCN,1984,732119681478.353 +Latin America & Caribbean,LCN,1985,753457210178.004 +Latin America & Caribbean,LCN,1986,766884114945.657 +Latin America & Caribbean,LCN,1987,807221928641.526 +Latin America & Caribbean,LCN,1988,921057504142.402 +Latin America & Caribbean,LCN,1989,1006663109065.92 +Latin America & Caribbean,LCN,1990,1170492068804.72 +Latin America & Caribbean,LCN,1991,1440178343364.67 +Latin America & Caribbean,LCN,1992,1358408884243.74 +Latin America & Caribbean,LCN,1993,1564958746610.74 +Latin America & Caribbean,LCN,1994,1797150601266.59 +Latin America & Caribbean,LCN,1995,1916099987242.12 +Latin America & Caribbean,LCN,1996,2060739339318.38 +Latin America & Caribbean,LCN,1997,2255377930705.67 +Latin America & Caribbean,LCN,1998,2271734532596.57 +Latin America & Caribbean,LCN,1999,2050793762812.47 +Latin America & Caribbean,LCN,2000,2262087168956.71 +Latin America & Caribbean,LCN,2001,2204812692751.2 +Latin America & Caribbean,LCN,2002,1976793288246.23 +Latin America & Caribbean,LCN,2003,2035297413712.73 +Latin America & Caribbean,LCN,2004,2350652052445.82 +Latin America & Caribbean,LCN,2005,2845502363895.91 +Latin America & Caribbean,LCN,2006,3337221449300.33 +Latin America & Caribbean,LCN,2007,3936233657945.05 +Latin America & Caribbean,LCN,2008,4575918476342.71 +Latin America & Caribbean,LCN,2009,4302206310681.48 +Latin America & Caribbean,LCN,2010,5334359905744.97 +Latin America & Caribbean,LCN,2011,6063818698406.67 +Latin America & Caribbean,LCN,2012,6118412885788.98 +Latin America & Caribbean,LCN,2013,6270431817071.43 +Latin America & Caribbean,LCN,2014,6389407132290.57 +Latin America & Caribbean,LCN,2015,5456024297600.86 +Latin America & Caribbean,LCN,2016,5294928047201.73 +Latin America & Caribbean (excluding high income),LAC,1960,73395468426.688 +Latin America & Caribbean (excluding high income),LAC,1961,77129609859.8088 +Latin America & Caribbean (excluding high income),LAC,1962,88911888348.821 +Latin America & Caribbean (excluding high income),LAC,1963,89097573498.6413 +Latin America & Caribbean (excluding high income),LAC,1964,99074812474.4309 +Latin America & Caribbean (excluding high income),LAC,1965,107304593077.581 +Latin America & Caribbean (excluding high income),LAC,1966,117616850185.479 +Latin America & Caribbean (excluding high income),LAC,1967,120609010516.58 +Latin America & Caribbean (excluding high income),LAC,1968,130256250949.786 +Latin America & Caribbean (excluding high income),LAC,1969,145346421052.827 +Latin America & Caribbean (excluding high income),LAC,1970,157880701506.35 +Latin America & Caribbean (excluding high income),LAC,1971,175505487290.549 +Latin America & Caribbean (excluding high income),LAC,1972,198599650385.719 +Latin America & Caribbean (excluding high income),LAC,1973,259117670925.781 +Latin America & Caribbean (excluding high income),LAC,1974,344587170087.191 +Latin America & Caribbean (excluding high income),LAC,1975,371280813794.006 +Latin America & Caribbean (excluding high income),LAC,1976,411643476107.596 +Latin America & Caribbean (excluding high income),LAC,1977,450102375279.173 +Latin America & Caribbean (excluding high income),LAC,1978,509915128707.522 +Latin America & Caribbean (excluding high income),LAC,1979,602811483644.084 +Latin America & Caribbean (excluding high income),LAC,1980,710116907993.984 +Latin America & Caribbean (excluding high income),LAC,1981,818425766809.108 +Latin America & Caribbean (excluding high income),LAC,1982,769759179392.8 +Latin America & Caribbean (excluding high income),LAC,1983,685169082243.003 +Latin America & Caribbean (excluding high income),LAC,1984,673764033131.398 +Latin America & Caribbean (excluding high income),LAC,1985,695943952938.005 +Latin America & Caribbean (excluding high income),LAC,1986,707488075055.622 +Latin America & Caribbean (excluding high income),LAC,1987,740352753238.472 +Latin America & Caribbean (excluding high income),LAC,1988,846851503909.44 +Latin America & Caribbean (excluding high income),LAC,1989,925567803838.453 +Latin America & Caribbean (excluding high income),LAC,1990,1081353158707.23 +Latin America & Caribbean (excluding high income),LAC,1991,1341594021709.41 +Latin America & Caribbean (excluding high income),LAC,1992,1247729796135 +Latin America & Caribbean (excluding high income),LAC,1993,1446291182393.37 +Latin America & Caribbean (excluding high income),LAC,1994,1663902703398.57 +Latin America & Caribbean (excluding high income),LAC,1995,1760538940825.78 +Latin America & Caribbean (excluding high income),LAC,1996,1895254878110.68 +Latin America & Caribbean (excluding high income),LAC,1997,2074269012884.32 +Latin America & Caribbean (excluding high income),LAC,1998,2085413655025.19 +Latin America & Caribbean (excluding high income),LAC,1999,1867635348455.59 +Latin America & Caribbean (excluding high income),LAC,2000,2070772006620.39 +Latin America & Caribbean (excluding high income),LAC,2001,2013631181344.99 +Latin America & Caribbean (excluding high income),LAC,2002,1791362291806.72 +Latin America & Caribbean (excluding high income),LAC,2003,1839436251262.6 +Latin America & Caribbean (excluding high income),LAC,2004,2121459944550.01 +Latin America & Caribbean (excluding high income),LAC,2005,2579728858022.5 +Latin America & Caribbean (excluding high income),LAC,2006,3029641277365.53 +Latin America & Caribbean (excluding high income),LAC,2007,3598012077005.43 +Latin America & Caribbean (excluding high income),LAC,2008,4213388169678.88 +Latin America & Caribbean (excluding high income),LAC,2009,3953038143139.52 +Latin America & Caribbean (excluding high income),LAC,2010,4923451838328.67 +Latin America & Caribbean (excluding high income),LAC,2011,5604881793369.78 +Latin America & Caribbean (excluding high income),LAC,2012,5639788774858.59 +Latin America & Caribbean (excluding high income),LAC,2013,5771253261929.29 +Latin America & Caribbean (excluding high income),LAC,2014,5905860152291 +Latin America & Caribbean (excluding high income),LAC,2015,5012025091739.32 +Latin America & Caribbean (excluding high income),LAC,2016,4851312777942.51 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1960,76482111077.6185 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1961,81138563371.9225 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1962,93494266400.9791 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1963,93815979997.1996 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1964,104219981388.786 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1965,112129154406.885 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1966,123024977802.299 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1967,125678109114.536 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1968,135122479528.732 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1969,151315870034.114 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1970,164325954209.404 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1971,183241160615.466 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1972,205656941379.028 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1973,271328852988.129 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1974,355626000642.165 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1975,371930862648.18 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1976,414445379589.903 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1977,457226562193.466 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1978,516657430530.222 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1979,616982642629.746 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1980,735862731970.81 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1981,851087909516.137 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1982,791710474105.973 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1983,696442194165.987 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1984,682241174471.374 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1985,703159186334.514 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1986,713216307476.36 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1987,750018929385.015 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1988,858688357375.556 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1989,941803363255.407 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1990,1100843309813.08 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1991,1372317945905.81 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1992,1290654691364.3 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1993,1493678182537.17 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1994,1715751583151.98 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1995,1829060058160.92 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1996,1975504627485.21 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1997,2164600526781.61 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1998,2173777212537.54 +Latin America & the Caribbean (IDA & IBRD countries),TLA,1999,1946393638777.13 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2000,2150291053438.54 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2001,2083909607913.16 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2002,1851416583657.79 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2003,1903845944839.22 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2004,2210850350066.21 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2005,2694953121481.19 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2006,3171420273729.5 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2007,3760043430335.24 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2008,4392555500737.54 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2009,4116124679683.7 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2010,5141956791475.98 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2011,5863434327505.38 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2012,5912679156108.39 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2013,6058441110940.89 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2014,6171728371691.76 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2015,5247223786180.95 +Latin America & the Caribbean (IDA & IBRD countries),TLA,2016,5091478259237.56 +Least developed countries: UN classification,LDC,1985,121227419694.536 +Least developed countries: UN classification,LDC,1986,131938238081.808 +Least developed countries: UN classification,LDC,1987,143578647017.282 +Least developed countries: UN classification,LDC,1988,147074754062.361 +Least developed countries: UN classification,LDC,1989,152628715228.138 +Least developed countries: UN classification,LDC,1990,157170715256.827 +Least developed countries: UN classification,LDC,1991,160976404765.403 +Least developed countries: UN classification,LDC,1992,141665506654.277 +Least developed countries: UN classification,LDC,1993,143654148545.13 +Least developed countries: UN classification,LDC,1994,134056722134.952 +Least developed countries: UN classification,LDC,1995,152708087751.642 +Least developed countries: UN classification,LDC,1996,168685657996.561 +Least developed countries: UN classification,LDC,1997,178534049893.884 +Least developed countries: UN classification,LDC,1998,179530418610.067 +Least developed countries: UN classification,LDC,1999,181622928394.098 +Least developed countries: UN classification,LDC,2000,206064992890.969 +Least developed countries: UN classification,LDC,2001,196139081536.109 +Least developed countries: UN classification,LDC,2002,211734892493.178 +Least developed countries: UN classification,LDC,2003,239687925539.993 +Least developed countries: UN classification,LDC,2004,275300002656.28 +Least developed countries: UN classification,LDC,2005,322233431675.558 +Least developed countries: UN classification,LDC,2006,377006716127.018 +Least developed countries: UN classification,LDC,2007,458953974129.743 +Least developed countries: UN classification,LDC,2008,570703787280.472 +Least developed countries: UN classification,LDC,2009,583900864058.256 +Least developed countries: UN classification,LDC,2010,659839922368.982 +Least developed countries: UN classification,LDC,2011,750266890616.884 +Least developed countries: UN classification,LDC,2012,796749375366.047 +Least developed countries: UN classification,LDC,2013,863502921391.032 +Least developed countries: UN classification,LDC,2014,936514097645.983 +Least developed countries: UN classification,LDC,2015,928999138028.508 +Least developed countries: UN classification,LDC,2016,940285148246.681 +Low & middle income,LMY,1960,322880916332.716 +Low & middle income,LMY,1961,311231715583.693 +Low & middle income,LMY,1962,325417665734.193 +Low & middle income,LMY,1963,350156888666 +Low & middle income,LMY,1964,389096758803.45 +Low & middle income,LMY,1965,430331569299.832 +Low & middle income,LMY,1966,445816749394.908 +Low & middle income,LMY,1967,457649154436.817 +Low & middle income,LMY,1968,484077925262.186 +Low & middle income,LMY,1969,541207794796.467 +Low & middle income,LMY,1970,592564334146.401 +Low & middle income,LMY,1971,639515242844.186 +Low & middle income,LMY,1972,714843001925.87 +Low & middle income,LMY,1973,903871947953.725 +Low & middle income,LMY,1974,1155364728140.96 +Low & middle income,LMY,1975,1278200898264.97 +Low & middle income,LMY,1976,1383584014217.24 +Low & middle income,LMY,1977,1557251333561.92 +Low & middle income,LMY,1978,1689674986849.66 +Low & middle income,LMY,1979,2008497065323.04 +Low & middle income,LMY,1980,2344256743828.1 +Low & middle income,LMY,1981,2520680956567.89 +Low & middle income,LMY,1982,2506206543210.46 +Low & middle income,LMY,1983,2460475457385.26 +Low & middle income,LMY,1984,2497490161411.77 +Low & middle income,LMY,1985,2631158758229.95 +Low & middle income,LMY,1986,2752146346147.57 +Low & middle income,LMY,1987,2830361348685.47 +Low & middle income,LMY,1988,3061048683744.94 +Low & middle income,LMY,1989,3252693889005.75 +Low & middle income,LMY,1990,3658538915672.86 +Low & middle income,LMY,1991,3901223943739.81 +Low & middle income,LMY,1992,3855226625179.94 +Low & middle income,LMY,1993,4108081847781.04 +Low & middle income,LMY,1994,4454438133064.89 +Low & middle income,LMY,1995,4983280097683.29 +Low & middle income,LMY,1996,5432096474657.18 +Low & middle income,LMY,1997,5746597952135 +Low & middle income,LMY,1998,5570045115899.25 +Low & middle income,LMY,1999,5438376046486.8 +Low & middle income,LMY,2000,5939720920632.49 +Low & middle income,LMY,2001,5994991423437.34 +Low & middle income,LMY,2002,6113967979982.54 +Low & middle income,LMY,2003,6911432587348.75 +Low & middle income,LMY,2004,8199024522261.18 +Low & middle income,LMY,2005,9771338254565.71 +Low & middle income,LMY,2006,11610585486988 +Low & middle income,LMY,2007,14403262097266.8 +Low & middle income,LMY,2008,17304070901099.9 +Low & middle income,LMY,2009,16904208788743.9 +Low & middle income,LMY,2010,20662142675904.1 +Low & middle income,LMY,2011,24424596002573.7 +Low & middle income,LMY,2012,25968368047735.1 +Low & middle income,LMY,2013,27567318674507.7 +Low & middle income,LMY,2014,28624869169602 +Low & middle income,LMY,2015,27167365722548.3 +Low & middle income,LMY,2016,27190673692762.9 +Low income,LIC,1980,80209493052.731 +Low income,LIC,1981,77218047173.3983 +Low income,LIC,1982,80698662025.246 +Low income,LIC,1983,75225831144.4383 +Low income,LIC,1984,69082552304.0881 +Low income,LIC,1985,71599175719.0479 +Low income,LIC,1986,81243884335.6357 +Low income,LIC,1987,84768074082.989 +Low income,LIC,1988,91473322897.3124 +Low income,LIC,1989,90496828327.9022 +Low income,LIC,1990,96263982212.309 +Low income,LIC,1991,98290478926.7244 +Low income,LIC,1992,86879256494.9218 +Low income,LIC,1993,86545417718.2698 +Low income,LIC,1994,73004355880.147 +Low income,LIC,1995,84186096134.2208 +Low income,LIC,1996,93849664244.7633 +Low income,LIC,1997,97016681510.3045 +Low income,LIC,1998,98076470573.4088 +Low income,LIC,1999,98178378552.344 +Low income,LIC,2000,113334918600.364 +Low income,LIC,2001,102344707240.841 +Low income,LIC,2002,110542725688.212 +Low income,LIC,2003,121412373512.426 +Low income,LIC,2004,138406056360.832 +Low income,LIC,2005,159876776422.899 +Low income,LIC,2006,177405351695.882 +Low income,LIC,2007,211564340820.323 +Low income,LIC,2008,254864815001.772 +Low income,LIC,2009,271114296708.762 +Low income,LIC,2010,289973428214.635 +Low income,LIC,2011,327276455418.728 +Low income,LIC,2012,352304788203.414 +Low income,LIC,2013,379841277359.31 +Low income,LIC,2014,409946364477.957 +Low income,LIC,2015,401557904349.121 +Low income,LIC,2016,405500691890.706 +Lower middle income,LMC,1965,137461884746.768 +Lower middle income,LMC,1966,124653071069.42 +Lower middle income,LMC,1967,132904891803.828 +Lower middle income,LMC,1968,142418186233.418 +Lower middle income,LMC,1969,158951711186.14 +Lower middle income,LMC,1970,174828599744.636 +Lower middle income,LMC,1971,181895531247.864 +Lower middle income,LMC,1972,193226951288.583 +Lower middle income,LMC,1973,230257570746.104 +Lower middle income,LMC,1974,295746915764.238 +Lower middle income,LMC,1975,328315078089.788 +Lower middle income,LMC,1976,355970733034.943 +Lower middle income,LMC,1977,407693469545.836 +Lower middle income,LMC,1978,456337424996.254 +Lower middle income,LMC,1979,519598733097.624 +Lower middle income,LMC,1980,645574198150.025 +Lower middle income,LMC,1981,681873952068.244 +Lower middle income,LMC,1982,688236725783.1 +Lower middle income,LMC,1983,672506305328.491 +Lower middle income,LMC,1984,669999684572.239 +Lower middle income,LMC,1985,705033625730.709 +Lower middle income,LMC,1986,734922204323.85 +Lower middle income,LMC,1987,807849540707.224 +Lower middle income,LMC,1988,841860056894.847 +Lower middle income,LMC,1989,854143629643.268 +Lower middle income,LMC,1990,914031845671.275 +Lower middle income,LMC,1991,879585053610.512 +Lower middle income,LMC,1992,917120105052.312 +Lower middle income,LMC,1993,928250234223.785 +Lower middle income,LMC,1994,1008393895038.79 +Lower middle income,LMC,1995,1132835750025.1 +Lower middle income,LMC,1996,1244059564531.71 +Lower middle income,LMC,1997,1285159992957.23 +Lower middle income,LMC,1998,1162403879271.33 +Lower middle income,LMC,1999,1260946586435.45 +Lower middle income,LMC,2000,1334823902218.48 +Lower middle income,LMC,2001,1347552601226.17 +Lower middle income,LMC,2002,1447377162059.63 +Lower middle income,LMC,2003,1659139779548.2 +Lower middle income,LMC,2004,1897336556896.53 +Lower middle income,LMC,2005,2185062024100.34 +Lower middle income,LMC,2006,2598144857845.71 +Lower middle income,LMC,2007,3198643502815.83 +Lower middle income,LMC,2008,3597614231170.5 +Lower middle income,LMC,2009,3686218059205.86 +Lower middle income,LMC,2010,4659868433805.74 +Lower middle income,LMC,2011,5271066216374.76 +Lower middle income,LMC,2012,5526562820088.11 +Lower middle income,LMC,2013,5765503690093.18 +Lower middle income,LMC,2014,6067382503069.23 +Lower middle income,LMC,2015,6034684295981.41 +Lower middle income,LMC,2016,6252243979358.16 +Middle East & North Africa,MEA,1968,32544887124.715 +Middle East & North Africa,MEA,1969,36324978697.3221 +Middle East & North Africa,MEA,1970,40541253687.1512 +Middle East & North Africa,MEA,1971,46837776480.6965 +Middle East & North Africa,MEA,1972,57004801533.1691 +Middle East & North Africa,MEA,1973,76859486837.6555 +Middle East & North Africa,MEA,1974,140509090225.561 +Middle East & North Africa,MEA,1975,153634644912.125 +Middle East & North Africa,MEA,1976,191078602015.36 +Middle East & North Africa,MEA,1977,221864632728.163 +Middle East & North Africa,MEA,1978,235765780535.398 +Middle East & North Africa,MEA,1979,308143991726.14 +Middle East & North Africa,MEA,1980,399635706600.82 +Middle East & North Africa,MEA,1981,413100094747.124 +Middle East & North Africa,MEA,1982,410711932256.055 +Middle East & North Africa,MEA,1983,416988855437.435 +Middle East & North Africa,MEA,1984,422997945987.704 +Middle East & North Africa,MEA,1985,429106552157.991 +Middle East & North Africa,MEA,1986,438374928771.13 +Middle East & North Africa,MEA,1987,405957775183.96 +Middle East & North Africa,MEA,1988,402886867149.289 +Middle East & North Africa,MEA,1989,415650066556.61 +Middle East & North Africa,MEA,1990,544628789841.346 +Middle East & North Africa,MEA,1991,545480411372.983 +Middle East & North Africa,MEA,1992,593377600004.871 +Middle East & North Africa,MEA,1993,597234481572.268 +Middle East & North Africa,MEA,1994,621835421140.165 +Middle East & North Africa,MEA,1995,708396338042.244 +Middle East & North Africa,MEA,1996,802232077700.633 +Middle East & North Africa,MEA,1997,832583629107.313 +Middle East & North Africa,MEA,1998,809335180977.759 +Middle East & North Africa,MEA,1999,866997519336.959 +Middle East & North Africa,MEA,2000,967123025893.847 +Middle East & North Africa,MEA,2001,970705165852.075 +Middle East & North Africa,MEA,2002,966886322034.273 +Middle East & North Africa,MEA,2003,1089026969409.72 +Middle East & North Africa,MEA,2004,1264692501508.67 +Middle East & North Africa,MEA,2005,1523735247225.23 +Middle East & North Africa,MEA,2006,1783624049835.17 +Middle East & North Africa,MEA,2007,2111520707885.6 +Middle East & North Africa,MEA,2008,2639163398129.61 +Middle East & North Africa,MEA,2009,2353140017976.63 +Middle East & North Africa,MEA,2010,2747991985923.82 +Middle East & North Africa,MEA,2011,3291238768813.27 +Middle East & North Africa,MEA,2012,3517290042987.4 +Middle East & North Africa,MEA,2013,3569108760902.47 +Middle East & North Africa,MEA,2014,3552155105906.59 +Middle East & North Africa,MEA,2015,3153183676492.12 +Middle East & North Africa,MEA,2016,3111499137793.74 +Middle East & North Africa (excluding high income),MNA,1993,291596156344.835 +Middle East & North Africa (excluding high income),MNA,1994,299033433705.304 +Middle East & North Africa (excluding high income),MNA,1995,341005087325.937 +Middle East & North Africa (excluding high income),MNA,1996,395419455083.866 +Middle East & North Africa (excluding high income),MNA,1997,406142008337.3 +Middle East & North Africa (excluding high income),MNA,1998,412226941363.17 +Middle East & North Africa (excluding high income),MNA,1999,435964657109.841 +Middle East & North Africa (excluding high income),MNA,2000,451745270165.348 +Middle East & North Africa (excluding high income),MNA,2001,467443771526.278 +Middle East & North Africa (excluding high income),MNA,2002,453763567498.89 +Middle East & North Africa (excluding high income),MNA,2003,511876924084.121 +Middle East & North Africa (excluding high income),MNA,2004,586243634956.355 +Middle East & North Africa (excluding high income),MNA,2005,691427125900.788 +Middle East & North Africa (excluding high income),MNA,2006,803273276926.291 +Middle East & North Africa (excluding high income),MNA,2007,989862700047.422 +Middle East & North Africa (excluding high income),MNA,2008,1225666634970.85 +Middle East & North Africa (excluding high income),MNA,2009,1179785595912.43 +Middle East & North Africa (excluding high income),MNA,2010,1362935523406.7 +Middle East & North Africa (excluding high income),MNA,2011,1577443963809.85 +Middle East & North Africa (excluding high income),MNA,2012,1668157593637.49 +Middle East & North Africa (excluding high income),MNA,2013,1637016759700.7 +Middle East & North Africa (excluding high income),MNA,2014,1579293076205.83 +Middle East & North Africa (excluding high income),MNA,2015,1445527236068.07 +Middle East & North Africa (IDA & IBRD countries),TMN,1993,288793981432.888 +Middle East & North Africa (IDA & IBRD countries),TMN,1994,296159788194.109 +Middle East & North Africa (IDA & IBRD countries),TMN,1995,337684846816.424 +Middle East & North Africa (IDA & IBRD countries),TMN,1996,391994294829.679 +Middle East & North Africa (IDA & IBRD countries),TMN,1997,402348143945.757 +Middle East & North Africa (IDA & IBRD countries),TMN,1998,408106910445.414 +Middle East & North Africa (IDA & IBRD countries),TMN,1999,431640382177.662 +Middle East & North Africa (IDA & IBRD countries),TMN,2000,447384545921.062 +Middle East & North Africa (IDA & IBRD countries),TMN,2001,463423567528.959 +Middle East & North Africa (IDA & IBRD countries),TMN,2002,450214949083.257 +Middle East & North Africa (IDA & IBRD countries),TMN,2003,507920055467.194 +Middle East & North Africa (IDA & IBRD countries),TMN,2004,581942286783.674 +Middle East & North Africa (IDA & IBRD countries),TMN,2005,686628893957.615 +Middle East & North Africa (IDA & IBRD countries),TMN,2006,798404019734.187 +Middle East & North Africa (IDA & IBRD countries),TMN,2007,984408659212.038 +Middle East & North Africa (IDA & IBRD countries),TMN,2008,1219063793136.09 +Middle East & North Africa (IDA & IBRD countries),TMN,2009,1172546853378.41 +Middle East & North Africa (IDA & IBRD countries),TMN,2010,1354032869496.32 +Middle East & North Africa (IDA & IBRD countries),TMN,2011,1566983828956.61 +Middle East & North Africa (IDA & IBRD countries),TMN,2012,1656868816266.87 +Middle East & North Africa (IDA & IBRD countries),TMN,2013,1624432436239.87 +Middle East & North Africa (IDA & IBRD countries),TMN,2014,1566425106492.08 +Middle East & North Africa (IDA & IBRD countries),TMN,2015,1432641907767.45 +Middle income,MIC,1960,310379641287.339 +Middle income,MIC,1961,298629856589.636 +Middle income,MIC,1962,311470336452.733 +Middle income,MIC,1963,332436061824.552 +Middle income,MIC,1964,375258292135.611 +Middle income,MIC,1965,413664176294.508 +Middle income,MIC,1966,427456737432.456 +Middle income,MIC,1967,440150321992.544 +Middle income,MIC,1968,465920438850.911 +Middle income,MIC,1969,520867515611.093 +Middle income,MIC,1970,571296418063.845 +Middle income,MIC,1971,616131606095.362 +Middle income,MIC,1972,688973366920.011 +Middle income,MIC,1973,872977889163.73 +Middle income,MIC,1974,1118745885064.35 +Middle income,MIC,1975,1236174910742.05 +Middle income,MIC,1976,1341860828067.38 +Middle income,MIC,1977,1509117019025.73 +Middle income,MIC,1978,1634224303394.68 +Middle income,MIC,1979,1947681001919.87 +Middle income,MIC,1980,2280187292914.43 +Middle income,MIC,1981,2459499139801.4 +Middle income,MIC,1982,2441787641412.67 +Middle income,MIC,1983,2400889964155.46 +Middle income,MIC,1984,2443660614880.83 +Middle income,MIC,1985,2575525887782.12 +Middle income,MIC,1986,2688214490798.85 +Middle income,MIC,1987,2763479253508.59 +Middle income,MIC,1988,2988896953383.47 +Middle income,MIC,1989,3182426401658.11 +Middle income,MIC,1990,3583954413081.7 +Middle income,MIC,1991,3825385475042.01 +Middle income,MIC,1992,3789343789199.26 +Middle income,MIC,1993,4043243535797.25 +Middle income,MIC,1994,4402360060455.03 +Middle income,MIC,1995,4922821848492.25 +Middle income,MIC,1996,5363658537833.46 +Middle income,MIC,1997,5674926531226.03 +Middle income,MIC,1998,5499432482324.87 +Middle income,MIC,1999,5365881260373.12 +Middle income,MIC,2000,5851457342169 +Middle income,MIC,2001,5917641548115.5 +Middle income,MIC,2002,6032742784414.22 +Middle income,MIC,2003,6827061176773.63 +Middle income,MIC,2004,8104396652437.36 +Middle income,MIC,2005,9658919014552.3 +Middle income,MIC,2006,11484611685884.1 +Middle income,MIC,2007,14252023316865.7 +Middle income,MIC,2008,17120054313779.3 +Middle income,MIC,2009,16697282511085.5 +Middle income,MIC,2010,20431462486141.4 +Middle income,MIC,2011,24158308272825.3 +Middle income,MIC,2012,25671457284263.6 +Middle income,MIC,2013,27244416912947.4 +Middle income,MIC,2014,28271814853457.7 +Middle income,MIC,2015,26814503372731.8 +Middle income,MIC,2016,26835804840473.3 +North America,NAC,1960,584477920198.99 +North America,NAC,1961,604157219440.397 +North America,NAC,1962,647173002027.413 +North America,NAC,1963,683353535761.531 +North America,NAC,1964,734790505460.858 +North America,NAC,1965,797723909391.131 +North America,NAC,1966,875492805408.936 +North America,NAC,1967,926623934246.798 +North America,NAC,1968,1013409031841.72 +North America,NAC,1969,1097952410241.71 +North America,NAC,1970,1163966395224.42 +North America,NAC,1971,1267253061477.52 +North America,NAC,1972,1395767220992.02 +North America,NAC,1973,1560140359214.08 +North America,NAC,1974,1709546297648.26 +North America,NAC,1975,1863102029787.65 +North America,NAC,1976,2084548864401.62 +North America,NAC,1977,2298010156934.65 +North America,NAC,1978,2575679667449.81 +North America,NAC,1979,2875732302185.42 +North America,NAC,1980,3136972126345.01 +North America,NAC,1981,3517909963656.99 +North America,NAC,1982,3659283025119.14 +North America,NAC,1983,3979574111781.89 +North America,NAC,1984,4397051258071.62 +North America,NAC,1985,4712529999482.75 +North America,NAC,1986,4968766427343.98 +North America,NAC,1987,5302830242049.45 +North America,NAC,1988,5761398451214.26 +North America,NAC,1989,6224250243275.25 +North America,NAC,1990,6575110950908.47 +North America,NAC,1991,6786006083611.19 +North America,NAC,1992,7133366589284.92 +North America,NAC,1993,7457709121892.44 +North America,NAC,1994,7888761439501.61 +North America,NAC,1995,8270122373385.4 +North America,NAC,1996,8731442777972.13 +North America,NAC,1997,9264273191726.28 +North America,NAC,1998,9724112027406.81 +North America,NAC,1999,10340031087640.9 +North America,NAC,2000,11030552667252.6 +North America,NAC,2001,11361884260892.6 +North America,NAC,2002,11739401906646.5 +North America,NAC,2003,12407237511367.9 +North America,NAC,2004,13302608706074.6 +North America,NAC,2005,14267952115864.7 +North America,NAC,2006,15176717496461.2 +North America,NAC,2007,15948507238205.8 +North America,NAC,2008,16273823136997.2 +North America,NAC,2009,15795698382986.4 +North America,NAC,2010,16583580836811.1 +North America,NAC,2011,17312124677047.8 +North America,NAC,2012,17985081294447.6 +North America,NAC,2013,18539718715830.2 +North America,NAC,2014,19191755961783.7 +North America,NAC,2015,19595346721974.5 +North America,NAC,2016,20104904753734.8 +OECD members,OED,1960,1071148468561.41 +OECD members,OED,1961,1125832842998.51 +OECD members,OED,1962,1215841389136.37 +OECD members,OED,1963,1310283723048.87 +OECD members,OED,1964,1431887112561.98 +OECD members,OED,1965,1554546204085.41 +OECD members,OED,1966,1706871950732.13 +OECD members,OED,1967,1831600828348.03 +OECD members,OED,1968,1985484758150.99 +OECD members,OED,1969,2179226855795.61 +OECD members,OED,1970,2390390686111.07 +OECD members,OED,1971,2646317574763.35 +OECD members,OED,1972,3070546015009.47 +OECD members,OED,1973,3709185177074.73 +OECD members,OED,1974,4158280828971.97 +OECD members,OED,1975,4658825077597.2 +OECD members,OED,1976,5049009543873.49 +OECD members,OED,1977,5693077367140.28 +OECD members,OED,1978,6835772209740.3 +OECD members,OED,1979,7896142494077.98 +OECD members,OED,1980,8764338498877.9 +OECD members,OED,1981,8922436064860.69 +OECD members,OED,1982,8786255124380.75 +OECD members,OED,1983,9077887021838.69 +OECD members,OED,1984,9494477176460.86 +OECD members,OED,1985,10015967458690.2 +OECD members,OED,1986,12140888703533 +OECD members,OED,1987,14052574571754.2 +OECD members,OED,1988,15854831419998 +OECD members,OED,1989,16610824977450.6 +OECD members,OED,1990,18717131834846.2 +OECD members,OED,1991,19798533698156.4 +OECD members,OED,1992,21286212823936.3 +OECD members,OED,1993,21602686285516.6 +OECD members,OED,1994,23066746233125.3 +OECD members,OED,1995,25409558844503.5 +OECD members,OED,1996,25631695317896.3 +OECD members,OED,1997,25240277081015.1 +OECD members,OED,1998,25498833540302.8 +OECD members,OED,1999,26798774923570.7 +OECD members,OED,2000,27363992604547.7 +OECD members,OED,2001,27110458919332 +OECD members,OED,2002,28288512785831.6 +OECD members,OED,2003,31695202048895.5 +OECD members,OED,2004,35282198913762.3 +OECD members,OED,2005,37292067332552.4 +OECD members,OED,2006,39314471295987.4 +OECD members,OED,2007,42976830154645.7 +OECD members,OED,2008,45489387299735.7 +OECD members,OED,2009,42557636517549.5 +OECD members,OED,2010,44588338330918.9 +OECD members,OED,2011,47907103635329.9 +OECD members,OED,2012,47806877198116 +OECD members,OED,2013,48377472404230.7 +OECD members,OED,2014,49318789250850.1 +OECD members,OED,2015,46489946919891.2 +OECD members,OED,2016,47394052796780.3 +Other small states,OSS,1970,3120000513.63038 +Other small states,OSS,1971,3703668497.25236 +Other small states,OSS,1972,4485075013.76688 +Other small states,OSS,1973,6495784978.63854 +Other small states,OSS,1974,11967802921.9622 +Other small states,OSS,1975,13355843219.8957 +Other small states,OSS,1976,16602401120.5883 +Other small states,OSS,1977,18699272186.2965 +Other small states,OSS,1978,20631386856.0129 +Other small states,OSS,1979,26785098967.4081 +Other small states,OSS,1980,37183269997.956 +Other small states,OSS,1981,37385918037.1978 +Other small states,OSS,1982,35362618281.9374 +Other small states,OSS,1983,33399704521.5294 +Other small states,OSS,1984,33642964084.1968 +Other small states,OSS,1985,31964598499.4935 +Other small states,OSS,1986,32342044549.6327 +Other small states,OSS,1987,38389402844.2948 +Other small states,OSS,1988,43139712814.829 +Other small states,OSS,1989,45177490212.0309 +Other small states,OSS,1990,54042037641.2318 +Other small states,OSS,1991,55656865129.0129 +Other small states,OSS,1992,60712295552.4811 +Other small states,OSS,1993,57746555835.7855 +Other small states,OSS,1994,60482828187.5356 +Other small states,OSS,1995,69298946725.52 +Other small states,OSS,1996,73172701870.202 +Other small states,OSS,1997,76266859217.9987 +Other small states,OSS,1998,74735365660.7398 +Other small states,OSS,1999,80433140076.8188 +Other small states,OSS,2000,91230480401.4556 +Other small states,OSS,2001,90672611826.8333 +Other small states,OSS,2002,97772578664.9743 +Other small states,OSS,2003,121118378940.561 +Other small states,OSS,2004,150081419957.446 +Other small states,OSS,2005,182102127175.268 +Other small states,OSS,2006,214036484985.338 +Other small states,OSS,2007,261998871872.612 +Other small states,OSS,2008,320442487440.3 +Other small states,OSS,2009,275173743167.462 +Other small states,OSS,2010,320128712509.16 +Other small states,OSS,2011,396019011152.095 +Other small states,OSS,2012,413403874820.602 +Other small states,OSS,2013,431086487370.448 +Other small states,OSS,2014,444405144277.814 +Other small states,OSS,2015,368813590036.302 +Other small states,OSS,2016,358773092768.133 +Pacific island small states,PSS,1975,1119628254.45097 +Pacific island small states,PSS,1976,1122701696.34762 +Pacific island small states,PSS,1977,1171337344.9078 +Pacific island small states,PSS,1978,1358461165.8138 +Pacific island small states,PSS,1979,1664350939.8496 +Pacific island small states,PSS,1980,1904926911.85166 +Pacific island small states,PSS,1981,1963994945.57172 +Pacific island small states,PSS,1982,1918437387.41573 +Pacific island small states,PSS,1983,1837236806.42751 +Pacific island small states,PSS,1984,2014185046.11569 +Pacific island small states,PSS,1985,1906817279.10052 +Pacific island small states,PSS,1986,2070080622.74654 +Pacific island small states,PSS,1987,2033588088.5576 +Pacific island small states,PSS,1988,2130602489.94617 +Pacific island small states,PSS,1989,2224856985.74429 +Pacific island small states,PSS,1990,2396519647.95393 +Pacific island small states,PSS,1991,2548876044.46992 +Pacific island small states,PSS,1992,2794580111.5317 +Pacific island small states,PSS,1993,2946262871.07794 +Pacific island small states,PSS,1994,3395405058.97482 +Pacific island small states,PSS,1995,3668259744.87741 +Pacific island small states,PSS,1996,3939096312.4053 +Pacific island small states,PSS,1997,3935301807.10212 +Pacific island small states,PSS,1998,3383564007.07114 +Pacific island small states,PSS,1999,3685133762.02162 +Pacific island small states,PSS,2000,3448662181.8232 +Pacific island small states,PSS,2001,3375672793.3588 +Pacific island small states,PSS,2002,3547120140.79495 +Pacific island small states,PSS,2003,4158737438.11844 +Pacific island small states,PSS,2004,4803309271.01673 +Pacific island small states,PSS,2005,5273003192.09283 +Pacific island small states,PSS,2006,5542891987.75737 +Pacific island small states,PSS,2007,6079623933.05137 +Pacific island small states,PSS,2008,6554131285.08651 +Pacific island small states,PSS,2009,5775975880.54319 +Pacific island small states,PSS,2010,6402407316.26645 +Pacific island small states,PSS,2011,7588040251.82748 +Pacific island small states,PSS,2012,8109258573.53231 +Pacific island small states,PSS,2013,8375325157.08132 +Pacific island small states,PSS,2014,8780810605.05193 +Pacific island small states,PSS,2015,8577127156.94718 +Pacific island small states,PSS,2016,8888374720.40864 +Post-demographic dividend,PST,1960,1044656471320.34 +Post-demographic dividend,PST,1961,1104232973387.34 +Post-demographic dividend,PST,1962,1192909023772.47 +Post-demographic dividend,PST,1963,1284222177741.77 +Post-demographic dividend,PST,1964,1401673751394.55 +Post-demographic dividend,PST,1965,1522536171657.24 +Post-demographic dividend,PST,1966,1669615615246.75 +Post-demographic dividend,PST,1967,1791607216531.48 +Post-demographic dividend,PST,1968,1941588054277.74 +Post-demographic dividend,PST,1969,2129810291257.2 +Post-demographic dividend,PST,1970,2340888132430.83 +Post-demographic dividend,PST,1971,2595435794745.15 +Post-demographic dividend,PST,1972,3010533039073.01 +Post-demographic dividend,PST,1973,3633402675461.9 +Post-demographic dividend,PST,1974,4057572289102.56 +Post-demographic dividend,PST,1975,4546348912848.59 +Post-demographic dividend,PST,1976,4932972042226.7 +Post-demographic dividend,PST,1977,5576027961708.64 +Post-demographic dividend,PST,1978,6699303304490.5 +Post-demographic dividend,PST,1979,7701902775121.56 +Post-demographic dividend,PST,1980,8528744893965.75 +Post-demographic dividend,PST,1981,8627548222470.53 +Post-demographic dividend,PST,1982,8585856196665.95 +Post-demographic dividend,PST,1983,8907329214532.46 +Post-demographic dividend,PST,1984,9311124585501.98 +Post-demographic dividend,PST,1985,9820475618013.04 +Post-demographic dividend,PST,1986,11992583228317.2 +Post-demographic dividend,PST,1987,13892518055017.9 +Post-demographic dividend,PST,1988,15649138703182.9 +Post-demographic dividend,PST,1989,16363490315438.2 +Post-demographic dividend,PST,1990,18373377012979.3 +Post-demographic dividend,PST,1991,19370853403893.8 +Post-demographic dividend,PST,1992,20787746843384.1 +Post-demographic dividend,PST,1993,20957060229668.8 +Post-demographic dividend,PST,1994,22429029383135.7 +Post-demographic dividend,PST,1995,24852064655451.6 +Post-demographic dividend,PST,1996,24982304258549.2 +Post-demographic dividend,PST,1997,24511726798084.9 +Post-demographic dividend,PST,1998,24615173781504.8 +Post-demographic dividend,PST,1999,25841010690140.8 +Post-demographic dividend,PST,2000,26282689637675.3 +Post-demographic dividend,PST,2001,26041902978856 +Post-demographic dividend,PST,2002,27158954468171.9 +Post-demographic dividend,PST,2003,30469203654916.5 +Post-demographic dividend,PST,2004,33857110810844.5 +Post-demographic dividend,PST,2005,35634331213681.7 +Post-demographic dividend,PST,2006,37477971990381.3 +Post-demographic dividend,PST,2007,40875024376117.4 +Post-demographic dividend,PST,2008,43181906552198.2 +Post-demographic dividend,PST,2009,40654677510668 +Post-demographic dividend,PST,2010,42396023961852.1 +Post-demographic dividend,PST,2011,45507579610296.7 +Post-demographic dividend,PST,2012,45431195222279.9 +Post-demographic dividend,PST,2013,45820016966895.3 +Post-demographic dividend,PST,2014,46685151869819.2 +Post-demographic dividend,PST,2015,44081796060319.5 +Post-demographic dividend,PST,2016,45072138207006.3 +Pre-demographic dividend,PRE,1960,10444792557.8843 +Pre-demographic dividend,PRE,1961,10792191176.9913 +Pre-demographic dividend,PRE,1962,11794111161.167 +Pre-demographic dividend,PRE,1963,13764637075.142 +Pre-demographic dividend,PRE,1964,12795571686.9276 +Pre-demographic dividend,PRE,1965,14432973775.8933 +Pre-demographic dividend,PRE,1966,15869568127.6857 +Pre-demographic dividend,PRE,1967,14966394983.6694 +Pre-demographic dividend,PRE,1968,15779012377.2635 +Pre-demographic dividend,PRE,1969,17940990058.5991 +Pre-demographic dividend,PRE,1970,21951712164.311 +Pre-demographic dividend,PRE,1971,21460771419.442 +Pre-demographic dividend,PRE,1972,24863758794.081 +Pre-demographic dividend,PRE,1973,30483369632.1883 +Pre-demographic dividend,PRE,1974,43595337802.2346 +Pre-demographic dividend,PRE,1975,49542343893.6683 +Pre-demographic dividend,PRE,1976,58304074038.3621 +Pre-demographic dividend,PRE,1977,64654895975.3614 +Pre-demographic dividend,PRE,1978,71877526055.5515 +Pre-demographic dividend,PRE,1979,90876577931.6188 +Pre-demographic dividend,PRE,1980,111128692579.225 +Pre-demographic dividend,PRE,1981,99890611243.0475 +Pre-demographic dividend,PRE,1982,96485338012.3114 +Pre-demographic dividend,PRE,1983,82315486748.1406 +Pre-demographic dividend,PRE,1984,81200162508.3063 +Pre-demographic dividend,PRE,1985,84292961016.2471 +Pre-demographic dividend,PRE,1986,86854873100.4704 +Pre-demographic dividend,PRE,1987,99081060277.1037 +Pre-demographic dividend,PRE,1988,101944868961.831 +Pre-demographic dividend,PRE,1989,104019371613.989 +Pre-demographic dividend,PRE,1990,167507910377.201 +Pre-demographic dividend,PRE,1991,166990503688.432 +Pre-demographic dividend,PRE,1992,152419870394.426 +Pre-demographic dividend,PRE,1993,138508748991.463 +Pre-demographic dividend,PRE,1994,126874724056.413 +Pre-demographic dividend,PRE,1995,155361079241.209 +Pre-demographic dividend,PRE,1996,173224107614.69 +Pre-demographic dividend,PRE,1997,180765049998.456 +Pre-demographic dividend,PRE,1998,178797997119.74 +Pre-demographic dividend,PRE,1999,181481700462.617 +Pre-demographic dividend,PRE,2000,211754710795.63 +Pre-demographic dividend,PRE,2001,200696505653.475 +Pre-demographic dividend,PRE,2002,237011718871.519 +Pre-demographic dividend,PRE,2003,274020284824.498 +Pre-demographic dividend,PRE,2004,332024783749.247 +Pre-demographic dividend,PRE,2005,411421770397.822 +Pre-demographic dividend,PRE,2006,513693910493.325 +Pre-demographic dividend,PRE,2007,628900837818.886 +Pre-demographic dividend,PRE,2008,802590453555.333 +Pre-demographic dividend,PRE,2009,730577224083.185 +Pre-demographic dividend,PRE,2010,1005125615291.85 +Pre-demographic dividend,PRE,2011,1162386942622.43 +Pre-demographic dividend,PRE,2012,1277869591512.9 +Pre-demographic dividend,PRE,2013,1396458716370.55 +Pre-demographic dividend,PRE,2014,1491939195061.18 +Pre-demographic dividend,PRE,2015,1296897941977.73 +Pre-demographic dividend,PRE,2016,1194739930946.8 +Small states,SST,1970,7836787195.57926 +Small states,SST,1971,8818144097.10709 +Small states,SST,1972,10407377358.8588 +Small states,SST,1973,12964753902.4681 +Small states,SST,1974,20152451259.247 +Small states,SST,1975,22936619953.578 +Small states,SST,1976,26214423633.4757 +Small states,SST,1977,29771720454.8057 +Small states,SST,1978,31993368148.3596 +Small states,SST,1979,39722899441.6698 +Small states,SST,1980,52643379201.5761 +Small states,SST,1981,54400876326.3316 +Small states,SST,1982,54173365558.0276 +Small states,SST,1983,52414910869.8285 +Small states,SST,1984,51973393619.5984 +Small states,SST,1985,50036733663.1376 +Small states,SST,1986,49068591555.2924 +Small states,SST,1987,56063766853.2931 +Small states,SST,1988,61791930551.2311 +Small states,SST,1989,64304587894.9821 +Small states,SST,1990,74325169013.8579 +Small states,SST,1991,75856511772.4776 +Small states,SST,1992,80746249830.122 +Small states,SST,1993,78946659813.3949 +Small states,SST,1994,83179982124.9322 +Small states,SST,1995,94034486010.0192 +Small states,SST,1996,100096683467.444 +Small states,SST,1997,105904285406.659 +Small states,SST,1998,106388698435.668 +Small states,SST,1999,114155580862.484 +Small states,SST,2000,126923095471.91 +Small states,SST,2001,127212731119.311 +Small states,SST,2002,136256691925.274 +Small states,SST,2003,162766467544.72 +Small states,SST,2004,196053942193.91 +Small states,SST,2005,234022949884.059 +Small states,SST,2006,271974858948.518 +Small states,SST,2007,326343861812.675 +Small states,SST,2008,393489345339.146 +Small states,SST,2009,336886290580.524 +Small states,SST,2010,387290741084.775 +Small states,SST,2011,469287734302.83 +Small states,SST,2012,489309844392.053 +Small states,SST,2013,508115793399.22 +Small states,SST,2014,521843492853.73 +Small states,SST,2015,444166579289.296 +Small states,SST,2016,431168068762.38 +South Asia,SAS,1960,46535882350.9266 +South Asia,SAS,1961,49639265058.4063 +South Asia,SAS,1962,52969959484.3953 +South Asia,SAS,1963,59564124015.8815 +South Asia,SAS,1964,68207240598.8702 +South Asia,SAS,1965,73302133554.3812 +South Asia,SAS,1966,61638106880.2155 +South Asia,SAS,1967,67859668328.6678 +South Asia,SAS,1968,71227636451.2209 +South Asia,SAS,1969,78199356804.4547 +South Asia,SAS,1970,84723556606.6577 +South Asia,SAS,1971,90042201735.933 +South Asia,SAS,1972,90429767479.7852 +South Asia,SAS,1973,103394104064.568 +South Asia,SAS,1974,125253027719.481 +South Asia,SAS,1975,134416247893.554 +South Asia,SAS,1976,131167736496.854 +South Asia,SAS,1977,151656859741.32 +South Asia,SAS,1978,172583702484.323 +South Asia,SAS,1979,193318644211.014 +South Asia,SAS,1980,233086150890.581 +South Asia,SAS,1981,247106727885.511 +South Asia,SAS,1982,255647758195.845 +South Asia,SAS,1983,270545959911.574 +South Asia,SAS,1984,269355371616.79 +South Asia,SAS,1985,292874261371.477 +South Asia,SAS,1986,310147312219.788 +South Asia,SAS,1987,344338564248.576 +South Asia,SAS,1988,370046274630.143 +South Asia,SAS,1989,373481452094.992 +South Asia,SAS,1990,402050004575.507 +South Asia,SAS,1991,357724016273.124 +South Asia,SAS,1992,379830007893.096 +South Asia,SAS,1993,376239667456.956 +South Asia,SAS,1994,426649315426.754 +South Asia,SAS,1995,474034412841.889 +South Asia,SAS,1996,518624561848.025 +South Asia,SAS,1997,544005563622.908 +South Asia,SAS,1998,551628275406.445 +South Asia,SAS,1999,590948715637.038 +South Asia,SAS,2000,614756473709.585 +South Asia,SAS,2001,630828017006.122 +South Asia,SAS,2002,663250167513.155 +South Asia,SAS,2003,774457944529.068 +South Asia,SAS,2004,897902015362.288 +South Asia,SAS,2005,1028596382537.81 +South Asia,SAS,2006,1176153232856.56 +South Asia,SAS,2007,1488571172561.54 +South Asia,SAS,2008,1515479924054.14 +South Asia,SAS,2009,1665393025481.3 +South Asia,SAS,2010,2041877081506.8 +South Asia,SAS,2011,2271681618877.26 +South Asia,SAS,2012,2297541689398.13 +South Asia,SAS,2013,2356159930348.29 +South Asia,SAS,2014,2577102437097.39 +South Asia,SAS,2015,2705001263802.98 +South Asia,SAS,2016,2896360597068.83 +South Asia (IDA & IBRD),TSA,1960,46535882350.9266 +South Asia (IDA & IBRD),TSA,1961,49639265058.4063 +South Asia (IDA & IBRD),TSA,1962,52969959484.3953 +South Asia (IDA & IBRD),TSA,1963,59564124015.8815 +South Asia (IDA & IBRD),TSA,1964,68207240598.8702 +South Asia (IDA & IBRD),TSA,1965,73302133554.3812 +South Asia (IDA & IBRD),TSA,1966,61638106880.2155 +South Asia (IDA & IBRD),TSA,1967,67859668328.6678 +South Asia (IDA & IBRD),TSA,1968,71227636451.2209 +South Asia (IDA & IBRD),TSA,1969,78199356804.4547 +South Asia (IDA & IBRD),TSA,1970,84723556606.6577 +South Asia (IDA & IBRD),TSA,1971,90042201735.933 +South Asia (IDA & IBRD),TSA,1972,90429767479.7852 +South Asia (IDA & IBRD),TSA,1973,103394104064.568 +South Asia (IDA & IBRD),TSA,1974,125253027719.481 +South Asia (IDA & IBRD),TSA,1975,134416247893.554 +South Asia (IDA & IBRD),TSA,1976,131167736496.854 +South Asia (IDA & IBRD),TSA,1977,151656859741.32 +South Asia (IDA & IBRD),TSA,1978,172583702484.323 +South Asia (IDA & IBRD),TSA,1979,193318644211.014 +South Asia (IDA & IBRD),TSA,1980,233086150890.581 +South Asia (IDA & IBRD),TSA,1981,247106727885.511 +South Asia (IDA & IBRD),TSA,1982,255647758195.845 +South Asia (IDA & IBRD),TSA,1983,270545959911.574 +South Asia (IDA & IBRD),TSA,1984,269355371616.79 +South Asia (IDA & IBRD),TSA,1985,292874261371.477 +South Asia (IDA & IBRD),TSA,1986,310147312219.788 +South Asia (IDA & IBRD),TSA,1987,344338564248.576 +South Asia (IDA & IBRD),TSA,1988,370046274630.143 +South Asia (IDA & IBRD),TSA,1989,373481452094.992 +South Asia (IDA & IBRD),TSA,1990,402050004575.507 +South Asia (IDA & IBRD),TSA,1991,357724016273.124 +South Asia (IDA & IBRD),TSA,1992,379830007893.096 +South Asia (IDA & IBRD),TSA,1993,376239667456.956 +South Asia (IDA & IBRD),TSA,1994,426649315426.754 +South Asia (IDA & IBRD),TSA,1995,474034412841.889 +South Asia (IDA & IBRD),TSA,1996,518624561848.025 +South Asia (IDA & IBRD),TSA,1997,544005563622.908 +South Asia (IDA & IBRD),TSA,1998,551628275406.445 +South Asia (IDA & IBRD),TSA,1999,590948715637.038 +South Asia (IDA & IBRD),TSA,2000,614756473709.585 +South Asia (IDA & IBRD),TSA,2001,630828017006.122 +South Asia (IDA & IBRD),TSA,2002,663250167513.155 +South Asia (IDA & IBRD),TSA,2003,774457944529.068 +South Asia (IDA & IBRD),TSA,2004,897902015362.288 +South Asia (IDA & IBRD),TSA,2005,1028596382537.81 +South Asia (IDA & IBRD),TSA,2006,1176153232856.56 +South Asia (IDA & IBRD),TSA,2007,1488571172561.54 +South Asia (IDA & IBRD),TSA,2008,1515479924054.14 +South Asia (IDA & IBRD),TSA,2009,1665393025481.3 +South Asia (IDA & IBRD),TSA,2010,2041877081506.8 +South Asia (IDA & IBRD),TSA,2011,2271681618877.26 +South Asia (IDA & IBRD),TSA,2012,2297541689398.13 +South Asia (IDA & IBRD),TSA,2013,2356159930348.29 +South Asia (IDA & IBRD),TSA,2014,2577102437097.39 +South Asia (IDA & IBRD),TSA,2015,2705001263802.98 +South Asia (IDA & IBRD),TSA,2016,2896360597068.83 +Sub-Saharan Africa,SSF,1960,30385873317.6191 +Sub-Saharan Africa,SSF,1961,31561069598.0721 +Sub-Saharan Africa,SSF,1962,34208896061.892 +Sub-Saharan Africa,SSF,1963,39225741664.7524 +Sub-Saharan Africa,SSF,1964,38271070687.048 +Sub-Saharan Africa,SSF,1965,42640958019.1558 +Sub-Saharan Africa,SSF,1966,46032013187.6583 +Sub-Saharan Africa,SSF,1967,45494160112.4203 +Sub-Saharan Africa,SSF,1968,48659688079.8348 +Sub-Saharan Africa,SSF,1969,55788782510.7981 +Sub-Saharan Africa,SSF,1970,65641311288.6349 +Sub-Saharan Africa,SSF,1971,66787674494.6591 +Sub-Saharan Africa,SSF,1972,75244560743.9655 +Sub-Saharan Africa,SSF,1973,96178659252.9924 +Sub-Saharan Africa,SSF,1974,126049492057.768 +Sub-Saharan Africa,SSF,1975,138623192435.063 +Sub-Saharan Africa,SSF,1976,150523567593.48 +Sub-Saharan Africa,SSF,1977,165924142356.056 +Sub-Saharan Africa,SSF,1978,183362414567.183 +Sub-Saharan Africa,SSF,1979,220720718807.57 +Sub-Saharan Africa,SSF,1980,277168620649.298 +Sub-Saharan Africa,SSF,1981,279597299140.561 +Sub-Saharan Africa,SSF,1982,261201722615.81 +Sub-Saharan Africa,SSF,1983,243178158509.023 +Sub-Saharan Africa,SSF,1984,231534327753.875 +Sub-Saharan Africa,SSF,1985,215767871591.388 +Sub-Saharan Africa,SSF,1986,239127684060.416 +Sub-Saharan Africa,SSF,1987,281787606420.109 +Sub-Saharan Africa,SSF,1988,296425266186.195 +Sub-Saharan Africa,SSF,1989,310125765635.045 +Sub-Saharan Africa,SSF,1990,310601465373.488 +Sub-Saharan Africa,SSF,1991,320112647218.571 +Sub-Saharan Africa,SSF,1992,314832065746.688 +Sub-Saharan Africa,SSF,1993,298956393687.87 +Sub-Saharan Africa,SSF,1994,291679005862.221 +Sub-Saharan Africa,SSF,1995,337515727715.285 +Sub-Saharan Africa,SSF,1996,349098748885.709 +Sub-Saharan Africa,SSF,1997,361099250055.323 +Sub-Saharan Africa,SSF,1998,340612558536.667 +Sub-Saharan Africa,SSF,1999,343239312535.324 +Sub-Saharan Africa,SSF,2000,367992054429.688 +Sub-Saharan Africa,SSF,2001,342553779838.8 +Sub-Saharan Africa,SSF,2002,367108332547.638 +Sub-Saharan Africa,SSF,2003,468992752558.158 +Sub-Saharan Africa,SSF,2004,583209894804.24 +Sub-Saharan Africa,SSF,2005,685920335014.857 +Sub-Saharan Africa,SSF,2006,801445697569.974 +Sub-Saharan Africa,SSF,2007,932416460747.498 +Sub-Saharan Africa,SSF,2008,1064752013079.22 +Sub-Saharan Africa,SSF,2009,1022260711828.75 +Sub-Saharan Africa,SSF,2010,1361111020590.47 +Sub-Saharan Africa,SSF,2011,1532598528787.88 +Sub-Saharan Africa,SSF,2012,1607918609335.78 +Sub-Saharan Africa,SSF,2013,1692968078930.83 +Sub-Saharan Africa,SSF,2014,1775063779086.99 +Sub-Saharan Africa,SSF,2015,1601114502934 +Sub-Saharan Africa,SSF,2016,1498001165832.29 +Sub-Saharan Africa (excluding high income),SSA,1960,30375251120.8982 +Sub-Saharan Africa (excluding high income),SSA,1961,31551059162.9924 +Sub-Saharan Africa (excluding high income),SSA,1962,34197956223.5719 +Sub-Saharan Africa (excluding high income),SSA,1963,39213859646.9823 +Sub-Saharan Africa (excluding high income),SSA,1964,38257387425.3277 +Sub-Saharan Africa (excluding high income),SSA,1965,42627500884.5051 +Sub-Saharan Africa (excluding high income),SSA,1966,46017949100.4039 +Sub-Saharan Africa (excluding high income),SSA,1967,45479820393.276 +Sub-Saharan Africa (excluding high income),SSA,1968,48646316919.2904 +Sub-Saharan Africa (excluding high income),SSA,1969,55775718701.4028 +Sub-Saharan Africa (excluding high income),SSA,1970,65627001306.2372 +Sub-Saharan Africa (excluding high income),SSA,1971,66769437518.4287 +Sub-Saharan Africa (excluding high income),SSA,1972,75217262850.8043 +Sub-Saharan Africa (excluding high income),SSA,1973,96146370804.013 +Sub-Saharan Africa (excluding high income),SSA,1974,126013152393.226 +Sub-Saharan Africa (excluding high income),SSA,1975,138582808945.702 +Sub-Saharan Africa (excluding high income),SSA,1976,150482725715.529 +Sub-Saharan Africa (excluding high income),SSA,1977,165867501154.588 +Sub-Saharan Africa (excluding high income),SSA,1978,183283589349.244 +Sub-Saharan Africa (excluding high income),SSA,1979,220598169194.501 +Sub-Saharan Africa (excluding high income),SSA,1980,277028916343.799 +Sub-Saharan Africa (excluding high income),SSA,1981,279449423286.245 +Sub-Saharan Africa (excluding high income),SSA,1982,261060121194.45 +Sub-Saharan Africa (excluding high income),SSA,1983,243036605981.087 +Sub-Saharan Africa (excluding high income),SSA,1984,231387005071.033 +Sub-Saharan Africa (excluding high income),SSA,1985,215600490241.505 +Sub-Saharan Africa (excluding high income),SSA,1986,238920584205.91 +Sub-Saharan Africa (excluding high income),SSA,1987,281539069227.019 +Sub-Saharan Africa (excluding high income),SSA,1988,296141433311.271 +Sub-Saharan Africa (excluding high income),SSA,1989,309820789988.06 +Sub-Saharan Africa (excluding high income),SSA,1990,310231626268.599 +Sub-Saharan Africa (excluding high income),SSA,1991,319737091702.347 +Sub-Saharan Africa (excluding high income),SSA,1992,314396072361.021 +Sub-Saharan Africa (excluding high income),SSA,1993,298479274571.218 +Sub-Saharan Africa (excluding high income),SSA,1994,291189045365.333 +Sub-Saharan Africa (excluding high income),SSA,1995,337004319808.346 +Sub-Saharan Africa (excluding high income),SSA,1996,348592745999.649 +Sub-Saharan Africa (excluding high income),SSA,1997,360532574706.808 +Sub-Saharan Africa (excluding high income),SSA,1998,339999446598.117 +Sub-Saharan Africa (excluding high income),SSA,1999,342611389093.949 +Sub-Saharan Africa (excluding high income),SSA,2000,367372728727.684 +Sub-Saharan Africa (excluding high income),SSA,2001,341926581367.121 +Sub-Saharan Africa (excluding high income),SSA,2002,366405040525.772 +Sub-Saharan Africa (excluding high income),SSA,2003,468282596074.19 +Sub-Saharan Africa (excluding high income),SSA,2004,582365642433.327 +Sub-Saharan Africa (excluding high income),SSA,2005,684996503798.667 +Sub-Saharan Africa (excluding high income),SSA,2006,800424661847.349 +Sub-Saharan Africa (excluding high income),SSA,2007,931379876723.897 +Sub-Saharan Africa (excluding high income),SSA,2008,1063784722921.19 +Sub-Saharan Africa (excluding high income),SSA,2009,1021413301121.37 +Sub-Saharan Africa (excluding high income),SSA,2010,1360141211429.22 +Sub-Saharan Africa (excluding high income),SSA,2011,1531532869537.52 +Sub-Saharan Africa (excluding high income),SSA,2012,1606784475519.59 +Sub-Saharan Africa (excluding high income),SSA,2013,1691556590025.3 +Sub-Saharan Africa (excluding high income),SSA,2014,1773640768624.54 +Sub-Saharan Africa (excluding high income),SSA,2015,1599676432988.51 +Sub-Saharan Africa (excluding high income),SSA,2016,1496573096431.15 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1960,30385873317.619 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1961,31561069598.0721 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1962,34208896061.8919 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1963,39225741664.7524 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1964,38271070687.0479 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1965,42640958019.1557 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1966,46032013187.6583 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1967,45494160112.4203 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1968,48659688079.8347 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1969,55788782510.798 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1970,65641311288.6349 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1971,66787674494.659 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1972,75244560743.9654 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1973,96178659252.9923 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1974,126049492057.768 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1975,138623192435.063 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1976,150523567593.48 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1977,165924142356.056 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1978,183362414567.182 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1979,220720718807.57 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1980,277168620649.297 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1981,279597299140.561 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1982,261201722615.809 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1983,243178158509.023 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1984,231534327753.875 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1985,215767871591.388 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1986,239127684060.416 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1987,281787606420.109 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1988,296425266186.195 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1989,310125765635.045 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1990,310601465373.488 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1991,320112647218.571 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1992,314832065746.688 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1993,298956393687.87 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1994,291679005862.221 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1995,337515727715.285 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1996,349098748885.709 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1997,361099250055.323 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1998,340612558536.667 +Sub-Saharan Africa (IDA & IBRD countries),TSS,1999,343239312535.324 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2000,367992054429.687 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2001,342553779838.8 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2002,367108332547.638 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2003,468992752558.158 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2004,583209894804.24 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2005,685920335014.857 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2006,801445697569.974 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2007,932416460747.498 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2008,1064752013079.22 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2009,1022260711828.75 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2010,1361111020590.47 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2011,1532598528787.88 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2012,1607918609335.78 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2013,1692968078930.83 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2014,1775063779086.99 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2015,1601114502934 +Sub-Saharan Africa (IDA & IBRD countries),TSS,2016,1498001165832.29 +Upper middle income,UMC,1960,217198647348.494 +Upper middle income,UMC,1961,198163003670.2 +Upper middle income,UMC,1962,208389042802.748 +Upper middle income,UMC,1963,218098552786.484 +Upper middle income,UMC,1964,246119837319.701 +Upper middle income,UMC,1965,274662862506.164 +Upper middle income,UMC,1966,301790005708.953 +Upper middle income,UMC,1967,306050686739.129 +Upper middle income,UMC,1968,322082966685.997 +Upper middle income,UMC,1969,360349217563.025 +Upper middle income,UMC,1970,394712327560.652 +Upper middle income,UMC,1971,432720300458.596 +Upper middle income,UMC,1972,494632159315.49 +Upper middle income,UMC,1973,642140455074.472 +Upper middle income,UMC,1974,822217878924.844 +Upper middle income,UMC,1975,906913549605.54 +Upper middle income,UMC,1976,984885444867.622 +Upper middle income,UMC,1977,1099899948045.69 +Upper middle income,UMC,1978,1175443653695.94 +Upper middle income,UMC,1979,1426467211025.1 +Upper middle income,UMC,1980,1630719856470.39 +Upper middle income,UMC,1981,1773950086597.61 +Upper middle income,UMC,1982,1749446371405.03 +Upper middle income,UMC,1983,1724517465799.49 +Upper middle income,UMC,1984,1770310443963.72 +Upper middle income,UMC,1985,1867008281184.46 +Upper middle income,UMC,1986,1949731563473.3 +Upper middle income,UMC,1987,1947828103084.37 +Upper middle income,UMC,1988,2143335758799.66 +Upper middle income,UMC,1989,2330524136589.05 +Upper middle income,UMC,1990,2668016557510.31 +Upper middle income,UMC,1991,2945883449408.78 +Upper middle income,UMC,1992,2871295456915.82 +Upper middle income,UMC,1993,3115112542376.69 +Upper middle income,UMC,1994,3394104181360.42 +Upper middle income,UMC,1995,3790108844101.48 +Upper middle income,UMC,1996,4119760606241.92 +Upper middle income,UMC,1997,4389848846126.91 +Upper middle income,UMC,1998,4336871558815.34 +Upper middle income,UMC,1999,4105143075774.15 +Upper middle income,UMC,2000,4516745939516.19 +Upper middle income,UMC,2001,4570215302631.64 +Upper middle income,UMC,2002,4585099461562.07 +Upper middle income,UMC,2003,5167508901821.26 +Upper middle income,UMC,2004,6206949763569.09 +Upper middle income,UMC,2005,7473673674144.63 +Upper middle income,UMC,2006,8886248909977.84 +Upper middle income,UMC,2007,11053091998253.6 +Upper middle income,UMC,2008,13518836281583.6 +Upper middle income,UMC,2009,13009912111056.7 +Upper middle income,UMC,2010,15772171277711.6 +Upper middle income,UMC,2011,18884745299009.3 +Upper middle income,UMC,2012,20141382977240.6 +Upper middle income,UMC,2013,21474040434046.4 +Upper middle income,UMC,2014,22200346875601.1 +Upper middle income,UMC,2015,20773804256767.4 +Upper middle income,UMC,2016,20570823016722.9 +World,WLD,1960,1366594741088.4 +World,WLD,1961,1421709987131.86 +World,WLD,1962,1526879874910.38 +World,WLD,1963,1643678995959.36 +World,WLD,1964,1800740602720.3 +World,WLD,1965,1961944483712.14 +World,WLD,1966,2128619422408.42 +World,WLD,1967,2264793675472.3 +World,WLD,1968,2443345941026.71 +World,WLD,1969,2690870797695.49 +World,WLD,1970,2956885263956.69 +World,WLD,1971,3265917075455.06 +World,WLD,1972,3766131377379.81 +World,WLD,1973,4589203445245.55 +World,WLD,1974,5292853388124.73 +World,WLD,1975,5893742092987.04 +World,WLD,1976,6412245309406.65 +World,WLD,1977,7252968306810.71 +World,WLD,1978,8537753756958.14 +World,WLD,1979,9919046089674.77 +World,WLD,1980,11166003844627.3 +World,WLD,1981,11457611762565.2 +World,WLD,1982,11355656421230.4 +World,WLD,1983,11616289845852.5 +World,WLD,1984,12058393957798 +World,WLD,1985,12681690895939.6 +World,WLD,1986,15014218229942.7 +World,WLD,1987,17083141772090.1 +World,WLD,1988,19129417553328 +World,WLD,1989,20080076891104.8 +World,WLD,1990,22579759701252.1 +World,WLD,1991,23909829105950.2 +World,WLD,1992,25389800980490.1 +World,WLD,1993,25834735037805.8 +World,WLD,1994,27740746941786.4 +World,WLD,1995,30840585358429 +World,WLD,1996,31518975357605.6 +World,WLD,1997,31403319223627.4 +World,WLD,1998,31314851252776.4 +World,WLD,1999,32486113872865.7 +World,WLD,2000,33543172517758.5 +World,WLD,2001,33335981983184.4 +World,WLD,2002,34612407886315.4 +World,WLD,2003,38867460911728.5 +World,WLD,2004,43770744134898.4 +World,WLD,2005,47385623695571.6 +World,WLD,2006,51306757202160.1 +World,WLD,2007,57793330584397.1 +World,WLD,2008,63386360623929.9 +World,WLD,2009,60086989444835.8 +World,WLD,2010,65906150734910.9 +World,WLD,2011,73241717918435.6 +World,WLD,2012,74802287628562.6 +World,WLD,2013,76924649557249.8 +World,WLD,2014,78972470867720.3 +World,WLD,2015,74606412596560.3 +World,WLD,2016,75641577475364.6 +Afghanistan,AFG,1960,537777811.111111 +Afghanistan,AFG,1961,548888895.555556 +Afghanistan,AFG,1962,546666677.777778 +Afghanistan,AFG,1963,751111191.111111 +Afghanistan,AFG,1964,800000044.444444 +Afghanistan,AFG,1965,1006666637.77778 +Afghanistan,AFG,1966,1399999966.66667 +Afghanistan,AFG,1967,1673333417.77778 +Afghanistan,AFG,1968,1373333366.66667 +Afghanistan,AFG,1969,1408888922.22222 +Afghanistan,AFG,1970,1748886595.55556 +Afghanistan,AFG,1971,1831108971.11111 +Afghanistan,AFG,1972,1595555475.55556 +Afghanistan,AFG,1973,1733333264.44444 +Afghanistan,AFG,1974,2155555497.77778 +Afghanistan,AFG,1975,2366666615.55556 +Afghanistan,AFG,1976,2555555566.66667 +Afghanistan,AFG,1977,2953333417.77778 +Afghanistan,AFG,1978,3300000108.88889 +Afghanistan,AFG,1979,3697940409.61098 +Afghanistan,AFG,1980,3641723321.99546 +Afghanistan,AFG,1981,3478787909.09091 +Afghanistan,AFG,2001,2461665937.89386 +Afghanistan,AFG,2002,4128820723.04713 +Afghanistan,AFG,2003,4583644246.48061 +Afghanistan,AFG,2004,5285465685.86423 +Afghanistan,AFG,2005,6275073571.54659 +Afghanistan,AFG,2006,7057598406.61553 +Afghanistan,AFG,2007,9843842455.48323 +Afghanistan,AFG,2008,10190529882.4878 +Afghanistan,AFG,2009,12486943505.7381 +Afghanistan,AFG,2010,15936800636.2487 +Afghanistan,AFG,2011,17930239399.8149 +Afghanistan,AFG,2012,20536542736.7297 +Afghanistan,AFG,2013,20046334303.9661 +Afghanistan,AFG,2014,20050189881.6659 +Afghanistan,AFG,2015,19702986340.5494 +Afghanistan,AFG,2016,19469022207.6357 +Albania,ALB,1984,1924242453.00793 +Albania,ALB,1985,1965384586.2409 +Albania,ALB,1986,2173750012.5 +Albania,ALB,1987,2156624900 +Albania,ALB,1988,2126000000 +Albania,ALB,1989,2335124987.5 +Albania,ALB,1990,2101624962.5 +Albania,ALB,1991,1139166645.83333 +Albania,ALB,1992,709452583.880319 +Albania,ALB,1993,1228071037.84446 +Albania,ALB,1994,1985673798.10258 +Albania,ALB,1995,2424499009.14264 +Albania,ALB,1996,3314898291.75235 +Albania,ALB,1997,2359903108.38446 +Albania,ALB,1998,2707123772.16195 +Albania,ALB,1999,3414760915.27878 +Albania,ALB,2000,3632043907.97733 +Albania,ALB,2001,4060758804.12084 +Albania,ALB,2002,4435078647.74817 +Albania,ALB,2003,5746945912.58082 +Albania,ALB,2004,7314865175.6199 +Albania,ALB,2005,8158548716.68554 +Albania,ALB,2006,8992642348.7871 +Albania,ALB,2007,10701011896.7708 +Albania,ALB,2008,12881352687.7773 +Albania,ALB,2009,12044212903.8168 +Albania,ALB,2010,11926953258.916 +Albania,ALB,2011,12890867538.5302 +Albania,ALB,2012,12319784787.2987 +Albania,ALB,2013,12781029643.5936 +Albania,ALB,2014,13219857459.1009 +Albania,ALB,2015,11390365293.8057 +Albania,ALB,2016,11926892452.8499 +Algeria,DZA,1960,2723648551.75208 +Algeria,DZA,1961,2434776645.73628 +Algeria,DZA,1962,2001468867.73344 +Algeria,DZA,1963,2703014867.32834 +Algeria,DZA,1964,2909351792.58659 +Algeria,DZA,1965,3136258896.9233 +Algeria,DZA,1966,3039834558.74906 +Algeria,DZA,1967,3370843065.76735 +Algeria,DZA,1968,3852115816.97758 +Algeria,DZA,1969,4257218772.15369 +Algeria,DZA,1970,4863487492.65763 +Algeria,DZA,1971,5077222366.97472 +Algeria,DZA,1972,6761786386.54713 +Algeria,DZA,1973,8715105930.49101 +Algeria,DZA,1974,13209713643.3219 +Algeria,DZA,1975,15557934268.4965 +Algeria,DZA,1976,17728347374.994 +Algeria,DZA,1977,20971901273.271 +Algeria,DZA,1978,26364491313.4471 +Algeria,DZA,1979,33243422157.6311 +Algeria,DZA,1980,42345277342.0195 +Algeria,DZA,1981,44348672667.8715 +Algeria,DZA,1982,45207088715.6483 +Algeria,DZA,1983,48801369800.3675 +Algeria,DZA,1984,53698278905.9678 +Algeria,DZA,1985,57937868670.1937 +Algeria,DZA,1986,63696301892.8116 +Algeria,DZA,1987,66742267773.1959 +Algeria,DZA,1988,59089067187.3943 +Algeria,DZA,1989,55631489801.5508 +Algeria,DZA,1990,62045099642.7774 +Algeria,DZA,1991,45715367087.1001 +Algeria,DZA,1992,48003298223.1178 +Algeria,DZA,1993,49946455210.966 +Algeria,DZA,1994,42542571305.5136 +Algeria,DZA,1995,41764052457.8814 +Algeria,DZA,1996,46941496779.8499 +Algeria,DZA,1997,48177862501.9495 +Algeria,DZA,1998,48187747528.899 +Algeria,DZA,1999,48640574566.6476 +Algeria,DZA,2000,54790245600.5846 +Algeria,DZA,2001,54744714396.1666 +Algeria,DZA,2002,56760288973.6703 +Algeria,DZA,2003,67863829880.4832 +Algeria,DZA,2004,85324998813.604 +Algeria,DZA,2005,103198228458.588 +Algeria,DZA,2006,117027304746.54 +Algeria,DZA,2007,134977087734.008 +Algeria,DZA,2008,171000691877.714 +Algeria,DZA,2009,137211039898.193 +Algeria,DZA,2010,161207268655.392 +Algeria,DZA,2011,200013051408.116 +Algeria,DZA,2012,209047389309.482 +Algeria,DZA,2013,209783503258.224 +Algeria,DZA,2014,213983107815.932 +Algeria,DZA,2015,164779467703.299 +Algeria,DZA,2016,156079606663.188 +American Samoa,ASM,2002,514000000 +American Samoa,ASM,2003,527000000 +American Samoa,ASM,2004,512000000 +American Samoa,ASM,2005,503000000 +American Samoa,ASM,2006,496000000 +American Samoa,ASM,2007,520000000 +American Samoa,ASM,2008,563000000 +American Samoa,ASM,2009,678000000 +American Samoa,ASM,2010,576000000 +American Samoa,ASM,2011,574000000 +American Samoa,ASM,2012,644000000 +American Samoa,ASM,2013,639000000 +American Samoa,ASM,2014,638000000 +American Samoa,ASM,2015,641000000 +Andorra,AND,1970,78619206.0850963 +Andorra,AND,1971,89409820.3592814 +Andorra,AND,1972,113408231.944085 +Andorra,AND,1973,150820102.798401 +Andorra,AND,1974,186558696.279204 +Andorra,AND,1975,220127246.376812 +Andorra,AND,1976,227281024.620741 +Andorra,AND,1977,254020153.340635 +Andorra,AND,1978,308008897.569444 +Andorra,AND,1979,411578334.159643 +Andorra,AND,1980,446416105.825017 +Andorra,AND,1981,388958731.302938 +Andorra,AND,1982,375895956.383462 +Andorra,AND,1983,327861832.946636 +Andorra,AND,1984,330070689.298282 +Andorra,AND,1985,346737964.774951 +Andorra,AND,1986,482000594.03588 +Andorra,AND,1987,611316399.407088 +Andorra,AND,1988,721425939.15155 +Andorra,AND,1989,795449332.396346 +Andorra,AND,1990,1029048481.88051 +Andorra,AND,1991,1106928582.86629 +Andorra,AND,1992,1210013651.87713 +Andorra,AND,1993,1007025755.00065 +Andorra,AND,1994,1017549124.33238 +Andorra,AND,1995,1178738991.19295 +Andorra,AND,1996,1223945356.62682 +Andorra,AND,1997,1180597272.72727 +Andorra,AND,1998,1211932397.81713 +Andorra,AND,1999,1239876305.13531 +Andorra,AND,2000,1401695227.56587 +Andorra,AND,2001,1484017897.09172 +Andorra,AND,2002,1717485413.13759 +Andorra,AND,2003,2373927765.23702 +Andorra,AND,2004,2916786689.84356 +Andorra,AND,2005,3248215396.09501 +Andorra,AND,2006,3536632793.87781 +Andorra,AND,2007,4010990966.32904 +Andorra,AND,2008,4001201113.22689 +Andorra,AND,2009,3650083356.48791 +Andorra,AND,2010,3346516556.29139 +Andorra,AND,2011,3427022518.76564 +Andorra,AND,2012,3146151869.45908 +Andorra,AND,2013,3248924588.42273 +Angola,AGO,1985,6684491978.60963 +Angola,AGO,1986,6684491978.60963 +Angola,AGO,1987,6684491978.60963 +Angola,AGO,1988,6684491978.60963 +Angola,AGO,1989,10026737967.9144 +Angola,AGO,1990,10026737967.9144 +Angola,AGO,1991,12118610904.2251 +Angola,AGO,1992,5684291718.77106 +Angola,AGO,1993,5278182970.79618 +Angola,AGO,1994,4059352153.05368 +Angola,AGO,1995,5039552482.42778 +Angola,AGO,1996,7526446605.51712 +Angola,AGO,1997,7648377412.83277 +Angola,AGO,1998,6445041824.66621 +Angola,AGO,1999,6152922942.98032 +Angola,AGO,2000,9129594818.60749 +Angola,AGO,2001,8936063723.20121 +Angola,AGO,2002,12497346669.6684 +Angola,AGO,2003,14188949190.618 +Angola,AGO,2004,19640848728.8937 +Angola,AGO,2005,28233712830.9035 +Angola,AGO,2006,41789478661.3096 +Angola,AGO,2007,60448921272.2326 +Angola,AGO,2008,84178032716.0971 +Angola,AGO,2009,75492384801.3695 +Angola,AGO,2010,82470913120.7314 +Angola,AGO,2011,104115923082.737 +Angola,AGO,2012,115398371427.673 +Angola,AGO,2013,124912063308.202 +Angola,AGO,2014,126776874216.703 +Angola,AGO,2015,102962245246.708 +Angola,AGO,2016,89633156470.3104 +Antigua and Barbuda,ATG,1977,77496740.7407407 +Antigua and Barbuda,ATG,1978,87879333.3333333 +Antigua and Barbuda,ATG,1979,109079962.962963 +Antigua and Barbuda,ATG,1980,131431037.037037 +Antigua and Barbuda,ATG,1981,147841740.740741 +Antigua and Barbuda,ATG,1982,164369296.296296 +Antigua and Barbuda,ATG,1983,182144111.111111 +Antigua and Barbuda,ATG,1984,208372851.851852 +Antigua and Barbuda,ATG,1985,240923925.925926 +Antigua and Barbuda,ATG,1986,290440148.148148 +Antigua and Barbuda,ATG,1987,337174851.851852 +Antigua and Barbuda,ATG,1988,398637740.740741 +Antigua and Barbuda,ATG,1989,438794777.777778 +Antigua and Barbuda,ATG,1990,459469074.074074 +Antigua and Barbuda,ATG,1991,481706333.333333 +Antigua and Barbuda,ATG,1992,499281148.148148 +Antigua and Barbuda,ATG,1993,535172777.777778 +Antigua and Barbuda,ATG,1994,589429592.592593 +Antigua and Barbuda,ATG,1995,577280740.740741 +Antigua and Barbuda,ATG,1996,633730629.62963 +Antigua and Barbuda,ATG,1997,680617111.111111 +Antigua and Barbuda,ATG,1998,727860592.592593 +Antigua and Barbuda,ATG,1999,766198925.925926 +Antigua and Barbuda,ATG,2000,825405518.518518 +Antigua and Barbuda,ATG,2001,795976518.518518 +Antigua and Barbuda,ATG,2002,809754481.481482 +Antigua and Barbuda,ATG,2003,850218592.592592 +Antigua and Barbuda,ATG,2004,913710370.37037 +Antigua and Barbuda,ATG,2005,1014979666.66667 +Antigua and Barbuda,ATG,2006,1149025481.48148 +Antigua and Barbuda,ATG,2007,1302388925.92593 +Antigua and Barbuda,ATG,2008,1359733555.55556 +Antigua and Barbuda,ATG,2009,1217719666.66667 +Antigua and Barbuda,ATG,2010,1147942222.22222 +Antigua and Barbuda,ATG,2011,1141865444.44444 +Antigua and Barbuda,ATG,2012,1216045777.77778 +Antigua and Barbuda,ATG,2013,1195885111.11111 +Antigua and Barbuda,ATG,2014,1274330333.33333 +Antigua and Barbuda,ATG,2015,1355645888.88889 +Antigua and Barbuda,ATG,2016,1449160185.18519 +Argentina,ARG,1962,24450604877.6081 +Argentina,ARG,1963,18272123664.4715 +Argentina,ARG,1964,25605249381.7597 +Argentina,ARG,1965,28344705966.6389 +Argentina,ARG,1966,28630474727.9023 +Argentina,ARG,1967,24256667553.2569 +Argentina,ARG,1968,26436857247.4982 +Argentina,ARG,1969,31256284543.6155 +Argentina,ARG,1970,31584210365.5447 +Argentina,ARG,1971,33293199095.4881 +Argentina,ARG,1972,34733000536.2862 +Argentina,ARG,1973,52544000116.9037 +Argentina,ARG,1974,72436777342.4554 +Argentina,ARG,1975,52438647921.9226 +Argentina,ARG,1976,51169499890.7722 +Argentina,ARG,1977,56781000100.9448 +Argentina,ARG,1978,58082870156.2634 +Argentina,ARG,1979,69252328953.3789 +Argentina,ARG,1980,76961923741.9478 +Argentina,ARG,1981,78676842366.4213 +Argentina,ARG,1982,84307486836.724 +Argentina,ARG,1983,103979106777.911 +Argentina,ARG,1984,79092001998.032 +Argentina,ARG,1985,88416668900.2596 +Argentina,ARG,1986,110934442762.694 +Argentina,ARG,1987,111106191358.197 +Argentina,ARG,1988,126206817196.091 +Argentina,ARG,1989,76636898036.4712 +Argentina,ARG,1990,141352368714.691 +Argentina,ARG,1991,189719984268.485 +Argentina,ARG,1992,228788617201.696 +Argentina,ARG,1993,236741715015.015 +Argentina,ARG,1994,257440000000 +Argentina,ARG,1995,258031750000 +Argentina,ARG,1996,272149750000 +Argentina,ARG,1997,292859000000 +Argentina,ARG,1998,298948250000 +Argentina,ARG,1999,283523000000 +Argentina,ARG,2000,284203750000 +Argentina,ARG,2001,268696750000 +Argentina,ARG,2002,97724004251.8602 +Argentina,ARG,2003,127586973492.177 +Argentina,ARG,2004,164657930452.787 +Argentina,ARG,2005,198737095012.282 +Argentina,ARG,2006,232557260817.308 +Argentina,ARG,2007,287530508430.568 +Argentina,ARG,2008,361558037110.419 +Argentina,ARG,2009,332976484577.619 +Argentina,ARG,2010,423627422092.49 +Argentina,ARG,2011,530163281574.658 +Argentina,ARG,2012,545982375701.128 +Argentina,ARG,2013,552025140252.246 +Argentina,ARG,2014,526319673731.638 +Argentina,ARG,2015,584711485367.267 +Argentina,ARG,2016,545866164478.053 +Armenia,ARM,1990,2256838858.42714 +Armenia,ARM,1991,2068526521.90299 +Armenia,ARM,1992,1272577521.7683 +Armenia,ARM,1993,1201313196.45626 +Armenia,ARM,1994,1315158670.47971 +Armenia,ARM,1995,1468317350.02343 +Armenia,ARM,1996,1596968913.19202 +Armenia,ARM,1997,1639492424.38103 +Armenia,ARM,1998,1893726437.35976 +Armenia,ARM,1999,1845482181.48539 +Armenia,ARM,2000,1911563665.39006 +Armenia,ARM,2001,2118467913.37873 +Armenia,ARM,2002,2376335048.39976 +Armenia,ARM,2003,2807061008.69084 +Armenia,ARM,2004,3576615240.41616 +Armenia,ARM,2005,4900469515.07252 +Armenia,ARM,2006,6384451606.1421 +Armenia,ARM,2007,9206301700.39619 +Armenia,ARM,2008,11662040713.8753 +Armenia,ARM,2009,8647936747.98704 +Armenia,ARM,2010,9260284937.79782 +Armenia,ARM,2011,10142111334.4961 +Armenia,ARM,2012,10619320048.5857 +Armenia,ARM,2013,11121465767.4067 +Armenia,ARM,2014,11609512939.7543 +Armenia,ARM,2015,10529182498.3475 +Armenia,ARM,2016,10547331235.1895 +Aruba,ABW,1994,1330167597.76536 +Aruba,ABW,1995,1320670391.06145 +Aruba,ABW,1996,1379888268.15642 +Aruba,ABW,1997,1531843575.41899 +Aruba,ABW,1998,1665363128.49162 +Aruba,ABW,1999,1722798882.68156 +Aruba,ABW,2000,1873452513.96648 +Aruba,ABW,2001,1920262569.8324 +Aruba,ABW,2002,1941094972.06704 +Aruba,ABW,2003,2021301675.97765 +Aruba,ABW,2004,2228279329.60894 +Aruba,ABW,2005,2331005586.59218 +Aruba,ABW,2006,2421474860.3352 +Aruba,ABW,2007,2623726256.98324 +Aruba,ABW,2008,2791960893.85475 +Aruba,ABW,2009,2498932960.89385 +Aruba,ABW,2010,2467703910.61453 +Aruba,ABW,2011,2584463687.15084 +Australia,AUS,1960,18593347519.3191 +Australia,AUS,1961,19666256019.7111 +Australia,AUS,1962,19911524246.8362 +Australia,AUS,1963,21527606674.8796 +Australia,AUS,1964,23787658192.4068 +Australia,AUS,1965,25962593795.4978 +Australia,AUS,1966,27288610146.713 +Australia,AUS,1967,30421099787.2102 +Australia,AUS,1968,32687870982.1929 +Australia,AUS,1969,36659200358.3828 +Australia,AUS,1970,41304737372.6061 +Australia,AUS,1971,45183111210.6619 +Australia,AUS,1972,52003504672.8972 +Australia,AUS,1973,63782190903.2671 +Australia,AUS,1974,88906411201.1791 +Australia,AUS,1975,97226546497.3372 +Australia,AUS,1976,104974158578.092 +Australia,AUS,1977,110266116081.67 +Australia,AUS,1978,118400631626.438 +Australia,AUS,1979,134793820288.538 +Australia,AUS,1980,149887465181.059 +Australia,AUS,1981,176804829908.278 +Australia,AUS,1982,193954540439.148 +Australia,AUS,1983,177176415535.798 +Australia,AUS,1984,193503894222.061 +Australia,AUS,1985,180470967247.066 +Australia,AUS,1986,182281757134.863 +Australia,AUS,1987,189375992588.671 +Australia,AUS,1988,236135768335.274 +Australia,AUS,1989,299941372852.374 +Australia,AUS,1990,311425933051.174 +Australia,AUS,1991,326068597441.331 +Australia,AUS,1992,325692532492.502 +Australia,AUS,1993,312372821810.006 +Australia,AUS,1994,323216879972.328 +Australia,AUS,1995,368391743391.743 +Australia,AUS,1996,401819423368.74 +Australia,AUS,1997,436097980904.68 +Australia,AUS,1998,399778878111.646 +Australia,AUS,1999,389146509587.668 +Australia,AUS,2000,415446209885.072 +Australia,AUS,2001,378899860470.108 +Australia,AUS,2002,394635830891.586 +Australia,AUS,2003,466853232382.062 +Australia,AUS,2004,613329776639.636 +Australia,AUS,2005,693764095624.718 +Australia,AUS,2006,747572626534.891 +Australia,AUS,2007,853764622752.61 +Australia,AUS,2008,1055334825425.25 +Australia,AUS,2009,927168310999.853 +Australia,AUS,2010,1142876772659.21 +Australia,AUS,2011,1390557034407.97 +Australia,AUS,2012,1538194473087.23 +Australia,AUS,2013,1567178619062.28 +Australia,AUS,2014,1459597906912.7 +Australia,AUS,2015,1345383143356.35 +Australia,AUS,2016,1204616439828.41 +Austria,AUT,1960,6592693841.18495 +Austria,AUT,1961,7311749633.36229 +Austria,AUT,1962,7756110210.11966 +Austria,AUT,1963,8374175257.73075 +Austria,AUT,1964,9169983885.71185 +Austria,AUT,1965,9994070615.85997 +Austria,AUT,1966,10887682273.1014 +Austria,AUT,1967,11579431668.9165 +Austria,AUT,1968,12440625312.8685 +Austria,AUT,1969,13582798556.2404 +Austria,AUT,1970,15335972267.7957 +Austria,AUT,1971,17815464919.0439 +Austria,AUT,1972,22006470861.3608 +Austria,AUT,1973,29444365310.2818 +Austria,AUT,1974,35104529078.3274 +Austria,AUT,1975,39962704274.3146 +Austria,AUT,1976,42856485617.8569 +Austria,AUT,1977,51421585629.8393 +Austria,AUT,1978,61902774945.5131 +Austria,AUT,1979,73759181883.685 +Austria,AUT,1980,81861232822.8037 +Austria,AUT,1981,70863106877.484 +Austria,AUT,1982,71103585383.5605 +Austria,AUT,1983,71947277233.032 +Austria,AUT,1984,67821568599.1335 +Austria,AUT,1985,69219621907.4222 +Austria,AUT,1986,98797587381.7035 +Austria,AUT,1987,123869321397.475 +Austria,AUT,1988,133018182770.534 +Austria,AUT,1989,132785154342.174 +Austria,AUT,1990,166062376739.683 +Austria,AUT,1991,173375508073.07 +Austria,AUT,1992,194608183696.469 +Austria,AUT,1993,189921096652.076 +Austria,AUT,1994,203044926876.28 +Austria,AUT,1995,240457622492.152 +Austria,AUT,1996,236720496490.772 +Austria,AUT,1997,212323463750.141 +Austria,AUT,1998,217683626056.025 +Austria,AUT,1999,216725261027.062 +Austria,AUT,2000,196421706283.398 +Austria,AUT,2001,196953628635.347 +Austria,AUT,2002,212970685111.989 +Austria,AUT,2003,260721478555.305 +Austria,AUT,2004,299857238639.185 +Austria,AUT,2005,314648986444.472 +Austria,AUT,2006,334309371471.584 +Austria,AUT,2007,386458951546.674 +Austria,AUT,2008,427611527757.434 +Austria,AUT,2009,397594276187.83 +Austria,AUT,2010,390211866490.257 +Austria,AUT,2011,429037361514.409 +Austria,AUT,2012,407451583084.239 +Austria,AUT,2013,428248420485.175 +Austria,AUT,2014,438376178526.317 +Austria,AUT,2015,376967406147.987 +Austria,AUT,2016,386427793787.215 +Azerbaijan,AZE,1990,8858006035.91566 +Azerbaijan,AZE,1991,8792365810.5094 +Azerbaijan,AZE,1992,4991350457.5425 +Azerbaijan,AZE,1993,3973027396.65195 +Azerbaijan,AZE,1994,3313739673.54738 +Azerbaijan,AZE,1995,3052467522.36104 +Azerbaijan,AZE,1996,3176749593.11788 +Azerbaijan,AZE,1997,3962710163.11167 +Azerbaijan,AZE,1998,4446396217.63265 +Azerbaijan,AZE,1999,4581222442.45783 +Azerbaijan,AZE,2000,5272617196.04517 +Azerbaijan,AZE,2001,5707720390.8515 +Azerbaijan,AZE,2002,6235795103.88809 +Azerbaijan,AZE,2003,7276013031.96905 +Azerbaijan,AZE,2004,8680472168.51531 +Azerbaijan,AZE,2005,13245716099.0057 +Azerbaijan,AZE,2006,20983019923.8863 +Azerbaijan,AZE,2007,33050343782.7759 +Azerbaijan,AZE,2008,48852482960.0779 +Azerbaijan,AZE,2009,44291490420.5026 +Azerbaijan,AZE,2010,52902703376.1056 +Azerbaijan,AZE,2011,65951627200.2026 +Azerbaijan,AZE,2012,69684317718.9409 +Azerbaijan,AZE,2013,74164435946.4627 +Azerbaijan,AZE,2014,75244166772.9185 +Azerbaijan,AZE,2015,53074370486.0433 +Azerbaijan,AZE,2016,37847715736.0406 +"Bahamas, The",BHS,1960,169803921.568627 +"Bahamas, The",BHS,1961,190098039.215686 +"Bahamas, The",BHS,1962,212254901.960784 +"Bahamas, The",BHS,1963,237745098.039216 +"Bahamas, The",BHS,1964,266666666.666667 +"Bahamas, The",BHS,1965,300392156.862745 +"Bahamas, The",BHS,1966,340000000 +"Bahamas, The",BHS,1967,390196078.431373 +"Bahamas, The",BHS,1968,444901960.784314 +"Bahamas, The",BHS,1969,528137254.901961 +"Bahamas, The",BHS,1970,538423153.692615 +"Bahamas, The",BHS,1971,573400000 +"Bahamas, The",BHS,1972,590900000 +"Bahamas, The",BHS,1973,670900000 +"Bahamas, The",BHS,1974,632400000 +"Bahamas, The",BHS,1975,596200000 +"Bahamas, The",BHS,1976,642100000 +"Bahamas, The",BHS,1977,713000000 +"Bahamas, The",BHS,1978,832400000 +"Bahamas, The",BHS,1979,1139800100 +"Bahamas, The",BHS,1980,1335300000 +"Bahamas, The",BHS,1981,1426500000 +"Bahamas, The",BHS,1982,1578300000 +"Bahamas, The",BHS,1983,1732800000 +"Bahamas, The",BHS,1984,2041100000 +"Bahamas, The",BHS,1985,2320699900 +"Bahamas, The",BHS,1986,2472500000 +"Bahamas, The",BHS,1987,2713999900 +"Bahamas, The",BHS,1988,2817900000 +"Bahamas, The",BHS,1989,3062000000 +"Bahamas, The",BHS,1990,3166000000 +"Bahamas, The",BHS,1991,3111160000 +"Bahamas, The",BHS,1992,3109000000 +"Bahamas, The",BHS,1993,3092000000 +"Bahamas, The",BHS,1994,3259000000 +"Bahamas, The",BHS,1995,3429000000 +"Bahamas, The",BHS,1996,3609000000 +"Bahamas, The",BHS,1997,4961119000 +"Bahamas, The",BHS,1998,5353524000 +"Bahamas, The",BHS,1999,6019972000 +"Bahamas, The",BHS,2000,6327552000 +"Bahamas, The",BHS,2001,6516651000 +"Bahamas, The",BHS,2002,6957996000 +"Bahamas, The",BHS,2003,6949317000 +"Bahamas, The",BHS,2004,7094413000 +"Bahamas, The",BHS,2005,7706222000 +"Bahamas, The",BHS,2006,7965588000 +"Bahamas, The",BHS,2007,8318996000 +"Bahamas, The",BHS,2008,8247000000 +"Bahamas, The",BHS,2009,7820000000 +"Bahamas, The",BHS,2010,7910000000 +"Bahamas, The",BHS,2011,7890000000 +"Bahamas, The",BHS,2012,8399000000 +"Bahamas, The",BHS,2013,8522000000 +"Bahamas, The",BHS,2014,8618000000 +"Bahamas, The",BHS,2015,8854000000 +"Bahamas, The",BHS,2016,9047000000 +Bahrain,BHR,1980,3072698328.46909 +Bahrain,BHR,1981,3467819148.93617 +Bahrain,BHR,1982,3645744680.85106 +Bahrain,BHR,1983,3735106382.97872 +Bahrain,BHR,1984,3905585106.38298 +Bahrain,BHR,1985,3651861702.12766 +Bahrain,BHR,1986,3052393617.02128 +Bahrain,BHR,1987,3392021010.6383 +Bahrain,BHR,1988,3702393617.02128 +Bahrain,BHR,1989,3863563829.78723 +Bahrain,BHR,1990,4229787234.04255 +Bahrain,BHR,1991,4616223404.25532 +Bahrain,BHR,1992,4751063829.78723 +Bahrain,BHR,1993,5200265957.44681 +Bahrain,BHR,1994,5567553457.44681 +Bahrain,BHR,1995,5849467819.14894 +Bahrain,BHR,1996,6101861436.17021 +Bahrain,BHR,1997,6349202393.61702 +Bahrain,BHR,1998,6183776595.74468 +Bahrain,BHR,1999,6621010372.34043 +Bahrain,BHR,2000,9062906914.89362 +Bahrain,BHR,2001,8976207712.76596 +Bahrain,BHR,2002,9632155053.19149 +Bahrain,BHR,2003,11074822074.4681 +Bahrain,BHR,2004,13150166755.3191 +Bahrain,BHR,2005,15968726861.7021 +Bahrain,BHR,2006,18505053191.4894 +Bahrain,BHR,2007,21730000000 +Bahrain,BHR,2008,25710877659.5745 +Bahrain,BHR,2009,22938218085.1064 +Bahrain,BHR,2010,25713271276.5957 +Bahrain,BHR,2011,29157446808.5106 +Bahrain,BHR,2012,30749308510.6383 +Bahrain,BHR,2013,32898670212.766 +Bahrain,BHR,2014,33387712765.9575 +Bahrain,BHR,2015,31125851063.8298 +Bahrain,BHR,2016,31858510638.2979 +Bangladesh,BGD,1960,4274893913.46432 +Bangladesh,BGD,1961,4817580183.56657 +Bangladesh,BGD,1962,5081413339.74945 +Bangladesh,BGD,1963,5319458351.12372 +Bangladesh,BGD,1964,5386054619.31076 +Bangladesh,BGD,1965,5906636556.95802 +Bangladesh,BGD,1966,6439687598.27648 +Bangladesh,BGD,1967,7253575399.26882 +Bangladesh,BGD,1968,7483685473.4584 +Bangladesh,BGD,1969,8471006100.89247 +Bangladesh,BGD,1970,8992721809.32801 +Bangladesh,BGD,1971,8751842839.73302 +Bangladesh,BGD,1972,6288245866.66667 +Bangladesh,BGD,1973,8086725729.3407 +Bangladesh,BGD,1974,12512460519.7088 +Bangladesh,BGD,1975,19448348073.4565 +Bangladesh,BGD,1976,10117113333.3333 +Bangladesh,BGD,1977,9651149301.8746 +Bangladesh,BGD,1978,13281767142.8571 +Bangladesh,BGD,1979,15565480321.9448 +Bangladesh,BGD,1980,18138049095.6072 +Bangladesh,BGD,1981,20249694002.448 +Bangladesh,BGD,1982,18525399201.5968 +Bangladesh,BGD,1983,17609048821.5488 +Bangladesh,BGD,1984,18920840000 +Bangladesh,BGD,1985,22278423076.9231 +Bangladesh,BGD,1986,21774033333.3333 +Bangladesh,BGD,1987,24298032258.0645 +Bangladesh,BGD,1988,26579005760.315 +Bangladesh,BGD,1989,28781714763.7823 +Bangladesh,BGD,1990,31598341233.5793 +Bangladesh,BGD,1991,30957483290.541 +Bangladesh,BGD,1992,31708873954.9405 +Bangladesh,BGD,1993,33166520084.8295 +Bangladesh,BGD,1994,33768662171.2233 +Bangladesh,BGD,1995,37939748051.3878 +Bangladesh,BGD,1996,46438482370.3942 +Bangladesh,BGD,1997,48244308274.8086 +Bangladesh,BGD,1998,49984559471.3656 +Bangladesh,BGD,1999,51270569883.5275 +Bangladesh,BGD,2000,53369787318.6245 +Bangladesh,BGD,2001,53991289844.3291 +Bangladesh,BGD,2002,54724081490.5102 +Bangladesh,BGD,2003,60158929188.2556 +Bangladesh,BGD,2004,65108544250.0425 +Bangladesh,BGD,2005,69442943089.4309 +Bangladesh,BGD,2006,71819083683.7403 +Bangladesh,BGD,2007,79611888213.148 +Bangladesh,BGD,2008,91631278239.3237 +Bangladesh,BGD,2009,102477791472.39 +Bangladesh,BGD,2010,115279077465.226 +Bangladesh,BGD,2011,128637938711.386 +Bangladesh,BGD,2012,133355749482.478 +Bangladesh,BGD,2013,149990451022.29 +Bangladesh,BGD,2014,172885454931.453 +Bangladesh,BGD,2015,195078561219.325 +Bangladesh,BGD,2016,221415280325.518 +Barbados,BRB,1980,1012264035.93834 +Barbados,BRB,1981,1114104641.92324 +Barbados,BRB,1982,1164059789.75045 +Barbados,BRB,1983,1235775210.81961 +Barbados,BRB,1984,1347033586.80082 +Barbados,BRB,1985,1409740726.1551 +Barbados,BRB,1986,1547790025.47984 +Barbados,BRB,1987,1704440882.93392 +Barbados,BRB,1988,1812891396.47311 +Barbados,BRB,1989,2006394477.47387 +Barbados,BRB,1990,2012302519.52124 +Barbados,BRB,1991,2020744653.61842 +Barbados,BRB,1992,1957168343.54374 +Barbados,BRB,1993,2063267995.73752 +Barbados,BRB,1994,2151285060.49141 +Barbados,BRB,1995,2261996995.18515 +Barbados,BRB,1996,2411846465.43502 +Barbados,BRB,1997,2549260575.07039 +Barbados,BRB,1998,2874413287.26735 +Barbados,BRB,1999,3012021852.2502 +Barbados,BRB,2000,3121619807.97687 +Barbados,BRB,2001,3116632412.98352 +Barbados,BRB,2002,3169612598.33334 +Barbados,BRB,2003,3274856571.16604 +Barbados,BRB,2004,3514370691.25563 +Barbados,BRB,2005,3897467233.85757 +Barbados,BRB,2006,4303275572.40197 +Barbados,BRB,2007,4546115388.40716 +Barbados,BRB,2008,4595264650 +Barbados,BRB,2009,4601250000 +Barbados,BRB,2010,4446800000 +Barbados,BRB,2011,4358900000 +Barbados,BRB,2012,4332150000 +Barbados,BRB,2013,4371200000 +Barbados,BRB,2014,4352700000 +Barbados,BRB,2015,4421800000 +Barbados,BRB,2016,4587550000 +Belarus,BLR,1990,21650000000 +Belarus,BLR,1991,17420000000 +Belarus,BLR,1992,17120370370.3704 +Belarus,BLR,1993,16286280991.7355 +Belarus,BLR,1994,14932192010.7419 +Belarus,BLR,1995,13972630803.5817 +Belarus,BLR,1996,14756861538.4615 +Belarus,BLR,1997,14128412417.193 +Belarus,BLR,1998,15222014828.3039 +Belarus,BLR,1999,12138485328.6267 +Belarus,BLR,2000,12736856827.9847 +Belarus,BLR,2001,12354820143.8849 +Belarus,BLR,2002,14594925392.9691 +Belarus,BLR,2003,17825436034.5366 +Belarus,BLR,2004,23141587717.7633 +Belarus,BLR,2005,30210091836.8294 +Belarus,BLR,2006,36961821893.6976 +Belarus,BLR,2007,45275747860.6442 +Belarus,BLR,2008,60752177438.8895 +Belarus,BLR,2009,49208656976.0389 +Belarus,BLR,2010,57231904542.8755 +Belarus,BLR,2011,61762341356.8996 +Belarus,BLR,2012,65685903833.0838 +Belarus,BLR,2013,75527537703.1836 +Belarus,BLR,2014,78813049849.6078 +Belarus,BLR,2015,56454775870.958 +Belarus,BLR,2016,47433442293.1858 +Belgium,BEL,1960,11658722590.99 +Belgium,BEL,1961,12400145221.595 +Belgium,BEL,1962,13264015675.3193 +Belgium,BEL,1963,14260017387.0492 +Belgium,BEL,1964,15960106680.6732 +Belgium,BEL,1965,17371457607.9374 +Belgium,BEL,1966,18651883472.4808 +Belgium,BEL,1967,19992040788.4593 +Belgium,BEL,1968,21376353113.475 +Belgium,BEL,1969,23710735894.7022 +Belgium,BEL,1970,26849173618.3945 +Belgium,BEL,1971,29981318394.8688 +Belgium,BEL,1972,37408626615.3423 +Belgium,BEL,1973,47999408507.5554 +Belgium,BEL,1974,56333063690.9693 +Belgium,BEL,1975,66029811341.45 +Belgium,BEL,1976,71494607105.5381 +Belgium,BEL,1977,83283407090.6021 +Belgium,BEL,1978,101788571282.183 +Belgium,BEL,1979,116938177352.779 +Belgium,BEL,1980,127508322941.095 +Belgium,BEL,1981,105290713602.781 +Belgium,BEL,1982,92588982518.0999 +Belgium,BEL,1983,87650998816.568 +Belgium,BEL,1984,83795759983.2449 +Belgium,BEL,1985,86730120728.3103 +Belgium,BEL,1986,120661334386.852 +Belgium,BEL,1987,150194219665.046 +Belgium,BEL,1988,163168007789.358 +Belgium,BEL,1989,165100250614.251 +Belgium,BEL,1990,206431036697.248 +Belgium,BEL,1991,211638016538.689 +Belgium,BEL,1992,236038607528.231 +Belgium,BEL,1993,225924893540.112 +Belgium,BEL,1994,246195171328.671 +Belgium,BEL,1995,289567597153.804 +Belgium,BEL,1996,281357654723.127 +Belgium,BEL,1997,254813937753.721 +Belgium,BEL,1998,260602356079.129 +Belgium,BEL,1999,260202429149.798 +Belgium,BEL,2000,237904919845.218 +Belgium,BEL,2001,237841610738.255 +Belgium,BEL,2002,258860342555.995 +Belgium,BEL,2003,319003386004.515 +Belgium,BEL,2004,370885274397.815 +Belgium,BEL,2005,387365999253.824 +Belgium,BEL,2006,409813072387.404 +Belgium,BEL,2007,471821790309.335 +Belgium,BEL,2008,518626043650.212 +Belgium,BEL,2009,484552653514.865 +Belgium,BEL,2010,483548693409.337 +Belgium,BEL,2011,527008036846.811 +Belgium,BEL,2012,497884088082.651 +Belgium,BEL,2013,520117140495.059 +Belgium,BEL,2014,531750903174.686 +Belgium,BEL,2015,454991318727.907 +Belgium,BEL,2016,466365727353.85 +Belize,BLZ,1960,28071888.5622288 +Belize,BLZ,1961,29964370.7125857 +Belize,BLZ,1962,31856922.8615428 +Belize,BLZ,1963,33749405.0118998 +Belize,BLZ,1964,36193826.1234775 +Belize,BLZ,1965,40069930.0699301 +Belize,BLZ,1966,44405594.4055944 +Belize,BLZ,1967,47379310.3448276 +Belize,BLZ,1968,44910179.6407186 +Belize,BLZ,1969,47305389.2215569 +Belize,BLZ,1970,53233532.9341317 +Belize,BLZ,1971,59207317.0731707 +Belize,BLZ,1972,66062500 +Belize,BLZ,1973,78343558.2822086 +Belize,BLZ,1974,103216374.269006 +Belize,BLZ,1975,118066298.342541 +Belize,BLZ,1976,96905829.5964126 +Belize,BLZ,1977,117650000 +Belize,BLZ,1978,136300000 +Belize,BLZ,1979,151800000 +Belize,BLZ,1980,194750000 +Belize,BLZ,1981,192900000 +Belize,BLZ,1982,179250000 +Belize,BLZ,1983,189000000 +Belize,BLZ,1984,210900000 +Belize,BLZ,1985,209150000 +Belize,BLZ,1986,227850000 +Belize,BLZ,1987,276550000 +Belize,BLZ,1988,314900000 +Belize,BLZ,1989,363150000 +Belize,BLZ,1990,413050000 +Belize,BLZ,1991,444720750 +Belize,BLZ,1992,518239100 +Belize,BLZ,1993,559858250 +Belize,BLZ,1994,580863700 +Belize,BLZ,1995,620140400 +Belize,BLZ,1996,641383800 +Belize,BLZ,1997,654314350 +Belize,BLZ,1998,688992450 +Belize,BLZ,1999,732732350 +Belize,BLZ,2000,832072450 +Belize,BLZ,2001,871860600 +Belize,BLZ,2002,932551850 +Belize,BLZ,2003,990374050 +Belize,BLZ,2004,1057845500 +Belize,BLZ,2005,1114222550 +Belize,BLZ,2006,1217467600 +Belize,BLZ,2007,1290573400 +Belize,BLZ,2008,1368625150 +Belize,BLZ,2009,1336957250 +Belize,BLZ,2010,1397113450 +Belize,BLZ,2011,1486712300 +Belize,BLZ,2012,1573618750 +Belize,BLZ,2013,1613705850 +Belize,BLZ,2014,1706497950 +Belize,BLZ,2015,1742545900 +Belize,BLZ,2016,1765256400 +Benin,BEN,1960,226195579.35701 +Benin,BEN,1961,235668222.429984 +Benin,BEN,1962,236434906.75427 +Benin,BEN,1963,253927646.475909 +Benin,BEN,1964,269818988.259263 +Benin,BEN,1965,289908720.648622 +Benin,BEN,1966,302925280.773564 +Benin,BEN,1967,306222000.407316 +Benin,BEN,1968,326323097.355964 +Benin,BEN,1969,330748211.459737 +Benin,BEN,1970,333627758.154666 +Benin,BEN,1971,335072975.215766 +Benin,BEN,1972,410331900.950531 +Benin,BEN,1973,504376035.716401 +Benin,BEN,1974,554654786.965107 +Benin,BEN,1975,676870140.341529 +Benin,BEN,1976,698408244.385343 +Benin,BEN,1977,750049739.152238 +Benin,BEN,1978,928843304.783965 +Benin,BEN,1979,1186231265.18417 +Benin,BEN,1980,1405251547.23882 +Benin,BEN,1981,1291119965.11262 +Benin,BEN,1982,1267778489.03079 +Benin,BEN,1983,1095348302.91865 +Benin,BEN,1984,1051133927.00009 +Benin,BEN,1985,1045712703.02696 +Benin,BEN,1986,1336102040.71025 +Benin,BEN,1987,1562412030.34838 +Benin,BEN,1988,1620246187.15171 +Benin,BEN,1989,1502294411.46202 +Benin,BEN,1990,1959965243.76269 +Benin,BEN,1991,1986437859.90346 +Benin,BEN,1992,1695315305.70308 +Benin,BEN,1993,2274557914.07481 +Benin,BEN,1994,1598075932.35432 +Benin,BEN,1995,2169627250.93379 +Benin,BEN,1996,2361116587.86079 +Benin,BEN,1997,2268301537.65128 +Benin,BEN,1998,2455092582.30927 +Benin,BEN,1999,2689787917.50711 +Benin,BEN,2000,2569186642.86999 +Benin,BEN,2001,2680213931.46472 +Benin,BEN,2002,3054571081.6912 +Benin,BEN,2003,3905366187.87017 +Benin,BEN,2004,4521424807.22519 +Benin,BEN,2005,4803702821.08055 +Benin,BEN,2006,5142380779.44103 +Benin,BEN,2007,5969535131.58016 +Benin,BEN,2008,7132787396.66547 +Benin,BEN,2009,7097198711.61023 +Benin,BEN,2010,6970240895.49888 +Benin,BEN,2011,7814081155.64988 +Benin,BEN,2012,8152554487.31321 +Benin,BEN,2013,9156748441.42175 +Benin,BEN,2014,9707432015.61441 +Benin,BEN,2015,8290986804.45245 +Benin,BEN,2016,8583031398.21675 +Bermuda,BMU,1960,84466654.0801544 +Bermuda,BMU,1961,89249986.7007156 +Bermuda,BMU,1962,94149985.9705588 +Bermuda,BMU,1963,96366652.3069165 +Bermuda,BMU,1964,107566650.637987 +Bermuda,BMU,1965,114339048.962736 +Bermuda,BMU,1966,134173373.782802 +Bermuda,BMU,1967,155102984.621576 +Bermuda,BMU,1968,150000000 +Bermuda,BMU,1969,164900000 +Bermuda,BMU,1970,186300000 +Bermuda,BMU,1971,211100000 +Bermuda,BMU,1972,235400000 +Bermuda,BMU,1973,269500000 +Bermuda,BMU,1974,312600000 +Bermuda,BMU,1975,345000000 +Bermuda,BMU,1976,386300000 +Bermuda,BMU,1977,447000000 +Bermuda,BMU,1978,475800000 +Bermuda,BMU,1979,517200000 +Bermuda,BMU,1980,613299968 +Bermuda,BMU,1981,739100032 +Bermuda,BMU,1982,785500032 +Bermuda,BMU,1983,889400000 +Bermuda,BMU,1984,985699968 +Bermuda,BMU,1985,1039500032 +Bermuda,BMU,1986,1173500032 +Bermuda,BMU,1987,1296499968 +Bermuda,BMU,1988,1415100032 +Bermuda,BMU,1989,1501500032 +Bermuda,BMU,1990,1592400000 +Bermuda,BMU,1991,1634899968 +Bermuda,BMU,1992,1679900032 +Bermuda,BMU,1993,1820359936 +Bermuda,BMU,1994,1867160064 +Bermuda,BMU,1995,2030749952 +Bermuda,BMU,1996,2695390000 +Bermuda,BMU,1997,2932827000 +Bermuda,BMU,1998,3130748000 +Bermuda,BMU,1999,3324433000 +Bermuda,BMU,2000,3480219000 +Bermuda,BMU,2001,3680483000 +Bermuda,BMU,2002,3937228000 +Bermuda,BMU,2003,4186525000 +Bermuda,BMU,2004,4484703000 +Bermuda,BMU,2005,4868136000 +Bermuda,BMU,2006,5414299000 +Bermuda,BMU,2007,5895048000 +Bermuda,BMU,2008,6109928000 +Bermuda,BMU,2009,5806378000 +Bermuda,BMU,2010,5744414000 +Bermuda,BMU,2011,5550771000 +Bermuda,BMU,2012,5537537000 +Bermuda,BMU,2013,5573710000 +Bhutan,BTN,1980,135653295.165394 +Bhutan,BTN,1981,146391639.722864 +Bhutan,BTN,1982,148934334.038055 +Bhutan,BTN,1983,165585940.594059 +Bhutan,BTN,1984,169264991.197183 +Bhutan,BTN,1985,172217502.021019 +Bhutan,BTN,1986,201375725.614592 +Bhutan,BTN,1987,253182453.703704 +Bhutan,BTN,1988,283855833.333333 +Bhutan,BTN,1989,275949889.09427 +Bhutan,BTN,1990,299787275.842376 +Bhutan,BTN,1991,250045839.929639 +Bhutan,BTN,1992,250794359.567901 +Bhutan,BTN,1993,235239570.350935 +Bhutan,BTN,1994,270801565.189672 +Bhutan,BTN,1995,303053462.843047 +Bhutan,BTN,1996,316420860.852385 +Bhutan,BTN,1997,365964500.137703 +Bhutan,BTN,1998,376955087.251575 +Bhutan,BTN,1999,419035810.496981 +Bhutan,BTN,2000,439158233.199822 +Bhutan,BTN,2001,476360697.181606 +Bhutan,BTN,2002,537050133.717342 +Bhutan,BTN,2003,622026107.771576 +Bhutan,BTN,2004,702682018.976169 +Bhutan,BTN,2005,818869145.124717 +Bhutan,BTN,2006,897731524.929922 +Bhutan,BTN,2007,1196091805.02316 +Bhutan,BTN,2008,1258332337.28382 +Bhutan,BTN,2009,1264758197.96593 +Bhutan,BTN,2010,1585472534.10547 +Bhutan,BTN,2011,1820207625.80217 +Bhutan,BTN,2012,1823692109.61652 +Bhutan,BTN,2013,1798333725.83954 +Bhutan,BTN,2014,1958819914.95916 +Bhutan,BTN,2015,2057947621.19283 +Bhutan,BTN,2016,2236933237.89015 +Bolivia,BOL,1960,563110051.920733 +Bolivia,BOL,1961,612518906.826491 +Bolivia,BOL,1962,669722541.277818 +Bolivia,BOL,1963,721142957.311474 +Bolivia,BOL,1964,812543072.505384 +Bolivia,BOL,1965,908874537.037037 +Bolivia,BOL,1966,994044553.872054 +Bolivia,BOL,1967,1084059814.81481 +Bolivia,BOL,1968,908874537.037037 +Bolivia,BOL,1969,964615698.653199 +Bolivia,BOL,1970,1017171717.17172 +Bolivia,BOL,1971,1095454545.45455 +Bolivia,BOL,1972,1257615644.97932 +Bolivia,BOL,1973,1263018490.75462 +Bolivia,BOL,1974,2100249875.06247 +Bolivia,BOL,1975,2404697651.17441 +Bolivia,BOL,1976,2732083958.02099 +Bolivia,BOL,1977,3227436281.85907 +Bolivia,BOL,1978,3758220889.55522 +Bolivia,BOL,1979,4421343606.18135 +Bolivia,BOL,1980,4537487842.57749 +Bolivia,BOL,1981,5891606676.18271 +Bolivia,BOL,1982,5594118400.16731 +Bolivia,BOL,1983,5422656261.71049 +Bolivia,BOL,1984,6169481549.37482 +Bolivia,BOL,1985,5377277406.71638 +Bolivia,BOL,1986,3959379487.6064 +Bolivia,BOL,1987,4347956298.51327 +Bolivia,BOL,1988,4597615562.66594 +Bolivia,BOL,1989,4715978868.21613 +Bolivia,BOL,1990,4867582620.20708 +Bolivia,BOL,1991,5343274311.56789 +Bolivia,BOL,1992,5643893347.00679 +Bolivia,BOL,1993,5734676560.92471 +Bolivia,BOL,1994,5981244886.917 +Bolivia,BOL,1995,6715220507.05164 +Bolivia,BOL,1996,7396966657.47054 +Bolivia,BOL,1997,7925673448.41368 +Bolivia,BOL,1998,8497545598.08352 +Bolivia,BOL,1999,8285075872.27307 +Bolivia,BOL,2000,8397912509.09679 +Bolivia,BOL,2001,8141537937.61068 +Bolivia,BOL,2002,7905485216.17852 +Bolivia,BOL,2003,8082364868.39357 +Bolivia,BOL,2004,8773451738.91129 +Bolivia,BOL,2005,9549077869.10651 +Bolivia,BOL,2006,11451869164.7112 +Bolivia,BOL,2007,13120159975.5451 +Bolivia,BOL,2008,16674324634.2373 +Bolivia,BOL,2009,17339992165.2422 +Bolivia,BOL,2010,19649631308.1648 +Bolivia,BOL,2011,23963033443.8518 +Bolivia,BOL,2012,27084497539.7974 +Bolivia,BOL,2013,30659338929.0883 +Bolivia,BOL,2014,32996187988.4226 +Bolivia,BOL,2015,33000198263.3864 +Bolivia,BOL,2016,33806395513.7482 +Bosnia and Herzegovina,BIH,1994,1255802469.1358 +Bosnia and Herzegovina,BIH,1995,1866572953.73666 +Bosnia and Herzegovina,BIH,1996,2786045321.63743 +Bosnia and Herzegovina,BIH,1997,3671816504.23851 +Bosnia and Herzegovina,BIH,1998,4116699437.4041 +Bosnia and Herzegovina,BIH,1999,4685729738.56209 +Bosnia and Herzegovina,BIH,2000,5505984455.95855 +Bosnia and Herzegovina,BIH,2001,5748990666.17862 +Bosnia and Herzegovina,BIH,2002,6651226179.01829 +Bosnia and Herzegovina,BIH,2003,8370020196.19158 +Bosnia and Herzegovina,BIH,2004,10022840634.9206 +Bosnia and Herzegovina,BIH,2005,11225138297.1959 +Bosnia and Herzegovina,BIH,2006,12866524918.2221 +Bosnia and Herzegovina,BIH,2007,15776422673.198 +Bosnia and Herzegovina,BIH,2008,19101454463.7507 +Bosnia and Herzegovina,BIH,2009,17600630726.6141 +Bosnia and Herzegovina,BIH,2010,17164279813.0968 +Bosnia and Herzegovina,BIH,2011,18629346790.8167 +Bosnia and Herzegovina,BIH,2012,17207367625.8048 +Bosnia and Herzegovina,BIH,2013,18154290272.2151 +Bosnia and Herzegovina,BIH,2014,18521475376.4754 +Bosnia and Herzegovina,BIH,2015,16173806634.5336 +Bosnia and Herzegovina,BIH,2016,16559695718.568 +Botswana,BWA,1960,30412308.9864012 +Botswana,BWA,1961,32902336.644746 +Botswana,BWA,1962,35643207.6265246 +Botswana,BWA,1963,38091150.566196 +Botswana,BWA,1964,41613969.0506064 +Botswana,BWA,1965,45790869.7473126 +Botswana,BWA,1966,51464435.1464435 +Botswana,BWA,1967,58646443.5146444 +Botswana,BWA,1968,66248256.6248257 +Botswana,BWA,1969,77356914.0788191 +Botswana,BWA,1970,96245114.4611949 +Botswana,BWA,1971,126957494.407159 +Botswana,BWA,1972,165258093.875959 +Botswana,BWA,1973,244129088.027662 +Botswana,BWA,1974,306033848.417954 +Botswana,BWA,1975,355172413.793103 +Botswana,BWA,1976,372010119.595216 +Botswana,BWA,1977,451603325.415677 +Botswana,BWA,1978,590376720.598889 +Botswana,BWA,1979,819877300.613497 +Botswana,BWA,1980,1060923829.13021 +Botswana,BWA,1981,1073861599.13948 +Botswana,BWA,1982,1014907254.54016 +Botswana,BWA,1983,1172258182.14969 +Botswana,BWA,1984,1240796364.75662 +Botswana,BWA,1985,1114764007.14811 +Botswana,BWA,1986,1392634771.9653 +Botswana,BWA,1987,1965274882.36345 +Botswana,BWA,1988,2644536804.11244 +Botswana,BWA,1989,3083800684.89751 +Botswana,BWA,1990,3790567051.86778 +Botswana,BWA,1991,3942792837.35655 +Botswana,BWA,1992,4146513722.33019 +Botswana,BWA,1993,4160086253.1468 +Botswana,BWA,1994,4259330999.03151 +Botswana,BWA,1995,4730611067.02258 +Botswana,BWA,1996,4847752842.78924 +Botswana,BWA,1997,5020214747.45261 +Botswana,BWA,1998,4790458837.17078 +Botswana,BWA,1999,5484257417.17844 +Botswana,BWA,2000,5788329609.15755 +Botswana,BWA,2001,5489608299.66445 +Botswana,BWA,2002,5438857106.73536 +Botswana,BWA,2003,7511582173.37724 +Botswana,BWA,2004,8957467706.5354 +Botswana,BWA,2005,9931134940.51346 +Botswana,BWA,2006,10126940513.3125 +Botswana,BWA,2007,10939053367.1521 +Botswana,BWA,2008,10945070441.9283 +Botswana,BWA,2009,10267133177.7334 +Botswana,BWA,2010,12786654365.8738 +Botswana,BWA,2011,15682926890.0326 +Botswana,BWA,2012,14686278713.5189 +Botswana,BWA,2013,14915780533.086 +Botswana,BWA,2014,16259445049.7698 +Botswana,BWA,2015,14430608463.4399 +Botswana,BWA,2016,15274861068.209 +Brazil,BRA,1960,15165569912.5199 +Brazil,BRA,1961,15236854859.469 +Brazil,BRA,1962,19926293839.0163 +Brazil,BRA,1963,23021477292.2093 +Brazil,BRA,1964,21211892259.9904 +Brazil,BRA,1965,21790035117.19 +Brazil,BRA,1966,27062716577.9111 +Brazil,BRA,1967,30591834053.9653 +Brazil,BRA,1968,33875881876.3672 +Brazil,BRA,1969,37458898243.8609 +Brazil,BRA,1970,42327600098.2412 +Brazil,BRA,1971,49204456700.4516 +Brazil,BRA,1972,58539008786.3684 +Brazil,BRA,1973,79279057730.829 +Brazil,BRA,1974,105136007528.76 +Brazil,BRA,1975,123709376567.89 +Brazil,BRA,1976,152678020452.829 +Brazil,BRA,1977,176171284311.761 +Brazil,BRA,1978,200800891870.164 +Brazil,BRA,1979,224969488835.181 +Brazil,BRA,1980,235024598983.261 +Brazil,BRA,1981,263561088977.129 +Brazil,BRA,1982,281682304161.041 +Brazil,BRA,1983,203304515490.795 +Brazil,BRA,1984,209023912696.839 +Brazil,BRA,1985,222942790435.299 +Brazil,BRA,1986,268137224729.722 +Brazil,BRA,1987,294084112392.66 +Brazil,BRA,1988,330397381998.489 +Brazil,BRA,1989,425595310000 +Brazil,BRA,1990,461951782000 +Brazil,BRA,1991,602860000000 +Brazil,BRA,1992,400599250000 +Brazil,BRA,1993,437798577639.752 +Brazil,BRA,1994,558111997497.263 +Brazil,BRA,1995,785643456467.255 +Brazil,BRA,1996,850425828275.793 +Brazil,BRA,1997,883199443413.729 +Brazil,BRA,1998,863723395088.324 +Brazil,BRA,1999,599388879704.634 +Brazil,BRA,2000,655421153320.579 +Brazil,BRA,2001,559372502338.237 +Brazil,BRA,2002,507962741819.919 +Brazil,BRA,2003,558320116997.075 +Brazil,BRA,2004,669316239316.239 +Brazil,BRA,2005,891629970423.924 +Brazil,BRA,2006,1107640325472.35 +Brazil,BRA,2007,1397084381901.29 +Brazil,BRA,2008,1695824517395.57 +Brazil,BRA,2009,1667019605881.76 +Brazil,BRA,2010,2208871646202.82 +Brazil,BRA,2011,2616201578192.25 +Brazil,BRA,2012,2465188674415.03 +Brazil,BRA,2013,2472806919901.67 +Brazil,BRA,2014,2455993200170 +Brazil,BRA,2015,1803652649613.75 +Brazil,BRA,2016,1796186586414.45 +Brunei Darussalam,BRN,1965,114040245.655299 +Brunei Darussalam,BRN,1966,132758395.400497 +Brunei Darussalam,BRN,1967,139030445.576898 +Brunei Darussalam,BRN,1968,160819286.554292 +Brunei Darussalam,BRN,1969,161211289.690318 +Brunei Darussalam,BRN,1970,179080099.307461 +Brunei Darussalam,BRN,1971,197523179.241883 +Brunei Darussalam,BRN,1972,270818555.823521 +Brunei Darussalam,BRN,1973,433092003.579273 +Brunei Darussalam,BRN,1974,1073577085.64159 +Brunei Darussalam,BRN,1975,1168304305.65513 +Brunei Darussalam,BRN,1976,1423061356.64562 +Brunei Darussalam,BRN,1977,1732721160.94122 +Brunei Darussalam,BRN,1978,1941600703.60598 +Brunei Darussalam,BRN,1979,2803780005.51826 +Brunei Darussalam,BRN,1980,4928824957.9675 +Brunei Darussalam,BRN,1981,4366213849.57637 +Brunei Darussalam,BRN,1982,4264252336.4486 +Brunei Darussalam,BRN,1983,3844723142.45149 +Brunei Darussalam,BRN,1984,3782523088.4628 +Brunei Darussalam,BRN,1985,3523612563.06532 +Brunei Darussalam,BRN,1986,2358592817.12134 +Brunei Darussalam,BRN,1987,2754463437.79677 +Brunei Darussalam,BRN,1988,2690717551.18267 +Brunei Darussalam,BRN,1989,2985467979.28524 +Brunei Darussalam,BRN,1990,3520551724.13793 +Brunei Darussalam,BRN,1991,3701667052.55846 +Brunei Darussalam,BRN,1992,4183548189.07305 +Brunei Darussalam,BRN,1993,4105706151.75145 +Brunei Darussalam,BRN,1994,4087337959.93191 +Brunei Darussalam,BRN,1995,4734020036.68689 +Brunei Darussalam,BRN,1996,5115602836.87943 +Brunei Darussalam,BRN,1997,5197332974.13793 +Brunei Darussalam,BRN,1998,4051147227.53346 +Brunei Darussalam,BRN,1999,4600000000 +Brunei Darussalam,BRN,2000,6001153306.2645 +Brunei Darussalam,BRN,2001,5601090584.36122 +Brunei Darussalam,BRN,2002,5843329107.56171 +Brunei Darussalam,BRN,2003,6557333084.60567 +Brunei Darussalam,BRN,2004,7872333215.00414 +Brunei Darussalam,BRN,2005,9531402847.87311 +Brunei Darussalam,BRN,2006,11470703002.0769 +Brunei Darussalam,BRN,2007,12247694247.2298 +Brunei Darussalam,BRN,2008,14393099068.5859 +Brunei Darussalam,BRN,2009,10732366286.2643 +Brunei Darussalam,BRN,2010,13707370737.0737 +Brunei Darussalam,BRN,2011,18525319977.7407 +Brunei Darussalam,BRN,2012,19048495518.5659 +Brunei Darussalam,BRN,2013,18093829923.2737 +Brunei Darussalam,BRN,2014,17123125493.2912 +Brunei Darussalam,BRN,2015,12930394937.8137 +Brunei Darussalam,BRN,2016,11400266877.3769 +Bulgaria,BGR,1980,19839230769.2308 +Bulgaria,BGR,1981,19870000000 +Bulgaria,BGR,1982,19342000000 +Bulgaria,BGR,1983,16563666666.6667 +Bulgaria,BGR,1984,17594944444.4444 +Bulgaria,BGR,1985,17155421052.6316 +Bulgaria,BGR,1986,20249294117.6471 +Bulgaria,BGR,1987,28101000000 +Bulgaria,BGR,1988,22555941176.4706 +Bulgaria,BGR,1989,21988444444.4444 +Bulgaria,BGR,1990,20632090909.0909 +Bulgaria,BGR,1991,10943548387.0968 +Bulgaria,BGR,1992,10350515463.9175 +Bulgaria,BGR,1993,10829710144.9275 +Bulgaria,BGR,1994,9697416974.16974 +Bulgaria,BGR,1995,13063422619.0476 +Bulgaria,BGR,1996,10109404159.6402 +Bulgaria,BGR,1997,11195630536.8928 +Bulgaria,BGR,1998,14630974778.4594 +Bulgaria,BGR,1999,13495062850.302 +Bulgaria,BGR,2000,13148099185.2305 +Bulgaria,BGR,2001,14135393875.5893 +Bulgaria,BGR,2002,16360346653.8276 +Bulgaria,BGR,2003,21074775206.3254 +Bulgaria,BGR,2004,26094622563.6468 +Bulgaria,BGR,2005,29821662537.3229 +Bulgaria,BGR,2006,34304448149.8108 +Bulgaria,BGR,2007,44765733379.986 +Bulgaria,BGR,2008,54666642734.2757 +Bulgaria,BGR,2009,51783454183.5501 +Bulgaria,BGR,2010,50610031135.7791 +Bulgaria,BGR,2011,57418391041.5926 +Bulgaria,BGR,2012,53903028252.2996 +Bulgaria,BGR,2013,55758744571.1183 +Bulgaria,BGR,2014,56732006512.0065 +Bulgaria,BGR,2015,50199117547.0415 +Bulgaria,BGR,2016,52395164027.1493 +Burkina Faso,BFA,1960,330442817.168859 +Burkina Faso,BFA,1961,350247237.11684 +Burkina Faso,BFA,1962,379567178.256898 +Burkina Faso,BFA,1963,394040749.12567 +Burkina Faso,BFA,1964,410321785.631059 +Burkina Faso,BFA,1965,422916848.424208 +Burkina Faso,BFA,1966,433889831.584706 +Burkina Faso,BFA,1967,450753993.176448 +Burkina Faso,BFA,1968,460442864.205949 +Burkina Faso,BFA,1969,478298781.545658 +Burkina Faso,BFA,1970,458404330.125096 +Burkina Faso,BFA,1971,482411278.982439 +Burkina Faso,BFA,1972,578595583.975723 +Burkina Faso,BFA,1973,674773821.151416 +Burkina Faso,BFA,1974,751133642.647461 +Burkina Faso,BFA,1975,939972703.463021 +Burkina Faso,BFA,1976,976547572.215824 +Burkina Faso,BFA,1977,1131225278.77773 +Burkina Faso,BFA,1978,1475584037.28156 +Burkina Faso,BFA,1979,1748480982.18517 +Burkina Faso,BFA,1980,1928720390.28869 +Burkina Faso,BFA,1981,1775842679.94056 +Burkina Faso,BFA,1982,1754450379.2077 +Burkina Faso,BFA,1983,1600278756.43589 +Burkina Faso,BFA,1984,1459880352.6483 +Burkina Faso,BFA,1985,1552493413.98989 +Burkina Faso,BFA,1986,2036303381.20142 +Burkina Faso,BFA,1987,2369835438.62393 +Burkina Faso,BFA,1988,2616040645.87263 +Burkina Faso,BFA,1989,2615588545.68629 +Burkina Faso,BFA,1990,3101301780.95067 +Burkina Faso,BFA,1991,3135045684.1006 +Burkina Faso,BFA,1992,2240264711.54816 +Burkina Faso,BFA,1993,2332018010.55341 +Burkina Faso,BFA,1994,1895290964.80829 +Burkina Faso,BFA,1995,2379518099.2266 +Burkina Faso,BFA,1996,2586550747.09844 +Burkina Faso,BFA,1997,2447669403.89018 +Burkina Faso,BFA,1998,2804902723.73145 +Burkina Faso,BFA,1999,2993753187.09677 +Burkina Faso,BFA,2000,2628920056.10098 +Burkina Faso,BFA,2001,2812845513.57125 +Burkina Faso,BFA,2002,3205592289.79773 +Burkina Faso,BFA,2003,4205691222.11396 +Burkina Faso,BFA,2004,4838551099.70985 +Burkina Faso,BFA,2005,5462709498.45119 +Burkina Faso,BFA,2006,5844669845.53733 +Burkina Faso,BFA,2007,6771277870.96412 +Burkina Faso,BFA,2008,8369637065.40255 +Burkina Faso,BFA,2009,8369175126.25316 +Burkina Faso,BFA,2010,8979966766.07232 +Burkina Faso,BFA,2011,10724061338.5874 +Burkina Faso,BFA,2012,11166061507.8024 +Burkina Faso,BFA,2013,11934606509.5944 +Burkina Faso,BFA,2014,12400688571.1396 +Burkina Faso,BFA,2015,11148759324.507 +Burkina Faso,BFA,2016,12115155931.5461 +Burundi,BDI,1960,195999990 +Burundi,BDI,1961,202999992 +Burundi,BDI,1962,213500006 +Burundi,BDI,1963,232749998 +Burundi,BDI,1964,260750008 +Burundi,BDI,1965,158994962.962963 +Burundi,BDI,1966,165444571.428571 +Burundi,BDI,1967,178297142.857143 +Burundi,BDI,1968,183200000 +Burundi,BDI,1969,190205714.285714 +Burundi,BDI,1970,242732571.428571 +Burundi,BDI,1971,252842285.714286 +Burundi,BDI,1972,246804571.428571 +Burundi,BDI,1973,304339839.552146 +Burundi,BDI,1974,345263492.063492 +Burundi,BDI,1975,420986666.666667 +Burundi,BDI,1976,448412753.623188 +Burundi,BDI,1977,547535555.555556 +Burundi,BDI,1978,610225555.555556 +Burundi,BDI,1979,782496666.666667 +Burundi,BDI,1980,919726666.666667 +Burundi,BDI,1981,969046666.666667 +Burundi,BDI,1982,1013222222.22222 +Burundi,BDI,1983,1082926304.46477 +Burundi,BDI,1984,987143931.166987 +Burundi,BDI,1985,1149979285.77347 +Burundi,BDI,1986,1201725497.06578 +Burundi,BDI,1987,1131466494.01101 +Burundi,BDI,1988,1082403219.48787 +Burundi,BDI,1989,1113924130.41149 +Burundi,BDI,1990,1132101252.51817 +Burundi,BDI,1991,1167398478.3459 +Burundi,BDI,1992,1083037670.60484 +Burundi,BDI,1993,938632612.026359 +Burundi,BDI,1994,925030590.153683 +Burundi,BDI,1995,1000428393.88528 +Burundi,BDI,1996,869033856.317093 +Burundi,BDI,1997,972896267.915425 +Burundi,BDI,1998,893770806.077641 +Burundi,BDI,1999,808077223.365746 +Burundi,BDI,2000,870486065.883137 +Burundi,BDI,2001,876794723.068586 +Burundi,BDI,2002,825394490.159111 +Burundi,BDI,2003,784654423.620476 +Burundi,BDI,2004,915257323.3961 +Burundi,BDI,2005,1117257279.46188 +Burundi,BDI,2006,1273180597.02711 +Burundi,BDI,2007,1356078278.18821 +Burundi,BDI,2008,1611634331.64869 +Burundi,BDI,2009,1739781488.7457 +Burundi,BDI,2010,2026864469.36388 +Burundi,BDI,2011,2355652125.85184 +Burundi,BDI,2012,2472384906.99794 +Burundi,BDI,2013,2714505634.52629 +Burundi,BDI,2014,3093647226.8107 +Burundi,BDI,2015,3097324739.8493 +Burundi,BDI,2016,3007029030.39976 +Cabo Verde,CPV,1980,142246875.536716 +Cabo Verde,CPV,1981,139468114.599741 +Cabo Verde,CPV,1982,140630758.594899 +Cabo Verde,CPV,1983,138476239.366792 +Cabo Verde,CPV,1984,132019065.033419 +Cabo Verde,CPV,1985,137728155.212661 +Cabo Verde,CPV,1986,190651207.999511 +Cabo Verde,CPV,1987,235253171.841062 +Cabo Verde,CPV,1988,264308140.285149 +Cabo Verde,CPV,1989,267448513.108168 +Cabo Verde,CPV,1990,306891107.262039 +Cabo Verde,CPV,1991,319827058.592875 +Cabo Verde,CPV,1992,357160985.327413 +Cabo Verde,CPV,1993,490417389.682569 +Cabo Verde,CPV,1994,406580652.330537 +Cabo Verde,CPV,1995,487148993.533109 +Cabo Verde,CPV,1996,501979069.274683 +Cabo Verde,CPV,1997,490608657.924976 +Cabo Verde,CPV,1998,521910560.524868 +Cabo Verde,CPV,1999,592416703.058878 +Cabo Verde,CPV,2000,539227277.626411 +Cabo Verde,CPV,2001,563024383.296626 +Cabo Verde,CPV,2002,620974660.230303 +Cabo Verde,CPV,2003,813963830.179217 +Cabo Verde,CPV,2004,924318490.7598 +Cabo Verde,CPV,2005,971977088.156914 +Cabo Verde,CPV,2006,1107891063.43863 +Cabo Verde,CPV,2007,1513934037.24782 +Cabo Verde,CPV,2008,1789333748.6799 +Cabo Verde,CPV,2009,1711817181.52969 +Cabo Verde,CPV,2010,1664310769.55229 +Cabo Verde,CPV,2011,1864824080.69256 +Cabo Verde,CPV,2012,1751888561.72747 +Cabo Verde,CPV,2013,1850951315.45564 +Cabo Verde,CPV,2014,1858121723.24993 +Cabo Verde,CPV,2015,1574288667.69981 +Cabo Verde,CPV,2016,1617467435.77007 +Cambodia,KHM,1960,637142865.714286 +Cambodia,KHM,1961,642857134.285714 +Cambodia,KHM,1962,660000008.571429 +Cambodia,KHM,1963,728571437.142857 +Cambodia,KHM,1964,782857128.571429 +Cambodia,KHM,1965,868571428.571429 +Cambodia,KHM,1966,914285714.285714 +Cambodia,KHM,1967,962857134.285714 +Cambodia,KHM,1968,1065714248.57143 +Cambodia,KHM,1969,978873232.394366 +Cambodia,KHM,1970,718401157.724163 +Cambodia,KHM,1971,969911421.394181 +Cambodia,KHM,1972,505549441.375077 +Cambodia,KHM,1973,702899155.982033 +Cambodia,KHM,1974,588443893.689773 +Cambodia,KHM,1993,2533727592.02872 +Cambodia,KHM,1994,2791435272.25765 +Cambodia,KHM,1995,3441205692.90388 +Cambodia,KHM,1996,3506695719.5716 +Cambodia,KHM,1997,3443413388.70675 +Cambodia,KHM,1998,3120425502.56968 +Cambodia,KHM,1999,3517242477.23368 +Cambodia,KHM,2000,3654031716.27649 +Cambodia,KHM,2001,3984000517.01899 +Cambodia,KHM,2002,4284028482.54971 +Cambodia,KHM,2003,4658246918.26014 +Cambodia,KHM,2004,5337833248.02828 +Cambodia,KHM,2005,6293046161.82646 +Cambodia,KHM,2006,7274595706.66355 +Cambodia,KHM,2007,8639235842.17756 +Cambodia,KHM,2008,10351914093.1626 +Cambodia,KHM,2009,10401851850.6062 +Cambodia,KHM,2010,11242275198.9706 +Cambodia,KHM,2011,12829541141.0175 +Cambodia,KHM,2012,14038383450.1945 +Cambodia,KHM,2013,15449630418.5461 +Cambodia,KHM,2014,16777820332.6952 +Cambodia,KHM,2015,18049954289.4301 +Cambodia,KHM,2016,20016747754.0153 +Cameroon,CMR,1960,618740988.011405 +Cameroon,CMR,1961,657597382.759152 +Cameroon,CMR,1962,699373701.217138 +Cameroon,CMR,1963,723624365.288138 +Cameroon,CMR,1964,782384527.813649 +Cameroon,CMR,1965,814139855.756458 +Cameroon,CMR,1966,853268771.097081 +Cameroon,CMR,1967,934079050.346173 +Cameroon,CMR,1968,1053077155.17925 +Cameroon,CMR,1969,1152418514.82616 +Cameroon,CMR,1970,1160002260.94729 +Cameroon,CMR,1971,1233991075.11626 +Cameroon,CMR,1972,1430951331.85034 +Cameroon,CMR,1973,1758727395.18703 +Cameroon,CMR,1974,2255496995.49378 +Cameroon,CMR,1975,2752771043.88609 +Cameroon,CMR,1976,3076592431.27204 +Cameroon,CMR,1977,3366368664.59706 +Cameroon,CMR,1978,4409920643.6422 +Cameroon,CMR,1979,5811444660.65752 +Cameroon,CMR,1980,6740756568.91566 +Cameroon,CMR,1981,7636345827.34308 +Cameroon,CMR,1982,7322914570.15588 +Cameroon,CMR,1983,7381854746.91629 +Cameroon,CMR,1984,7801858825.18416 +Cameroon,CMR,1985,8148223603.58399 +Cameroon,CMR,1986,10621158532.5193 +Cameroon,CMR,1987,12302471429.4318 +Cameroon,CMR,1988,12493286761.7341 +Cameroon,CMR,1989,11140055364.1502 +Cameroon,CMR,1990,11151578050.7356 +Cameroon,CMR,1991,12434370004.9586 +Cameroon,CMR,1992,11396310990.2197 +Cameroon,CMR,1993,13532137227.585 +Cameroon,CMR,1994,9220470913.32766 +Cameroon,CMR,1995,8733231184.34755 +Cameroon,CMR,1996,9732328115.73674 +Cameroon,CMR,1997,9840553235.89425 +Cameroon,CMR,1998,9629649416.89037 +Cameroon,CMR,1999,10486451144.4061 +Cameroon,CMR,2000,9287367235.25769 +Cameroon,CMR,2001,9633109349.64535 +Cameroon,CMR,2002,10879778384.1965 +Cameroon,CMR,2003,13621738837.1961 +Cameroon,CMR,2004,15775357014.6254 +Cameroon,CMR,2005,16587858856.6778 +Cameroon,CMR,2006,17953066721.0949 +Cameroon,CMR,2007,20431780377.8605 +Cameroon,CMR,2008,23322254113.5623 +Cameroon,CMR,2009,23381142146.6485 +Cameroon,CMR,2010,23622483983.7101 +Cameroon,CMR,2011,26587311527.5711 +Cameroon,CMR,2012,26472056037.7696 +Cameroon,CMR,2013,29567504655.4935 +Cameroon,CMR,2014,32050817632.9602 +Cameroon,CMR,2015,28415950981.4447 +Cameroon,CMR,2016,24204448566.6105 +Canada,CAN,1960,41093453544.9096 +Canada,CAN,1961,40767969453.696 +Canada,CAN,1962,41978852041.4426 +Canada,CAN,1963,44657169109.224 +Canada,CAN,1964,48882938810.2204 +Canada,CAN,1965,53909570342.169 +Canada,CAN,1966,60358632035.1532 +Canada,CAN,1967,64768831262.1761 +Canada,CAN,1968,70759031841.7237 +Canada,CAN,1969,77887510241.7083 +Canada,CAN,1970,87896095224.4234 +Canada,CAN,1971,99271961477.5203 +Canada,CAN,1972,113082820992.019 +Canada,CAN,1973,131321859214.079 +Canada,CAN,1974,160408697648.262 +Canada,CAN,1975,173834029787.652 +Canada,CAN,1976,206575564401.623 +Canada,CAN,1977,211612156934.65 +Canada,CAN,1978,218632867449.812 +Canada,CAN,1979,243072102185.419 +Canada,CAN,1980,273853826377.01 +Canada,CAN,1981,306214863624.99 +Canada,CAN,1982,313506525087.136 +Canada,CAN,1983,340547711781.889 +Canada,CAN,1984,355372558103.621 +Canada,CAN,1985,364756499450.751 +Canada,CAN,1986,377437927311.983 +Canada,CAN,1987,431316742081.448 +Canada,CAN,1988,507354351182.254 +Canada,CAN,1989,565055743243.243 +Canada,CAN,1990,593929550908.468 +Canada,CAN,1991,610328183643.188 +Canada,CAN,1992,592387689252.916 +Canada,CAN,1993,577170761956.438 +Canada,CAN,1994,578139279437.61 +Canada,CAN,1995,604031623433.401 +Canada,CAN,1996,628546387972.131 +Canada,CAN,1997,652825364726.275 +Canada,CAN,1998,631813279406.808 +Canada,CAN,1999,676082654640.91 +Canada,CAN,2000,742293448252.643 +Canada,CAN,2001,736379777892.562 +Canada,CAN,2002,757950678646.53 +Canada,CAN,2003,892380986367.854 +Canada,CAN,2004,1023196003074.56 +Canada,CAN,2005,1169357979864.66 +Canada,CAN,2006,1315415197461.21 +Canada,CAN,2007,1464977190205.75 +Canada,CAN,2008,1549131208997.19 +Canada,CAN,2009,1371153004986.44 +Canada,CAN,2010,1613464422811.13 +Canada,CAN,2011,1788647906047.76 +Canada,CAN,2012,1824288757447.57 +Canada,CAN,2013,1842628005830.18 +Canada,CAN,2014,1792883225804.38 +Canada,CAN,2015,1552807652015.37 +Canada,CAN,2016,1529760492201.35 +Cayman Islands,CYM,1996,1012444074.07495 +Cayman Islands,CYM,2006,3207032512.94205 +Central African Republic,CAF,1960,112155598.949571 +Central African Republic,CAF,1961,123134584.467673 +Central African Republic,CAF,1962,124482748.937917 +Central African Republic,CAF,1963,129379097.888958 +Central African Republic,CAF,1964,142025069.461676 +Central African Republic,CAF,1965,150574816.300764 +Central African Republic,CAF,1966,157930041.875883 +Central African Republic,CAF,1967,163820538.867947 +Central African Republic,CAF,1968,191767436.956884 +Central African Republic,CAF,1969,188039191.323608 +Central African Republic,CAF,1970,189106554.521277 +Central African Republic,CAF,1971,201450768.367553 +Central African Republic,CAF,1972,230317908.038643 +Central African Republic,CAF,1973,271183061.359635 +Central African Republic,CAF,1974,281398668.160613 +Central African Republic,CAF,1975,378660016.265936 +Central African Republic,CAF,1976,451152449.984411 +Central African Republic,CAF,1977,507298120.68315 +Central African Republic,CAF,1978,610578523.761178 +Central African Republic,CAF,1979,700764892.704831 +Central African Republic,CAF,1980,797048028.773247 +Central African Republic,CAF,1981,694803502.722356 +Central African Republic,CAF,1982,748312283.726758 +Central African Republic,CAF,1983,658679394.907969 +Central African Republic,CAF,1984,637820620.670195 +Central African Republic,CAF,1985,864849765.059665 +Central African Republic,CAF,1986,1122265026.38274 +Central African Republic,CAF,1987,1200991825.95398 +Central African Republic,CAF,1988,1264899368.20165 +Central African Republic,CAF,1989,1233930277.04922 +Central African Republic,CAF,1990,1440711395.67069 +Central African Republic,CAF,1991,1377375030.52921 +Central African Republic,CAF,1992,1411917558.45855 +Central African Republic,CAF,1993,1278781166.72188 +Central African Republic,CAF,1994,851174350.649409 +Central African Republic,CAF,1995,1115389731.79119 +Central African Republic,CAF,1996,1007791186.20106 +Central African Republic,CAF,1997,937741468.029676 +Central African Republic,CAF,1998,967338348.658314 +Central African Republic,CAF,1999,999477510.686632 +Central African Republic,CAF,2000,914500299.097034 +Central African Republic,CAF,2001,931833302.752857 +Central African Republic,CAF,2002,991387870.12463 +Central African Republic,CAF,2003,1139754799.16304 +Central African Republic,CAF,2004,1270080250.65268 +Central African Republic,CAF,2005,1350301057.06866 +Central African Republic,CAF,2006,1460562038.37097 +Central African Republic,CAF,2007,1698125617.92304 +Central African Republic,CAF,2008,1985239276.62611 +Central African Republic,CAF,2009,1981728140.77833 +Central African Republic,CAF,2010,1986014845.63184 +Central African Republic,CAF,2011,2212699746.81377 +Central African Republic,CAF,2012,2184183758.31567 +Central African Republic,CAF,2013,1518565219.01061 +Central African Republic,CAF,2014,1702898939.55483 +Central African Republic,CAF,2015,1583776759.97697 +Central African Republic,CAF,2016,1756124677.19671 +Chad,TCD,1960,313582727.638108 +Chad,TCD,1961,333975336.626596 +Chad,TCD,1962,357635713.876856 +Chad,TCD,1963,371767002.656036 +Chad,TCD,1964,392247517.601949 +Chad,TCD,1965,416926302.963497 +Chad,TCD,1966,432794922.459759 +Chad,TCD,1967,449826322.995107 +Chad,TCD,1968,453980096.654412 +Chad,TCD,1969,471635620.924368 +Chad,TCD,1970,469266736.605101 +Chad,TCD,1971,501866730.722503 +Chad,TCD,1972,585427545.723598 +Chad,TCD,1973,647199482.827982 +Chad,TCD,1974,652532796.06664 +Chad,TCD,1975,864602103.303074 +Chad,TCD,1976,866044961.048354 +Chad,TCD,1977,935360466.351488 +Chad,TCD,1978,1113920122.61232 +Chad,TCD,1979,1004316495.11176 +Chad,TCD,1980,1033002401.82543 +Chad,TCD,1981,876937559.724954 +Chad,TCD,1982,834369860.427317 +Chad,TCD,1983,832415805.956265 +Chad,TCD,1984,919103735.322906 +Chad,TCD,1985,1033069709.99506 +Chad,TCD,1986,1067828247.23579 +Chad,TCD,1987,1163426850.65024 +Chad,TCD,1988,1482597298.88729 +Chad,TCD,1989,1433686309.83641 +Chad,TCD,1990,1738605558.05436 +Chad,TCD,1991,1877138041.64308 +Chad,TCD,1992,1881847676.80752 +Chad,TCD,1993,1463251055.40068 +Chad,TCD,1994,1179837954.72193 +Chad,TCD,1995,1445919969.89272 +Chad,TCD,1996,1607345450.04578 +Chad,TCD,1997,1544689502.82472 +Chad,TCD,1998,1744794457.276 +Chad,TCD,1999,1534673583.2487 +Chad,TCD,2000,1385058161.76746 +Chad,TCD,2001,1709347793.32873 +Chad,TCD,2002,1987622279.11463 +Chad,TCD,2003,2736666515.8294 +Chad,TCD,2004,4414929219.99649 +Chad,TCD,2005,6646663561.2656 +Chad,TCD,2006,7422102655.98832 +Chad,TCD,2007,8638711442.7705 +Chad,TCD,2008,10351932604.4154 +Chad,TCD,2009,9253484108.49701 +Chad,TCD,2010,10657705536.4978 +Chad,TCD,2011,12156380425.0825 +Chad,TCD,2012,12368071038.7362 +Chad,TCD,2013,12949854262.8127 +Chad,TCD,2014,13922223233.5184 +Chad,TCD,2015,10888798113.7866 +Chad,TCD,2016,9600761473.78738 +Channel Islands,CHI,1998,5945677376.61477 +Channel Islands,CHI,1999,6262740656.85164 +Channel Islands,CHI,2000,6439703434.71024 +Channel Islands,CHI,2001,6232906290.4851 +Channel Islands,CHI,2002,6663669064.7482 +Channel Islands,CHI,2003,7332244897.95918 +Channel Islands,CHI,2004,8553643354.08275 +Channel Islands,CHI,2005,8827272727.27273 +Channel Islands,CHI,2006,9676172953.08188 +Channel Islands,CHI,2007,11514605842.3369 +Chile,CHL,1960,4109993820.85867 +Chile,CHL,1961,4609700367.43769 +Chile,CHL,1962,5416266783.44725 +Chile,CHL,1963,5668205957.19525 +Chile,CHL,1964,5982343871.07657 +Chile,CHL,1965,6026583778.99913 +Chile,CHL,1966,7072636623.49356 +Chile,CHL,1967,7013192291.50469 +Chile,CHL,1968,7167084577.79975 +Chile,CHL,1969,8377098357.87508 +Chile,CHL,1970,9126311883.24115 +Chile,CHL,1971,10884112885.7799 +Chile,CHL,1972,11853818445.9512 +Chile,CHL,1973,16836261234.4254 +Chile,CHL,1974,16210404218.7163 +Chile,CHL,1975,7622217357.00739 +Chile,CHL,1976,10341925245.9606 +Chile,CHL,1977,13962893421.8332 +Chile,CHL,1978,15989933709.6354 +Chile,CHL,1979,21803696986.4362 +Chile,CHL,1980,29036709873.0313 +Chile,CHL,1981,34509878043.8003 +Chile,CHL,1982,25325893204.9564 +Chile,CHL,1983,20355959236.7512 +Chile,CHL,1984,19622527479.8718 +Chile,CHL,1985,17702885393.2705 +Chile,CHL,1986,18891048818.9936 +Chile,CHL,1987,22255407684.5828 +Chile,CHL,1988,26040229792.9356 +Chile,CHL,1989,29885685143.0648 +Chile,CHL,1990,33113887817.8869 +Chile,CHL,1991,37834793730.368 +Chile,CHL,1992,45964327558.9522 +Chile,CHL,1993,49297773130.1452 +Chile,CHL,1994,57008425295.862 +Chile,CHL,1995,73447063319.1781 +Chile,CHL,1996,78039572221.6062 +Chile,CHL,1997,84952360922.4958 +Chile,CHL,1998,81577430181.4606 +Chile,CHL,1999,75173794497.0496 +Chile,CHL,2000,77860932151.9303 +Chile,CHL,2001,70980110277.4532 +Chile,CHL,2002,69737148847.9119 +Chile,CHL,2003,75643733356.097 +Chile,CHL,2004,99210528495.6404 +Chile,CHL,2005,122964812046.14 +Chile,CHL,2006,154788024805.866 +Chile,CHL,2007,173605979255.357 +Chile,CHL,2008,179638483957.885 +Chile,CHL,2009,172389500030.292 +Chile,CHL,2010,218537565496.634 +Chile,CHL,2011,252251992029.518 +Chile,CHL,2012,267122318194.715 +Chile,CHL,2013,278384345259.391 +Chile,CHL,2014,260990291671.248 +Chile,CHL,2015,242517910999.453 +Chile,CHL,2016,247027899421.318 +China,CHN,1960,59716467625.3148 +China,CHN,1961,50056868957.6732 +China,CHN,1962,47209359005.6056 +China,CHN,1963,50706799902.5103 +China,CHN,1964,59708343488.5043 +China,CHN,1965,70436266146.7219 +China,CHN,1966,76720285969.6157 +China,CHN,1967,72881631326.6715 +China,CHN,1968,70846535055.6503 +China,CHN,1969,79705906247.4612 +China,CHN,1970,92602973434.0726 +China,CHN,1971,99800958648.1436 +China,CHN,1972,113687586299.051 +China,CHN,1973,138544284708.957 +China,CHN,1974,144182133387.722 +China,CHN,1975,163431551779.761 +China,CHN,1976,153940455341.506 +China,CHN,1977,174938098826.569 +China,CHN,1978,149540650406.504 +China,CHN,1979,178282608695.652 +China,CHN,1980,191150000000 +China,CHN,1981,195865079365.079 +China,CHN,1982,205091603053.435 +China,CHN,1983,230685823754.789 +China,CHN,1984,259946428571.429 +China,CHN,1985,309486394557.823 +China,CHN,1986,300759420289.855 +China,CHN,1987,272973094170.404 +China,CHN,1988,312353909465.021 +China,CHN,1989,347767206477.733 +China,CHN,1990,360858508604.206 +China,CHN,1991,383372822299.652 +China,CHN,1992,426915227629.513 +China,CHN,1993,444730903968.185 +China,CHN,1994,564325246266.838 +China,CHN,1995,734548001963.907 +China,CHN,1996,863746361646.34 +China,CHN,1997,961603416246.472 +China,CHN,1998,1029043011921.59 +China,CHN,1999,1093997559885.48 +China,CHN,2000,1211346395438.73 +China,CHN,2001,1339395440432.04 +China,CHN,2002,1470549716080.71 +China,CHN,2003,1660287543796.06 +China,CHN,2004,1955347477285.91 +China,CHN,2005,2285965854313.36 +China,CHN,2006,2752132089196.58 +China,CHN,2007,3552182714426.55 +China,CHN,2008,4598205419718.8 +China,CHN,2009,5109954035775.98 +China,CHN,2010,6100620356557.32 +China,CHN,2011,7572554360442.62 +China,CHN,2012,8560546868811.69 +China,CHN,2013,9607224248684.59 +China,CHN,2014,10482371325324.7 +China,CHN,2015,11064664793255.7 +China,CHN,2016,11199145157649.2 +Colombia,COL,1960,4040948153.73022 +Colombia,COL,1961,4552914000 +Colombia,COL,1962,4968603735.58222 +Colombia,COL,1963,4838841455.55556 +Colombia,COL,1964,5992169466.66667 +Colombia,COL,1965,5790247619.04762 +Colombia,COL,1966,5452762962.96296 +Colombia,COL,1967,5727195020.23203 +Colombia,COL,1968,5918455409.8099 +Colombia,COL,1969,6405427873.70755 +Colombia,COL,1970,7198360460.19887 +Colombia,COL,1971,7820380970.53674 +Colombia,COL,1972,8671358732.68486 +Colombia,COL,1973,10315760000.3394 +Colombia,COL,1974,12370029583.6419 +Colombia,COL,1975,13098633901.8673 +Colombia,COL,1976,15341403660.4698 +Colombia,COL,1977,19470960619.1297 +Colombia,COL,1978,23263511958.0509 +Colombia,COL,1979,27940411250.2732 +Colombia,COL,1980,33400735644.0481 +Colombia,COL,1981,36388366869.0309 +Colombia,COL,1982,38968039721.748 +Colombia,COL,1983,38729822781.5997 +Colombia,COL,1984,38253120737.9671 +Colombia,COL,1985,34894411351.983 +Colombia,COL,1986,34942489683.9712 +Colombia,COL,1987,36373307085.0887 +Colombia,COL,1988,39212550050.4223 +Colombia,COL,1989,39540080200.3938 +Colombia,COL,1990,40274204595.2296 +Colombia,COL,1991,41239551378.2482 +Colombia,COL,1992,49279585355.0948 +Colombia,COL,1993,55802538219.0264 +Colombia,COL,1994,81703500846.0364 +Colombia,COL,1995,92507279383.0387 +Colombia,COL,1996,97160109277.8087 +Colombia,COL,1997,106659508271.255 +Colombia,COL,1998,98443739941.1664 +Colombia,COL,1999,86186158684.7685 +Colombia,COL,2000,99886577330.7271 +Colombia,COL,2001,98203546156.3102 +Colombia,COL,2002,97933391976.083 +Colombia,COL,2003,94684584162.773 +Colombia,COL,2004,117074863821.85 +Colombia,COL,2005,146566264837.014 +Colombia,COL,2006,162590146096.414 +Colombia,COL,2007,207416494642.379 +Colombia,COL,2008,243982437870.84 +Colombia,COL,2009,233821670544.258 +Colombia,COL,2010,287018184637.529 +Colombia,COL,2011,335415156702.186 +Colombia,COL,2012,369659700375.52 +Colombia,COL,2013,380191881860.372 +Colombia,COL,2014,378195716714.266 +Colombia,COL,2015,291519591532.951 +Colombia,COL,2016,282462548889.26 +Comoros,COM,1980,123505640.914474 +Comoros,COM,1981,114271897.268272 +Comoros,COM,1982,107089552.302395 +Comoros,COM,1983,111519676.021905 +Comoros,COM,1984,107489822.704044 +Comoros,COM,1985,114490697.57503 +Comoros,COM,1986,162487763.894624 +Comoros,COM,1987,196433684.042405 +Comoros,COM,1988,207476554.806734 +Comoros,COM,1989,198733185.875107 +Comoros,COM,1990,250030760.754786 +Comoros,COM,1991,246823428.906664 +Comoros,COM,1992,266191040.373328 +Comoros,COM,1993,263568114.445462 +Comoros,COM,1994,185761822.560488 +Comoros,COM,1995,231896229.562629 +Comoros,COM,1996,230495751.446593 +Comoros,COM,1997,212099634.697751 +Comoros,COM,1998,215394066.068976 +Comoros,COM,1999,222580453.753844 +Comoros,COM,2000,203846427.738737 +Comoros,COM,2001,220093812.206791 +Comoros,COM,2002,246737679.472106 +Comoros,COM,2003,317562269.371106 +Comoros,COM,2004,368143118.68996 +Comoros,COM,2005,380372892.606774 +Comoros,COM,2006,406111873.539847 +Comoros,COM,2007,462453582.873627 +Comoros,COM,2008,523134896.968654 +Comoros,COM,2009,524157261.014644 +Comoros,COM,2010,530493353.218937 +Comoros,COM,2011,586281766.75997 +Comoros,COM,2012,570865941.229395 +Comoros,COM,2013,618663921.86116 +Comoros,COM,2014,647720707.076427 +Comoros,COM,2015,565689764.63263 +Comoros,COM,2016,616654490.471188 +"Congo, Dem. Rep.",COD,1960,3359404132.31797 +"Congo, Dem. Rep.",COD,1961,3086746936.39789 +"Congo, Dem. Rep.",COD,1962,3779841409.55267 +"Congo, Dem. Rep.",COD,1963,6213185773.92265 +"Congo, Dem. Rep.",COD,1964,2881545277.14307 +"Congo, Dem. Rep.",COD,1965,4043901724.13762 +"Congo, Dem. Rep.",COD,1966,4532660145.32842 +"Congo, Dem. Rep.",COD,1967,3384063359.82333 +"Congo, Dem. Rep.",COD,1968,3909780525.37375 +"Congo, Dem. Rep.",COD,1969,5032434970.84174 +"Congo, Dem. Rep.",COD,1970,4877684933.12505 +"Congo, Dem. Rep.",COD,1971,5594770351.56981 +"Congo, Dem. Rep.",COD,1972,6173712809.28569 +"Congo, Dem. Rep.",COD,1973,7870239463.58461 +"Congo, Dem. Rep.",COD,1974,9596960174.34365 +"Congo, Dem. Rep.",COD,1975,10237343153.4311 +"Congo, Dem. Rep.",COD,1976,9648583220.47256 +"Congo, Dem. Rep.",COD,1977,12344424775.9239 +"Congo, Dem. Rep.",COD,1978,15372607995.4061 +"Congo, Dem. Rep.",COD,1979,15068422242.0571 +"Congo, Dem. Rep.",COD,1980,14394927492.9647 +"Congo, Dem. Rep.",COD,1981,12537821039.8252 +"Congo, Dem. Rep.",COD,1982,13651667370.5466 +"Congo, Dem. Rep.",COD,1983,11006712649.2175 +"Congo, Dem. Rep.",COD,1984,7857729192.85629 +"Congo, Dem. Rep.",COD,1985,7195042615.84176 +"Congo, Dem. Rep.",COD,1986,8095367168.16178 +"Congo, Dem. Rep.",COD,1987,7661625472.51189 +"Congo, Dem. Rep.",COD,1988,8861299976.68858 +"Congo, Dem. Rep.",COD,1989,9021862775.25443 +"Congo, Dem. Rep.",COD,1990,9349764580.35198 +"Congo, Dem. Rep.",COD,1991,9087965281.52807 +"Congo, Dem. Rep.",COD,1992,8206227134.00857 +"Congo, Dem. Rep.",COD,1993,10707792340.0276 +"Congo, Dem. Rep.",COD,1994,5820383305.54668 +"Congo, Dem. Rep.",COD,1995,5643439262.21735 +"Congo, Dem. Rep.",COD,1996,5771454939.62404 +"Congo, Dem. Rep.",COD,1997,6090840548.18784 +"Congo, Dem. Rep.",COD,1998,6215591269.89747 +"Congo, Dem. Rep.",COD,1999,4711259427.27273 +"Congo, Dem. Rep.",COD,2000,19088046305.7971 +"Congo, Dem. Rep.",COD,2001,7438189100.33333 +"Congo, Dem. Rep.",COD,2002,8728038525.14034 +"Congo, Dem. Rep.",COD,2003,8937567059.87754 +"Congo, Dem. Rep.",COD,2004,10297483481.223 +"Congo, Dem. Rep.",COD,2005,11964484667.9102 +"Congo, Dem. Rep.",COD,2006,14296507096.4135 +"Congo, Dem. Rep.",COD,2007,16364029327.3457 +"Congo, Dem. Rep.",COD,2008,19206060270.2521 +"Congo, Dem. Rep.",COD,2009,18262773820.8055 +"Congo, Dem. Rep.",COD,2010,20523285374.187 +"Congo, Dem. Rep.",COD,2011,23849009737.6669 +"Congo, Dem. Rep.",COD,2012,27463220380.0054 +"Congo, Dem. Rep.",COD,2013,30014813755.772 +"Congo, Dem. Rep.",COD,2014,34028119332.6087 +"Congo, Dem. Rep.",COD,2015,36188521106.9294 +"Congo, Dem. Rep.",COD,2016,34998638634.1 +"Congo, Rep.",COG,1960,131731862.568997 +"Congo, Rep.",COG,1961,151675739.160627 +"Congo, Rep.",COG,1962,166521239.863281 +"Congo, Rep.",COG,1963,172233430.871502 +"Congo, Rep.",COG,1964,185693724.845331 +"Congo, Rep.",COG,1965,198318063.860835 +"Congo, Rep.",COG,1966,220613582.369827 +"Congo, Rep.",COG,1967,237397428.336429 +"Congo, Rep.",COG,1968,251247458.012189 +"Congo, Rep.",COG,1969,265040036.059116 +"Congo, Rep.",COG,1970,274960699.85855 +"Congo, Rep.",COG,1971,322128019.323561 +"Congo, Rep.",COG,1972,410669262.897929 +"Congo, Rep.",COG,1973,541973362.480998 +"Congo, Rep.",COG,1974,585364635.354748 +"Congo, Rep.",COG,1975,767102679.018622 +"Congo, Rep.",COG,1976,754549600.548182 +"Congo, Rep.",COG,1977,765224030.636552 +"Congo, Rep.",COG,1978,878771771.29105 +"Congo, Rep.",COG,1979,1198749665.95066 +"Congo, Rep.",COG,1980,1705796849.54655 +"Congo, Rep.",COG,1981,1993512325.92286 +"Congo, Rep.",COG,1982,2160640566.5396 +"Congo, Rep.",COG,1983,2097274289.61512 +"Congo, Rep.",COG,1984,2193581366.40722 +"Congo, Rep.",COG,1985,2160872541.41887 +"Congo, Rep.",COG,1986,1849268214.68184 +"Congo, Rep.",COG,1987,2297753649.2798 +"Congo, Rep.",COG,1988,2212536313.33492 +"Congo, Rep.",COG,1989,2389593021.94866 +"Congo, Rep.",COG,1990,2798746050.58236 +"Congo, Rep.",COG,1991,2724853507.63856 +"Congo, Rep.",COG,1992,2933222705.80382 +"Congo, Rep.",COG,1993,1918970177.74925 +"Congo, Rep.",COG,1994,1769365438.87155 +"Congo, Rep.",COG,1995,2116003868.17928 +"Congo, Rep.",COG,1996,2540697537.71673 +"Congo, Rep.",COG,1997,2322719101.29807 +"Congo, Rep.",COG,1998,1949481380.64044 +"Congo, Rep.",COG,1999,2353909441.71514 +"Congo, Rep.",COG,2000,3219910666.03357 +"Congo, Rep.",COG,2001,2794259783.08097 +"Congo, Rep.",COG,2002,3019993738.77492 +"Congo, Rep.",COG,2003,3495868808.0512 +"Congo, Rep.",COG,2004,4648628921.36969 +"Congo, Rep.",COG,2005,6087003176.11624 +"Congo, Rep.",COG,2006,7731261310.93322 +"Congo, Rep.",COG,2007,8394688284.06224 +"Congo, Rep.",COG,2008,11859014004.0772 +"Congo, Rep.",COG,2009,9593536531.23778 +"Congo, Rep.",COG,2010,12007880590.4575 +"Congo, Rep.",COG,2011,14425607224.168 +"Congo, Rep.",COG,2012,13677930123.5919 +"Congo, Rep.",COG,2013,14085852120.4761 +"Congo, Rep.",COG,2014,14177437627.2969 +"Congo, Rep.",COG,2015,8553154505.83693 +"Congo, Rep.",COG,2016,7833509443.39395 +Costa Rica,CRI,1960,507513829.994855 +Costa Rica,CRI,1961,490325181.614275 +Costa Rica,CRI,1962,479180824.348506 +Costa Rica,CRI,1963,511902136.809973 +Costa Rica,CRI,1964,542578367.242598 +Costa Rica,CRI,1965,592981162.264151 +Costa Rica,CRI,1966,647305630.188679 +Costa Rica,CRI,1967,699456618.867925 +Costa Rica,CRI,1968,773841494.339623 +Costa Rica,CRI,1969,853630203.773585 +Costa Rica,CRI,1970,984830158.490566 +Costa Rica,CRI,1971,1077152902.29104 +Costa Rica,CRI,1972,1238251695.55388 +Costa Rica,CRI,1973,1528916185.23199 +Costa Rica,CRI,1974,1666544754.09836 +Costa Rica,CRI,1975,1960863465.5776 +Costa Rica,CRI,1976,2412555425.90432 +Costa Rica,CRI,1977,3072427012.83547 +Costa Rica,CRI,1978,3523208809.80163 +Costa Rica,CRI,1979,4035519323.22054 +Costa Rica,CRI,1980,4831447001.16686 +Costa Rica,CRI,1981,2623807074.2948 +Costa Rica,CRI,1982,2606621255.01581 +Costa Rica,CRI,1983,3976453966.73983 +Costa Rica,CRI,1984,4593908718.76172 +Costa Rica,CRI,1985,4796628461.38614 +Costa Rica,CRI,1986,5477895474.91039 +Costa Rica,CRI,1987,5841132961.60586 +Costa Rica,CRI,1988,6063759370.62937 +Costa Rica,CRI,1989,6866402028.10997 +Costa Rica,CRI,1990,7403457319.20472 +Costa Rica,CRI,1991,7168999428.24471 +Costa Rica,CRI,1992,8528593084.48749 +Costa Rica,CRI,1993,9537297507.16915 +Costa Rica,CRI,1994,10432619390.3609 +Costa Rica,CRI,1995,11513472693.8707 +Costa Rica,CRI,1996,11618286553.3677 +Costa Rica,CRI,1997,12552071367.1539 +Costa Rica,CRI,1998,13617405420.1174 +Costa Rica,CRI,1999,14195623424.811 +Costa Rica,CRI,2000,14949514585.1585 +Costa Rica,CRI,2001,15913363335.0564 +Costa Rica,CRI,2002,16504795453.2822 +Costa Rica,CRI,2003,17195867540.353 +Costa Rica,CRI,2004,18529767934.4743 +Costa Rica,CRI,2005,19952156474.8454 +Costa Rica,CRI,2006,22600431878.0024 +Costa Rica,CRI,2007,26743874286.8514 +Costa Rica,CRI,2008,30612932802.8991 +Costa Rica,CRI,2009,30562361123.0307 +Costa Rica,CRI,2010,37268635287.0856 +Costa Rica,CRI,2011,42262697840.385 +Costa Rica,CRI,2012,46473128285.5589 +Costa Rica,CRI,2013,49745088111.6953 +Costa Rica,CRI,2014,50656002895.8763 +Costa Rica,CRI,2015,54840103850.265 +Costa Rica,CRI,2016,57435507212.256 +Cote d'Ivoire,CIV,1960,546203561.571989 +Cote d'Ivoire,CIV,1961,618245639.221382 +Cote d'Ivoire,CIV,1962,645284344.684118 +Cote d'Ivoire,CIV,1963,761047045.830402 +Cote d'Ivoire,CIV,1964,921063266.445521 +Cote d'Ivoire,CIV,1965,919771356.426097 +Cote d'Ivoire,CIV,1966,1024103034.29198 +Cote d'Ivoire,CIV,1967,1082922892.15202 +Cote d'Ivoire,CIV,1968,1281281245.67032 +Cote d'Ivoire,CIV,1969,1361360157.26999 +Cote d'Ivoire,CIV,1970,1455482990.24143 +Cote d'Ivoire,CIV,1971,1584128262.08933 +Cote d'Ivoire,CIV,1972,1849400599.77558 +Cote d'Ivoire,CIV,1973,2508421234.8557 +Cote d'Ivoire,CIV,1974,3070151901.06383 +Cote d'Ivoire,CIV,1975,3893839190.26806 +Cote d'Ivoire,CIV,1976,4662053707.7763 +Cote d'Ivoire,CIV,1977,6265067857.86534 +Cote d'Ivoire,CIV,1978,7900524897.8644 +Cote d'Ivoire,CIV,1979,9142935857.94766 +Cote d'Ivoire,CIV,1980,10175615441.8127 +Cote d'Ivoire,CIV,1981,8432588483.85263 +Cote d'Ivoire,CIV,1982,7567109766.61129 +Cote d'Ivoire,CIV,1983,6838185418.53642 +Cote d'Ivoire,CIV,1984,6841638714.5454 +Cote d'Ivoire,CIV,1985,6977650069.33578 +Cote d'Ivoire,CIV,1986,9158302205.36237 +Cote d'Ivoire,CIV,1987,10087653189.3287 +Cote d'Ivoire,CIV,1988,10255170459.986 +Cote d'Ivoire,CIV,1989,9757410614.0812 +Cote d'Ivoire,CIV,1990,10795850106.9547 +Cote d'Ivoire,CIV,1991,10492628915.4927 +Cote d'Ivoire,CIV,1992,11152971316.074 +Cote d'Ivoire,CIV,1993,11045759468.9412 +Cote d'Ivoire,CIV,1994,8313557450.25213 +Cote d'Ivoire,CIV,1995,11000146839.497 +Cote d'Ivoire,CIV,1996,12139234938.7863 +Cote d'Ivoire,CIV,1997,11722142706.1278 +Cote d'Ivoire,CIV,1998,12612033728.8572 +Cote d'Ivoire,CIV,1999,12376639822.9265 +Cote d'Ivoire,CIV,2000,10717022462.6859 +Cote d'Ivoire,CIV,2001,11192560827.2962 +Cote d'Ivoire,CIV,2002,12346919216.1359 +Cote d'Ivoire,CIV,2003,15306602560.2533 +Cote d'Ivoire,CIV,2004,16554441846.5192 +Cote d'Ivoire,CIV,2005,17084928927.4555 +Cote d'Ivoire,CIV,2006,17800887796.4987 +Cote d'Ivoire,CIV,2007,20343635319.6174 +Cote d'Ivoire,CIV,2008,24224903099.6283 +Cote d'Ivoire,CIV,2009,24277493862.0625 +Cote d'Ivoire,CIV,2010,24884505034.5564 +Cote d'Ivoire,CIV,2011,25381616734.0693 +Cote d'Ivoire,CIV,2012,27040562587.1771 +Cote d'Ivoire,CIV,2013,31273049200.243 +Cote d'Ivoire,CIV,2014,35372603446.2605 +Cote d'Ivoire,CIV,2015,32828516580.3451 +Cote d'Ivoire,CIV,2016,36164644633.0972 +Croatia,HRV,1995,22387561845.2244 +Croatia,HRV,1996,23678012697.3612 +Croatia,HRV,1997,23822087053.2091 +Croatia,HRV,1998,25432144406.2043 +Croatia,HRV,1999,23386945596.6928 +Croatia,HRV,2000,21774273832.1031 +Croatia,HRV,2001,23289671102.3197 +Croatia,HRV,2002,26878499206.0165 +Croatia,HRV,2003,34658113497.39 +Croatia,HRV,2004,41574530815.5047 +Croatia,HRV,2005,45416076680.8707 +Croatia,HRV,2006,50453577898.4886 +Croatia,HRV,2007,60093155532.7678 +Croatia,HRV,2008,70481451814.3118 +Croatia,HRV,2009,62703095750.5257 +Croatia,HRV,2010,59665427464.5326 +Croatia,HRV,2011,62236751773.0497 +Croatia,HRV,2012,56485301967.4205 +Croatia,HRV,2013,57769872074.883 +Croatia,HRV,2014,57080369367.8021 +Croatia,HRV,2015,48676334689.3545 +Croatia,HRV,2016,50425333970.0264 +Cuba,CUB,1970,5693005200 +Cuba,CUB,1971,6914658400 +Cuba,CUB,1972,8135150891.92025 +Cuba,CUB,1973,9987709650.18094 +Cuba,CUB,1974,11405957317.0732 +Cuba,CUB,1975,13027415243.9024 +Cuba,CUB,1976,13789579902.5579 +Cuba,CUB,1977,14206158674.6988 +Cuba,CUB,1978,17844705324.6753 +Cuba,CUB,1979,19584443287.6712 +Cuba,CUB,1980,19912889861.1111 +Cuba,CUB,1981,20150254096.3855 +Cuba,CUB,1982,20953510235.2941 +Cuba,CUB,1983,22204940512.2235 +Cuba,CUB,1984,24039383608.4235 +Cuba,CUB,1985,22920490774.102 +Cuba,CUB,1986,24226574634.0293 +Cuba,CUB,1987,25213935012.0819 +Cuba,CUB,1988,27458999472.2955 +Cuba,CUB,1989,27023468665.8977 +Cuba,CUB,1990,28645436569.1489 +Cuba,CUB,1991,24316556025.6585 +Cuba,CUB,1992,22085858243.2432 +Cuba,CUB,1993,22367254864.8649 +Cuba,CUB,1994,28448326756.7568 +Cuba,CUB,1995,30429803651.2192 +Cuba,CUB,1996,25017300000 +Cuba,CUB,1997,25366200000 +Cuba,CUB,1998,25736331247.1786 +Cuba,CUB,1999,28364615241.6894 +Cuba,CUB,2000,30565400000 +Cuba,CUB,2001,31682400000 +Cuba,CUB,2002,33590500000 +Cuba,CUB,2003,35901200000 +Cuba,CUB,2004,38203000000 +Cuba,CUB,2005,42643836074.8 +Cuba,CUB,2006,52742800000 +Cuba,CUB,2007,58603900000 +Cuba,CUB,2008,60806300000 +Cuba,CUB,2009,62080000000 +Cuba,CUB,2010,64328000000 +Cuba,CUB,2011,68990000000 +Cuba,CUB,2012,73141000000 +Cuba,CUB,2013,77148000000 +Cuba,CUB,2014,80656100000 +Cuba,CUB,2015,87132800000 +Cyprus,CYP,1975,489914760.682807 +Cyprus,CYP,1976,576090073.715036 +Cyprus,CYP,1977,734887973.975806 +Cyprus,CYP,1978,964026512.197839 +Cyprus,CYP,1979,1288715209.58084 +Cyprus,CYP,1980,2154311276.94859 +Cyprus,CYP,1981,2087496373.77964 +Cyprus,CYP,1982,2159242416.76942 +Cyprus,CYP,1983,2160364071.19021 +Cyprus,CYP,1984,2278248953.14058 +Cyprus,CYP,1985,2430411900.19194 +Cyprus,CYP,1986,3090734463.27684 +Cyprus,CYP,1987,3704813885.50548 +Cyprus,CYP,1988,4278792597.23965 +Cyprus,CYP,1989,4563482603.5503 +Cyprus,CYP,1990,5591130217.66965 +Cyprus,CYP,1991,5770197348.48485 +Cyprus,CYP,1992,6912150456.32334 +Cyprus,CYP,1993,6590291048.29211 +Cyprus,CYP,1994,7425703928.57143 +Cyprus,CYP,1995,9826778783.9586 +Cyprus,CYP,1996,9899623588.45671 +Cyprus,CYP,1997,9594298745.72406 +Cyprus,CYP,1998,10353506787.3303 +Cyprus,CYP,1999,10614455231.931 +Cyprus,CYP,2000,10183317624.8822 +Cyprus,CYP,2001,10567304189.4353 +Cyprus,CYP,2002,11618269230.7692 +Cyprus,CYP,2003,14576896942.2424 +Cyprus,CYP,2004,17422375000 +Cyprus,CYP,2005,18703146374.829 +Cyprus,CYP,2006,20403713461.2972 +Cyprus,CYP,2007,24077470572.1325 +Cyprus,CYP,2008,27839460963.8201 +Cyprus,CYP,2009,25942622950.8197 +Cyprus,CYP,2010,25562251655.6291 +Cyprus,CYP,2011,27427161523.4918 +Cyprus,CYP,2012,25012206090.1966 +Cyprus,CYP,2013,24054965480.616 +Cyprus,CYP,2014,23308212816.7706 +Cyprus,CYP,2015,19559942331.1523 +Cyprus,CYP,2016,19801664168.2788 +Czech Republic,CZE,1990,40315847383.7197 +Czech Republic,CZE,1991,29557058174.1697 +Czech Republic,CZE,1992,34451993226.0347 +Czech Republic,CZE,1993,40452245779.1651 +Czech Republic,CZE,1994,47364869195.7617 +Czech Republic,CZE,1995,59537113790.5049 +Czech Republic,CZE,1996,66775046785.4354 +Czech Republic,CZE,1997,61621364981.4187 +Czech Republic,CZE,1998,66372594575.1707 +Czech Republic,CZE,1999,64719461254.5271 +Czech Republic,CZE,2000,61474265134.5364 +Czech Republic,CZE,2001,67375623427.4642 +Czech Republic,CZE,2002,81696651658.8981 +Czech Republic,CZE,2003,99300329682.0164 +Czech Republic,CZE,2004,118976023159.713 +Czech Republic,CZE,2005,135990215966.674 +Czech Republic,CZE,2006,155213006071.979 +Czech Republic,CZE,2007,188818155388.125 +Czech Republic,CZE,2008,235204812643.146 +Czech Republic,CZE,2009,205729790694.015 +Czech Republic,CZE,2010,207016402026.364 +Czech Republic,CZE,2011,227948349666.354 +Czech Republic,CZE,2012,207376427020.815 +Czech Republic,CZE,2013,209402444996.104 +Czech Republic,CZE,2014,207818330723.835 +Czech Republic,CZE,2015,185156359571.116 +Czech Republic,CZE,2016,192924593987.295 +Denmark,DNK,1960,6248946880.2777 +Denmark,DNK,1961,6933842098.84548 +Denmark,DNK,1962,7812968114.40012 +Denmark,DNK,1963,8316692385.77386 +Denmark,DNK,1964,9506678762.77765 +Denmark,DNK,1965,10678897387.0006 +Denmark,DNK,1966,11721248101.0874 +Denmark,DNK,1967,12788479692.1939 +Denmark,DNK,1968,13196541952 +Denmark,DNK,1969,15009384584.5333 +Denmark,DNK,1970,17075466666.6667 +Denmark,DNK,1971,19085681968.1403 +Denmark,DNK,1972,23232411897.6012 +Denmark,DNK,1973,30730638895.7765 +Denmark,DNK,1974,34160363582.6675 +Denmark,DNK,1975,40474400473.3563 +Denmark,DNK,1976,44575847808.1059 +Denmark,DNK,1977,49784281716.4179 +Denmark,DNK,1978,60362854966.8154 +Denmark,DNK,1979,70366280174.8717 +Denmark,DNK,1980,71127592753.5975 +Denmark,DNK,1981,61877755004.6326 +Denmark,DNK,1982,60412846238.7787 +Denmark,DNK,1983,60644833242.2089 +Denmark,DNK,1984,59105208272.9853 +Denmark,DNK,1985,62658544411.3095 +Denmark,DNK,1986,88078729452.4781 +Denmark,DNK,1987,109414353171.645 +Denmark,DNK,1988,115552848547.872 +Denmark,DNK,1989,112409236409.401 +Denmark,DNK,1990,138247261092.977 +Denmark,DNK,1991,139224732275.463 +Denmark,DNK,1992,152915624326.966 +Denmark,DNK,1993,143195607581.857 +Denmark,DNK,1994,156162311731.598 +Denmark,DNK,1995,185006961302.299 +Denmark,DNK,1996,187632400365.599 +Denmark,DNK,1997,173537588008.176 +Denmark,DNK,1998,176992000955.11 +Denmark,DNK,1999,177965224620.854 +Denmark,DNK,2000,164158800460.219 +Denmark,DNK,2001,164791416350.267 +Denmark,DNK,2002,178635160297.415 +Denmark,DNK,2003,218095997085.477 +Denmark,DNK,2004,251373036671.062 +Denmark,DNK,2005,264467308109.19 +Denmark,DNK,2006,282884912894.33 +Denmark,DNK,2007,319423370134.284 +Denmark,DNK,2008,353361056079.716 +Denmark,DNK,2009,321241396034.248 +Denmark,DNK,2010,321995350346.501 +Denmark,DNK,2011,344003209695.606 +Denmark,DNK,2012,327148899962.146 +Denmark,DNK,2013,343584385594.132 +Denmark,DNK,2014,352296969840.949 +Denmark,DNK,2015,301307828843.613 +Denmark,DNK,2016,306142937248.09 +Djibouti,DJI,1985,340989527.967995 +Djibouti,DJI,1987,373371738.286415 +Djibouti,DJI,1988,395794538.630775 +Djibouti,DJI,1989,409220087.102818 +Djibouti,DJI,1990,452328087.282876 +Djibouti,DJI,1991,462421998.525779 +Djibouti,DJI,1992,478058304.871118 +Djibouti,DJI,1993,466048469.22986 +Djibouti,DJI,1994,491689220.744875 +Djibouti,DJI,1995,497723960.589913 +Djibouti,DJI,1996,494004647.73437 +Djibouti,DJI,1997,502675542.001227 +Djibouti,DJI,1998,514267869.300758 +Djibouti,DJI,1999,536080148.097299 +Djibouti,DJI,2000,551230861.856505 +Djibouti,DJI,2001,572417440.820162 +Djibouti,DJI,2002,591122039.601398 +Djibouti,DJI,2003,622044665.515049 +Djibouti,DJI,2004,666072101.777505 +Djibouti,DJI,2005,708633194.726566 +Djibouti,DJI,2006,768873684.032838 +Djibouti,DJI,2007,847918929.107984 +Djibouti,DJI,2008,999105339.267729 +Djibouti,DJI,2009,1049110684.72493 +Djibouti,DJI,2010,1128611700.3618 +Djibouti,DJI,2011,1239144501.77525 +Djibouti,DJI,2012,1353632941.5207 +Djibouti,DJI,2013,1455000000 +Djibouti,DJI,2014,1588000000 +Djibouti,DJI,2015,1727000000 +Dominica,DMA,1977,36370370.3703704 +Dominica,DMA,1978,45170370.3703704 +Dominica,DMA,1979,44296296.2962963 +Dominica,DMA,1980,59100000 +Dominica,DMA,1981,66218518.5185185 +Dominica,DMA,1982,72051851.8518518 +Dominica,DMA,1983,79925925.9259259 +Dominica,DMA,1984,89848148.1481481 +Dominica,DMA,1985,98585185.1851852 +Dominica,DMA,1986,112074074.074074 +Dominica,DMA,1987,126348148.148148 +Dominica,DMA,1988,143766666.666667 +Dominica,DMA,1989,153374074.074074 +Dominica,DMA,1990,166322222.222222 +Dominica,DMA,1991,180437037.037037 +Dominica,DMA,1992,191759259.259259 +Dominica,DMA,1993,200418518.518519 +Dominica,DMA,1994,215459259.259259 +Dominica,DMA,1995,224037037.037037 +Dominica,DMA,1996,236444444.444444 +Dominica,DMA,1997,245781481.481481 +Dominica,DMA,1998,258440740.740741 +Dominica,DMA,1999,267740740.740741 +Dominica,DMA,2000,335845814.814815 +Dominica,DMA,2001,343119370.37037 +Dominica,DMA,2002,337695740.740741 +Dominica,DMA,2003,350091222.222222 +Dominica,DMA,2004,374771481.481481 +Dominica,DMA,2005,370370370.37037 +Dominica,DMA,2006,390370370.37037 +Dominica,DMA,2007,421375851.851852 +Dominica,DMA,2008,458190185.185185 +Dominica,DMA,2009,489074333.333333 +Dominica,DMA,2010,493824407.407407 +Dominica,DMA,2011,500988407.407407 +Dominica,DMA,2012,485905592.592593 +Dominica,DMA,2013,508447148.148148 +Dominica,DMA,2014,528178703.703704 +Dominica,DMA,2015,517218962.962963 +Dominica,DMA,2016,525424630 +Dominican Republic,DOM,1960,672399700 +Dominican Republic,DOM,1961,654100200 +Dominican Republic,DOM,1962,824100000 +Dominican Republic,DOM,1963,940799900 +Dominican Republic,DOM,1964,1025599900 +Dominican Republic,DOM,1965,888100000 +Dominican Republic,DOM,1966,983900000 +Dominican Republic,DOM,1967,1034800000 +Dominican Republic,DOM,1968,1079100000 +Dominican Republic,DOM,1969,1230500000 +Dominican Republic,DOM,1970,1485400100 +Dominican Republic,DOM,1971,1666400000 +Dominican Republic,DOM,1972,1987300000 +Dominican Republic,DOM,1973,2344699900 +Dominican Republic,DOM,1974,2925600000 +Dominican Republic,DOM,1975,3599300100 +Dominican Republic,DOM,1976,3951399900 +Dominican Republic,DOM,1977,4587100200 +Dominican Republic,DOM,1978,4774400000 +Dominican Republic,DOM,1979,5498800100 +Dominican Republic,DOM,1980,6631000100 +Dominican Republic,DOM,1981,7266999800 +Dominican Republic,DOM,1982,7964000300 +Dominican Republic,DOM,1983,8622000100 +Dominican Republic,DOM,1984,10330399700 +Dominican Republic,DOM,1985,5044592912.6775 +Dominican Republic,DOM,1986,6122197810.14358 +Dominican Republic,DOM,1987,5826987203.49563 +Dominican Republic,DOM,1988,5374315190.18405 +Dominican Republic,DOM,1989,6686592728.70663 +Dominican Republic,DOM,1990,7073674721.12418 +Dominican Republic,DOM,1991,9724402004.34906 +Dominican Republic,DOM,1992,11277676879.9612 +Dominican Republic,DOM,1993,12976408000 +Dominican Republic,DOM,1994,14511134920.6349 +Dominican Republic,DOM,1995,16358496124.031 +Dominican Republic,DOM,1996,18131813000.6281 +Dominican Republic,DOM,1997,19593869595.0191 +Dominican Republic,DOM,1998,21171523985.0642 +Dominican Republic,DOM,1999,21709726722.118 +Dominican Republic,DOM,2000,23996063503.0497 +Dominican Republic,DOM,2001,24892521236.9553 +Dominican Republic,DOM,2002,26571620978.7885 +Dominican Republic,DOM,2003,21277165885.6865 +Dominican Republic,DOM,2004,22039232609.9553 +Dominican Republic,DOM,2005,34004033803.9438 +Dominican Republic,DOM,2006,35952845582.5029 +Dominican Republic,DOM,2007,44169678153.1566 +Dominican Republic,DOM,2008,48288967303.4896 +Dominican Republic,DOM,2009,48376555305.6902 +Dominican Republic,DOM,2010,53954579003.5277 +Dominican Republic,DOM,2011,57746684847.0898 +Dominican Republic,DOM,2012,60613645121.3529 +Dominican Republic,DOM,2013,61965942056.6828 +Dominican Republic,DOM,2014,65231032303.2418 +Dominican Republic,DOM,2015,68102618092.1031 +Dominican Republic,DOM,2016,71583553488.0804 +Ecuador,ECU,1960,1010325138.03016 +Ecuador,ECU,1961,979108806.848646 +Ecuador,ECU,1962,958598195.033967 +Ecuador,ECU,1963,1038389642.31418 +Ecuador,ECU,1964,1156150890.06133 +Ecuador,ECU,1965,2387048255.45173 +Ecuador,ECU,1966,2429309513.80854 +Ecuador,ECU,1967,2553596091.82258 +Ecuador,ECU,1968,2582180794.1855 +Ecuador,ECU,1969,3112166848.3004 +Ecuador,ECU,1970,2862504169.99893 +Ecuador,ECU,1971,2754220263.02528 +Ecuador,ECU,1972,3185987234.84089 +Ecuador,ECU,1973,3891755551.94138 +Ecuador,ECU,1974,6599259420.99605 +Ecuador,ECU,1975,7731677256.80982 +Ecuador,ECU,1976,9091924304.83477 +Ecuador,ECU,1977,11026346589.5011 +Ecuador,ECU,1978,11922502170.6405 +Ecuador,ECU,1979,14175166007.5774 +Ecuador,ECU,1980,17881514682.8784 +Ecuador,ECU,1981,21810767209.3695 +Ecuador,ECU,1982,19929853574.6095 +Ecuador,ECU,1983,17152483214.3536 +Ecuador,ECU,1984,16912515183.2783 +Ecuador,ECU,1985,17149094589.9827 +Ecuador,ECU,1986,15314143988.0621 +Ecuador,ECU,1987,13945431882.2271 +Ecuador,ECU,1988,13051886552.3377 +Ecuador,ECU,1989,13890828707.6493 +Ecuador,ECU,1990,15239278100.3502 +Ecuador,ECU,1991,16988535267.6338 +Ecuador,ECU,1992,18094238119.0595 +Ecuador,ECU,1993,18938717358.6793 +Ecuador,ECU,1994,22708673336.6683 +Ecuador,ECU,1995,24432884442.2211 +Ecuador,ECU,1996,25226393196.5983 +Ecuador,ECU,1997,28162053026.5133 +Ecuador,ECU,1998,27981896948.4742 +Ecuador,ECU,1999,19645272636.3182 +Ecuador,ECU,2000,18327764882.4412 +Ecuador,ECU,2001,24468324000 +Ecuador,ECU,2002,28548945000 +Ecuador,ECU,2003,32432859000 +Ecuador,ECU,2004,36591661000 +Ecuador,ECU,2005,41507085000 +Ecuador,ECU,2006,46802044000 +Ecuador,ECU,2007,51007777000 +Ecuador,ECU,2008,61762635000 +Ecuador,ECU,2009,62519686000 +Ecuador,ECU,2010,69555367000 +Ecuador,ECU,2011,79276664000 +Ecuador,ECU,2012,87924544000 +Ecuador,ECU,2013,95129659000 +Ecuador,ECU,2014,102292260000 +Ecuador,ECU,2015,100176808000 +Ecuador,ECU,2016,97802211000 +"Egypt, Arab Rep.",EGY,1965,5111621013.54303 +"Egypt, Arab Rep.",EGY,1966,5339520612.99374 +"Egypt, Arab Rep.",EGY,1967,5579168509.50907 +"Egypt, Arab Rep.",EGY,1968,6109112149.53271 +"Egypt, Arab Rep.",EGY,1969,6861743341.40436 +"Egypt, Arab Rep.",EGY,1970,7682491836.22206 +"Egypt, Arab Rep.",EGY,1971,8266003570.51773 +"Egypt, Arab Rep.",EGY,1972,8763960703.20579 +"Egypt, Arab Rep.",EGY,1973,9616725366.34664 +"Egypt, Arab Rep.",EGY,1974,9015166839.80885 +"Egypt, Arab Rep.",EGY,1975,11437965585.2696 +"Egypt, Arab Rep.",EGY,1976,13360476861.9662 +"Egypt, Arab Rep.",EGY,1977,14636028766.883 +"Egypt, Arab Rep.",EGY,1978,14849909490.6004 +"Egypt, Arab Rep.",EGY,1979,18150000571.4286 +"Egypt, Arab Rep.",EGY,1980,22912500555.5556 +"Egypt, Arab Rep.",EGY,1981,23405404729.7297 +"Egypt, Arab Rep.",EGY,1982,25592365394.0887 +"Egypt, Arab Rep.",EGY,1983,28137369499.4179 +"Egypt, Arab Rep.",EGY,1984,30642873038.0563 +"Egypt, Arab Rep.",EGY,1985,34689560464.8728 +"Egypt, Arab Rep.",EGY,1986,35880262675.3976 +"Egypt, Arab Rep.",EGY,1987,40507934171.249 +"Egypt, Arab Rep.",EGY,1988,35044634014.7643 +"Egypt, Arab Rep.",EGY,1989,39648442534.0768 +"Egypt, Arab Rep.",EGY,1990,43130416913.4141 +"Egypt, Arab Rep.",EGY,1991,36970555898.9698 +"Egypt, Arab Rep.",EGY,1992,41855986519.4235 +"Egypt, Arab Rep.",EGY,1993,46578631452.581 +"Egypt, Arab Rep.",EGY,1994,51897983392.6453 +"Egypt, Arab Rep.",EGY,1995,60159245060.4542 +"Egypt, Arab Rep.",EGY,1996,67629716981.1321 +"Egypt, Arab Rep.",EGY,1997,78436578171.0914 +"Egypt, Arab Rep.",EGY,1998,84828807556.0803 +"Egypt, Arab Rep.",EGY,1999,90710704806.8416 +"Egypt, Arab Rep.",EGY,2000,99838543960.0763 +"Egypt, Arab Rep.",EGY,2001,97632008709.853 +"Egypt, Arab Rep.",EGY,2002,87850683978.6691 +"Egypt, Arab Rep.",EGY,2003,82924503942.6381 +"Egypt, Arab Rep.",EGY,2004,78845185293.4964 +"Egypt, Arab Rep.",EGY,2005,89685725230.2517 +"Egypt, Arab Rep.",EGY,2006,107484034870.974 +"Egypt, Arab Rep.",EGY,2007,130478960092.499 +"Egypt, Arab Rep.",EGY,2008,162818181818.182 +"Egypt, Arab Rep.",EGY,2009,188982374700.805 +"Egypt, Arab Rep.",EGY,2010,218888324504.753 +"Egypt, Arab Rep.",EGY,2011,236001858960.015 +"Egypt, Arab Rep.",EGY,2012,279372758361.832 +"Egypt, Arab Rep.",EGY,2013,288586231501.877 +"Egypt, Arab Rep.",EGY,2014,305529656458.438 +"Egypt, Arab Rep.",EGY,2015,332698041030.807 +"Egypt, Arab Rep.",EGY,2016,336296921758.782 +El Salvador,SLV,1965,877720000 +El Salvador,SLV,1966,929520000 +El Salvador,SLV,1967,976200000 +El Salvador,SLV,1968,1009760100 +El Salvador,SLV,1969,1049400000 +El Salvador,SLV,1970,1132920000 +El Salvador,SLV,1971,1186120000 +El Salvador,SLV,1972,1263720000 +El Salvador,SLV,1973,1442320000 +El Salvador,SLV,1974,1665880000 +El Salvador,SLV,1975,1884120100 +El Salvador,SLV,1976,2328280100 +El Salvador,SLV,1977,2941640100 +El Salvador,SLV,1978,3127960000 +El Salvador,SLV,1979,3463639900 +El Salvador,SLV,1980,3573959900 +El Salvador,SLV,1981,3437200200 +El Salvador,SLV,1982,3399189100 +El Salvador,SLV,1983,3506347800 +El Salvador,SLV,1984,3661683400 +El Salvador,SLV,1985,3800368600 +El Salvador,SLV,1986,3771663200 +El Salvador,SLV,1987,3958045800 +El Salvador,SLV,1988,4189880000 +El Salvador,SLV,1989,4372215300 +El Salvador,SLV,1990,4800900000 +El Salvador,SLV,1991,5311000000 +El Salvador,SLV,1992,5954700000 +El Salvador,SLV,1993,6938000000 +El Salvador,SLV,1994,8085600000 +El Salvador,SLV,1995,9500500000 +El Salvador,SLV,1996,10315500000 +El Salvador,SLV,1997,11134700000 +El Salvador,SLV,1998,12008400000 +El Salvador,SLV,1999,12464700000 +El Salvador,SLV,2000,13134100000 +El Salvador,SLV,2001,13812700000 +El Salvador,SLV,2002,14306700000 +El Salvador,SLV,2003,15046700000 +El Salvador,SLV,2004,15798300000 +El Salvador,SLV,2005,17093800000 +El Salvador,SLV,2006,18550700000 +El Salvador,SLV,2007,20104900000 +El Salvador,SLV,2008,21430950000 +El Salvador,SLV,2009,20661030000 +El Salvador,SLV,2010,21418330000 +El Salvador,SLV,2011,23139040000 +El Salvador,SLV,2012,23813600000 +El Salvador,SLV,2013,24350930000 +El Salvador,SLV,2014,25054230000 +El Salvador,SLV,2015,26052340000 +El Salvador,SLV,2016,26797470000 +Equatorial Guinea,GNQ,1962,9122751.45318345 +Equatorial Guinea,GNQ,1963,10840095.1283649 +Equatorial Guinea,GNQ,1964,12712471.3960211 +Equatorial Guinea,GNQ,1965,64748333.3333333 +Equatorial Guinea,GNQ,1966,69110000 +Equatorial Guinea,GNQ,1967,72317446.9327193 +Equatorial Guinea,GNQ,1968,67514285.7142857 +Equatorial Guinea,GNQ,1969,67225714.2857143 +Equatorial Guinea,GNQ,1970,66331428.5714286 +Equatorial Guinea,GNQ,1971,64946954.756798 +Equatorial Guinea,GNQ,1972,65429198.238708 +Equatorial Guinea,GNQ,1973,81203226.9138345 +Equatorial Guinea,GNQ,1974,94159862.7073691 +Equatorial Guinea,GNQ,1975,104295643.388437 +Equatorial Guinea,GNQ,1976,103653049.93797 +Equatorial Guinea,GNQ,1977,103987520.075827 +Equatorial Guinea,GNQ,1980,50642880.7737503 +Equatorial Guinea,GNQ,1981,36731422.8456914 +Equatorial Guinea,GNQ,1982,44294647.733479 +Equatorial Guinea,GNQ,1983,44442456.94764 +Equatorial Guinea,GNQ,1984,50320914.4065688 +Equatorial Guinea,GNQ,1985,62118564.8495425 +Equatorial Guinea,GNQ,1986,76407396.7552964 +Equatorial Guinea,GNQ,1987,93345847.7270323 +Equatorial Guinea,GNQ,1988,100534663.294927 +Equatorial Guinea,GNQ,1989,88265974.5843603 +Equatorial Guinea,GNQ,1990,112119406.548331 +Equatorial Guinea,GNQ,1991,110906032.075075 +Equatorial Guinea,GNQ,1992,134707184.355541 +Equatorial Guinea,GNQ,1993,136047896.155778 +Equatorial Guinea,GNQ,1994,100807001.813926 +Equatorial Guinea,GNQ,1995,141853368.256815 +Equatorial Guinea,GNQ,1996,232463036.435759 +Equatorial Guinea,GNQ,1997,442337849.474377 +Equatorial Guinea,GNQ,1998,370687618.717326 +Equatorial Guinea,GNQ,1999,621117885.668503 +Equatorial Guinea,GNQ,2000,1045998496.43872 +Equatorial Guinea,GNQ,2001,1461139022.02954 +Equatorial Guinea,GNQ,2002,1806742742.27311 +Equatorial Guinea,GNQ,2003,2484745935.09329 +Equatorial Guinea,GNQ,2004,4410764338.66733 +Equatorial Guinea,GNQ,2005,8217369092.65224 +Equatorial Guinea,GNQ,2006,10086528698.8604 +Equatorial Guinea,GNQ,2007,13071718758.7373 +Equatorial Guinea,GNQ,2008,19749893536.3204 +Equatorial Guinea,GNQ,2009,15027795173.2187 +Equatorial Guinea,GNQ,2010,16298542027.9965 +Equatorial Guinea,GNQ,2011,21329395900.871 +Equatorial Guinea,GNQ,2012,22389627294.4179 +Equatorial Guinea,GNQ,2013,21942597765.3631 +Equatorial Guinea,GNQ,2014,21461989483.1265 +Equatorial Guinea,GNQ,2015,12162117377.3923 +Equatorial Guinea,GNQ,2016,10178967206.0184 +Eritrea,ERI,1992,477101651.648376 +Eritrea,ERI,1993,467872714.755603 +Eritrea,ERI,1994,531688311.688312 +Eritrea,ERI,1995,578015625 +Eritrea,ERI,1996,693535954.190067 +Eritrea,ERI,1997,686490090.140141 +Eritrea,ERI,1998,745526154.93283 +Eritrea,ERI,1999,688921325.712043 +Eritrea,ERI,2000,706370815.584416 +Eritrea,ERI,2001,752368495.512622 +Eritrea,ERI,2002,729321366.651861 +Eritrea,ERI,2003,870247703.182758 +Eritrea,ERI,2004,1109054005.43971 +Eritrea,ERI,2005,1098425900.74116 +Eritrea,ERI,2006,1211161879.6748 +Eritrea,ERI,2007,1317974491.05691 +Eritrea,ERI,2008,1380188800 +Eritrea,ERI,2009,1856695551.21951 +Eritrea,ERI,2010,2117039512.19512 +Eritrea,ERI,2011,2607739837.39837 +Estonia,EST,1995,4373665145.55468 +Estonia,EST,1996,4746109767.1999 +Estonia,EST,1997,5066240419.29666 +Estonia,EST,1998,5617109244.63233 +Estonia,EST,1999,5726897998.29642 +Estonia,EST,2000,5685774808.80862 +Estonia,EST,2001,6245069734.13302 +Estonia,EST,2002,7322069511.16134 +Estonia,EST,2003,9833870709.12376 +Estonia,EST,2004,12059201242.236 +Estonia,EST,2005,14006088297.4754 +Estonia,EST,2006,16963625015.6818 +Estonia,EST,2007,22237061730.0849 +Estonia,EST,2008,24194039255.8957 +Estonia,EST,2009,19652492636.8436 +Estonia,EST,2010,19490936349.1753 +Estonia,EST,2011,23170239900.7654 +Estonia,EST,2012,23043864510.0543 +Estonia,EST,2013,25081185830.6876 +Estonia,EST,2014,26213940386.7883 +Estonia,EST,2015,22460470490.0133 +Estonia,EST,2016,23136741984.155 +Ethiopia,ETH,1981,7324903188.4058 +Ethiopia,ETH,1982,7707678019.32367 +Ethiopia,ETH,1983,8567890821.25604 +Ethiopia,ETH,1984,8096302367.14976 +Ethiopia,ETH,1985,9480840483.09179 +Ethiopia,ETH,1986,9848600869.56522 +Ethiopia,ETH,1987,10527338647.343 +Ethiopia,ETH,1988,10908935748.7923 +Ethiopia,ETH,1989,11476584879.2271 +Ethiopia,ETH,1990,12175166763.285 +Ethiopia,ETH,1991,13463868357.4879 +Ethiopia,ETH,1992,10492993077.6093 +Ethiopia,ETH,1993,8830712713.90781 +Ethiopia,ETH,1994,6927950564.55657 +Ethiopia,ETH,1995,7663984567.90123 +Ethiopia,ETH,1996,8547939730.62374 +Ethiopia,ETH,1997,8589211390.49612 +Ethiopia,ETH,1998,7818224905.55071 +Ethiopia,ETH,1999,7700833482.00615 +Ethiopia,ETH,2000,8242392103.68061 +Ethiopia,ETH,2001,8231326016.47494 +Ethiopia,ETH,2002,7850809498.16803 +Ethiopia,ETH,2003,8623691300.04079 +Ethiopia,ETH,2004,10131187261.4421 +Ethiopia,ETH,2005,12401139453.9738 +Ethiopia,ETH,2006,15280861834.6024 +Ethiopia,ETH,2007,19707616772.7996 +Ethiopia,ETH,2008,27066912635.2228 +Ethiopia,ETH,2009,32437389116.038 +Ethiopia,ETH,2010,29933790334.3418 +Ethiopia,ETH,2011,31952763089.33 +Ethiopia,ETH,2012,43310721414.0829 +Ethiopia,ETH,2013,47648211133.2183 +Ethiopia,ETH,2014,55612228233.5179 +Ethiopia,ETH,2015,64464423674.6569 +Ethiopia,ETH,2016,72374252815.3782 +Faroe Islands,FRO,1998,1105688872.97039 +Faroe Islands,FRO,1999,1125684470.05533 +Faroe Islands,FRO,2000,1062339943.83343 +Faroe Islands,FRO,2001,1154899793.33878 +Faroe Islands,FRO,2002,1268445919.41429 +Faroe Islands,FRO,2003,1486861878.95624 +Faroe Islands,FRO,2004,1683997930.26322 +Faroe Islands,FRO,2005,1730891409.07567 +Faroe Islands,FRO,2006,1970142377.91507 +Faroe Islands,FRO,2007,2278229533.05096 +Faroe Islands,FRO,2008,2413237402.14803 +Faroe Islands,FRO,2009,2257097731.55019 +Faroe Islands,FRO,2010,2301178416.00619 +Faroe Islands,FRO,2011,2468748767.9772 +Faroe Islands,FRO,2012,2356505419.09755 +Faroe Islands,FRO,2013,2613458942.48139 +Fiji,FJI,1960,112328422.113084 +Fiji,FJI,1961,116987784.913739 +Fiji,FJI,1962,122906434.957814 +Fiji,FJI,1963,129454728.623599 +Fiji,FJI,1964,140032741.468329 +Fiji,FJI,1965,147084750.031482 +Fiji,FJI,1966,150603925.515853 +Fiji,FJI,1967,162625885.863484 +Fiji,FJI,1968,166952937.135005 +Fiji,FJI,1969,182182067.703568 +Fiji,FJI,1970,219878482.173564 +Fiji,FJI,1971,247749327.721267 +Fiji,FJI,1972,316650508.967523 +Fiji,FJI,1973,425963359.355326 +Fiji,FJI,1974,558589870.903674 +Fiji,FJI,1975,684268280.812751 +Fiji,FJI,1976,694552411.718837 +Fiji,FJI,1977,719533137.126662 +Fiji,FJI,1978,829239489.844119 +Fiji,FJI,1979,1019743927.24662 +Fiji,FJI,1980,1202567359.4132 +Fiji,FJI,1981,1235899836.18067 +Fiji,FJI,1982,1194015444.01544 +Fiji,FJI,1983,1123107276.30285 +Fiji,FJI,1984,1177997413.63384 +Fiji,FJI,1985,1141210124.82663 +Fiji,FJI,1986,1290228616.82408 +Fiji,FJI,1987,1177908191.97685 +Fiji,FJI,1988,1109976927.91722 +Fiji,FJI,1989,1182686577.22645 +Fiji,FJI,1990,1337024782.22702 +Fiji,FJI,1991,1383843860.1247 +Fiji,FJI,1992,1531803060.54558 +Fiji,FJI,1993,1635426125.30808 +Fiji,FJI,1994,1825285158.11762 +Fiji,FJI,1995,1970347720.96992 +Fiji,FJI,1996,2129266728.42585 +Fiji,FJI,1997,2093994597.21549 +Fiji,FJI,1998,1656784779.545 +Fiji,FJI,1999,1942170999.18765 +Fiji,FJI,2000,1684109743.49338 +Fiji,FJI,2001,1660102345.60309 +Fiji,FJI,2002,1842691481.09196 +Fiji,FJI,2003,2315935752.71653 +Fiji,FJI,2004,2727507212.92556 +Fiji,FJI,2005,3006725014.78415 +Fiji,FJI,2006,3102741451.01664 +Fiji,FJI,2007,3405050611.68726 +Fiji,FJI,2008,3523185919.55826 +Fiji,FJI,2009,2870624635.68032 +Fiji,FJI,2010,3140508835.9485 +Fiji,FJI,2011,3774530615.65916 +Fiji,FJI,2012,3972012570.53467 +Fiji,FJI,2013,4190143206.25611 +Fiji,FJI,2014,4469810099.08335 +Fiji,FJI,2015,4391064780.77249 +Fiji,FJI,2016,4631626233.96998 +Finland,FIN,1960,5224102195.52771 +Finland,FIN,1961,5921659485.03284 +Finland,FIN,1962,6340580854.39073 +Finland,FIN,1963,6885920328.66187 +Finland,FIN,1964,7766655085.78588 +Finland,FIN,1965,8589340019.02985 +Finland,FIN,1966,9208524504.87684 +Finland,FIN,1967,9368954010.3132 +Finland,FIN,1968,8823033880.32993 +Finland,FIN,1969,10070766720.5011 +Finland,FIN,1970,11365953567.3839 +Finland,FIN,1971,12536710287.0134 +Finland,FIN,1972,14754136507.0261 +Finland,FIN,1973,19486826979.9284 +Finland,FIN,1974,24867278714.3532 +Finland,FIN,1975,29494515597.22 +Finland,FIN,1976,31873171718.726 +Finland,FIN,1977,33524682307.8058 +Finland,FIN,1978,36283091407.9422 +Finland,FIN,1979,44498283620.8213 +Finland,FIN,1980,53685049410.2646 +Finland,FIN,1981,52485533204.7396 +Finland,FIN,1982,52832120389.7866 +Finland,FIN,1983,51014090520.9223 +Finland,FIN,1984,52926394934.7052 +Finland,FIN,1985,55914236377.5902 +Finland,FIN,1986,73586676049.7302 +Finland,FIN,1987,91642093872.5822 +Finland,FIN,1988,109103056147.832 +Finland,FIN,1989,119064708327.56 +Finland,FIN,1990,141517648888.198 +Finland,FIN,1991,127866490222.026 +Finland,FIN,1992,112625431377.754 +Finland,FIN,1993,89255751014.885 +Finland,FIN,1994,103321570859.419 +Finland,FIN,1995,134199346405.229 +Finland,FIN,1996,132099404607.818 +Finland,FIN,1997,126833123353.568 +Finland,FIN,1998,133936359590.565 +Finland,FIN,1999,135225868314.511 +Finland,FIN,2000,125539893126.958 +Finland,FIN,2001,129250111856.823 +Finland,FIN,2002,139552983248.635 +Finland,FIN,2003,171071106094.808 +Finland,FIN,2004,196768065557.487 +Finland,FIN,2005,204436015420.968 +Finland,FIN,2006,216552502822.732 +Finland,FIN,2007,255384615384.615 +Finland,FIN,2008,283742493042.332 +Finland,FIN,2009,251499027507.641 +Finland,FIN,2010,247799815768.477 +Finland,FIN,2011,273674236772.815 +Finland,FIN,2012,256706466091.089 +Finland,FIN,2013,269980111642.898 +Finland,FIN,2014,272609288689.575 +Finland,FIN,2015,232361689855.142 +Finland,FIN,2016,236785046710.878 +France,FRA,1960,62651474946.6007 +France,FRA,1961,68346741504.4257 +France,FRA,1962,76313782251.6964 +France,FRA,1963,85551113767.3727 +France,FRA,1964,94906593388.3107 +France,FRA,1965,102160571409.274 +France,FRA,1966,110597467198.645 +France,FRA,1967,119466139619.589 +France,FRA,1968,129847107787.883 +France,FRA,1969,140725497222.277 +France,FRA,1970,148948860281.091 +France,FRA,1971,166564460755.298 +France,FRA,1972,204283485045.514 +France,FRA,1973,265381555686.506 +France,FRA,1974,286526186579.378 +France,FRA,1975,362000917852.226 +France,FRA,1976,373410270417.919 +France,FRA,1977,411464295266.114 +France,FRA,1978,508183139534.884 +France,FRA,1979,615834104224.484 +France,FRA,1980,703525302701.025 +France,FRA,1981,617589619794.81 +France,FRA,1982,586837009681.605 +France,FRA,1983,561852138738.274 +France,FRA,1984,532648802822.187 +France,FRA,1985,555197109067.017 +France,FRA,1986,774556302680.178 +France,FRA,1987,938368438284.405 +France,FRA,1988,1023504019381.13 +France,FRA,1989,1030122352457.33 +France,FRA,1990,1275300566196.84 +France,FRA,1991,1275563306592.26 +France,FRA,1992,1408724907063.2 +France,FRA,1993,1330094973361.13 +France,FRA,1994,1401636342155.01 +France,FRA,1995,1609892232882.11 +France,FRA,1996,1614245416078.98 +France,FRA,1997,1460709148123.17 +France,FRA,1998,1510758283299.98 +France,FRA,1999,1500275942893.67 +France,FRA,2000,1368438363736.87 +France,FRA,2001,1382218344519.02 +France,FRA,2002,1500337850555.24 +France,FRA,2003,1848124153498.87 +France,FRA,2004,2124112242364.04 +France,FRA,2005,2203678646934.46 +France,FRA,2006,2325011918203.49 +France,FRA,2007,2663112510265.54 +France,FRA,2008,2923465651091.26 +France,FRA,2009,2693827452070.02 +France,FRA,2010,2646837111794.78 +France,FRA,2011,2862680142625.14 +France,FRA,2012,2681416108537.39 +France,FRA,2013,2808511203185.39 +France,FRA,2014,2849305322684.76 +France,FRA,2015,2433562015516.21 +France,FRA,2016,2465453975282.24 +French Polynesia,PYF,1965,176534589.603389 +French Polynesia,PYF,1966,215659455.017302 +French Polynesia,PYF,1967,220984369.12915 +French Polynesia,PYF,1968,259590076.293001 +French Polynesia,PYF,1969,242943776.862299 +French Polynesia,PYF,1970,254035999.217197 +French Polynesia,PYF,1971,296613496.873269 +French Polynesia,PYF,1972,325843254.667123 +French Polynesia,PYF,1973,431254103.046477 +French Polynesia,PYF,1974,555337985.682991 +French Polynesia,PYF,1975,690319754.911192 +French Polynesia,PYF,1976,732286143.34291 +French Polynesia,PYF,1977,793193187.41557 +French Polynesia,PYF,1978,1005573294.20763 +French Polynesia,PYF,1979,1215031775.26795 +French Polynesia,PYF,1980,1362151523.68993 +French Polynesia,PYF,1981,1279972866.38172 +French Polynesia,PYF,1982,1286462642.63697 +French Polynesia,PYF,1983,1335895286.3918 +French Polynesia,PYF,1984,1378991403.37881 +French Polynesia,PYF,1985,1507230778.89921 +French Polynesia,PYF,1986,2301514717.29807 +French Polynesia,PYF,1987,2543199148.3893 +French Polynesia,PYF,1988,2687472829.62988 +French Polynesia,PYF,1989,2636461517.1052 +French Polynesia,PYF,1990,3181206304.81549 +French Polynesia,PYF,1991,3267367609.89528 +French Polynesia,PYF,1992,3558215110.24809 +French Polynesia,PYF,1993,3694600399.89225 +French Polynesia,PYF,1994,3522272321.40766 +French Polynesia,PYF,1995,3982374845.92709 +French Polynesia,PYF,1996,3954696873.74892 +French Polynesia,PYF,1997,3567062511.87293 +French Polynesia,PYF,1998,3775160797.38928 +French Polynesia,PYF,1999,3797016068.69688 +French Polynesia,PYF,2000,3447543137.9415 +Gabon,GAB,1960,141468977.570007 +Gabon,GAB,1961,167637907.381723 +Gabon,GAB,1962,182796536.499884 +Gabon,GAB,1963,154480244.246844 +Gabon,GAB,1964,215679855.272516 +Gabon,GAB,1965,226474285.587109 +Gabon,GAB,1966,245849781.7159 +Gabon,GAB,1967,271543680.279285 +Gabon,GAB,1968,294468564.534369 +Gabon,GAB,1969,318124701.048949 +Gabon,GAB,1970,323802475.480977 +Gabon,GAB,1971,381687073.058558 +Gabon,GAB,1972,430508357.723916 +Gabon,GAB,1973,722780701.123251 +Gabon,GAB,1974,1544216003.9841 +Gabon,GAB,1975,2157592936.60712 +Gabon,GAB,1976,3009409970.90514 +Gabon,GAB,1977,2809349074.17738 +Gabon,GAB,1978,2389479269.18878 +Gabon,GAB,1979,3030251116.35999 +Gabon,GAB,1980,4279637933.85126 +Gabon,GAB,1981,3862269126.92642 +Gabon,GAB,1982,3618007844.44919 +Gabon,GAB,1983,3391275731.31834 +Gabon,GAB,1984,3561451562.23569 +Gabon,GAB,1985,3339914759.37269 +Gabon,GAB,1986,3403638193.57912 +Gabon,GAB,1987,3281797038.66591 +Gabon,GAB,1988,3834503378.35525 +Gabon,GAB,1989,4186411457.4569 +Gabon,GAB,1990,5952293765.84484 +Gabon,GAB,1991,5402919956.93831 +Gabon,GAB,1992,5592390848.52648 +Gabon,GAB,1993,4378645081.01769 +Gabon,GAB,1994,4190819314.02958 +Gabon,GAB,1995,4958845906.34769 +Gabon,GAB,1996,5694040336.82571 +Gabon,GAB,1997,5326816858.99586 +Gabon,GAB,1998,4483417119.83928 +Gabon,GAB,1999,4662992036.2073 +Gabon,GAB,2000,5067865320.7979 +Gabon,GAB,2001,5018874179.18704 +Gabon,GAB,2002,5310381151.35952 +Gabon,GAB,2003,6497305662.09274 +Gabon,GAB,2004,7756293574.98077 +Gabon,GAB,2005,9458884812.18106 +Gabon,GAB,2006,10154041929.6521 +Gabon,GAB,2007,12438956756.4455 +Gabon,GAB,2008,15508574820.3516 +Gabon,GAB,2009,12065138272.7538 +Gabon,GAB,2010,14358584300.3006 +Gabon,GAB,2011,18186478119.9582 +Gabon,GAB,2012,17171447372.3334 +Gabon,GAB,2013,17590716232.4913 +Gabon,GAB,2014,18179717776.1597 +Gabon,GAB,2015,14262032470.9041 +Gabon,GAB,2016,14213558130.1817 +"Gambia, The",GMB,1966,44212353.6988296 +"Gambia, The",GMB,1967,46695363.1558873 +"Gambia, The",GMB,1968,41160658.5705371 +"Gambia, The",GMB,1969,45168722.6995632 +"Gambia, The",GMB,1970,52296836.749388 +"Gambia, The",GMB,1971,55728608.974983 +"Gambia, The",GMB,1972,59161544.9957528 +"Gambia, The",GMB,1973,75187969.924812 +"Gambia, The",GMB,1974,95797533.4619206 +"Gambia, The",GMB,1975,115182522.123894 +"Gambia, The",GMB,1976,112189468.481826 +"Gambia, The",GMB,1977,138094243.349324 +"Gambia, The",GMB,1978,171836793.402695 +"Gambia, The",GMB,1979,207114382.546071 +"Gambia, The",GMB,1980,241080708.89018 +"Gambia, The",GMB,1981,218764445.784343 +"Gambia, The",GMB,1982,216051495.959817 +"Gambia, The",GMB,1983,213446562.57106 +"Gambia, The",GMB,1984,177338801.93075 +"Gambia, The",GMB,1985,225724851.691107 +"Gambia, The",GMB,1986,185646209.386282 +"Gambia, The",GMB,1987,220626484.224811 +"Gambia, The",GMB,1988,266673126.229801 +"Gambia, The",GMB,1989,284119692.49433 +"Gambia, The",GMB,1990,317083373.524559 +"Gambia, The",GMB,1991,690314321.374999 +"Gambia, The",GMB,1992,714255460.503389 +"Gambia, The",GMB,1993,755042548.055824 +"Gambia, The",GMB,1994,746491692.583857 +"Gambia, The",GMB,1995,785996982.492168 +"Gambia, The",GMB,1996,848237108.56163 +"Gambia, The",GMB,1997,803630742.53446 +"Gambia, The",GMB,1998,840285264.631545 +"Gambia, The",GMB,1999,814723460.08372 +"Gambia, The",GMB,2000,782915402.421095 +"Gambia, The",GMB,2001,687408804.630527 +"Gambia, The",GMB,2002,578236035.104279 +"Gambia, The",GMB,2003,487038821.611959 +"Gambia, The",GMB,2004,578785278.7703 +"Gambia, The",GMB,2005,624174723.713404 +"Gambia, The",GMB,2006,655068695.952711 +"Gambia, The",GMB,2007,798870894.208271 +"Gambia, The",GMB,2008,965769128.170004 +"Gambia, The",GMB,2009,900639747.93953 +"Gambia, The",GMB,2010,952429030.415536 +"Gambia, The",GMB,2011,904256643.415984 +"Gambia, The",GMB,2012,912569686.7859 +"Gambia, The",GMB,2013,903779326.206421 +"Gambia, The",GMB,2014,849122624.781348 +"Gambia, The",GMB,2015,938794719.358588 +"Gambia, The",GMB,2016,964599177.535474 +Georgia,GEO,1990,7753501867.76095 +Georgia,GEO,1991,6357615894.03974 +Georgia,GEO,1992,3690328963.64086 +Georgia,GEO,1993,2701181331.30816 +Georgia,GEO,1994,2513870586.73344 +Georgia,GEO,1995,2693731865.97036 +Georgia,GEO,1996,3094915505.9093 +Georgia,GEO,1997,3510540809.24855 +Georgia,GEO,1998,3613500117.24928 +Georgia,GEO,1999,2800024313.95144 +Georgia,GEO,2000,3057453482.55826 +Georgia,GEO,2001,3219487824.87911 +Georgia,GEO,2002,3395778673.79183 +Georgia,GEO,2003,3991374548.50512 +Georgia,GEO,2004,5125273880.74998 +Georgia,GEO,2005,6410941012.59189 +Georgia,GEO,2006,7745406200.85374 +Georgia,GEO,2007,10172869679.7366 +Georgia,GEO,2008,12795044472.7663 +Georgia,GEO,2009,10766809099.0721 +Georgia,GEO,2010,11638536834.4274 +Georgia,GEO,2011,14434619982.2117 +Georgia,GEO,2012,15846474595.773 +Georgia,GEO,2013,16140047012.1438 +Georgia,GEO,2014,16509305827.7171 +Georgia,GEO,2015,13993546732.4726 +Georgia,GEO,2016,14332880086.196 +Germany,DEU,1970,215021806498.156 +Germany,DEU,1971,249039217364.635 +Germany,DEU,1972,298667219346.133 +Germany,DEU,1973,396866742553.97 +Germany,DEU,1974,443618642959.716 +Germany,DEU,1975,488780155338.262 +Germany,DEU,1976,517787921003.573 +Germany,DEU,1977,598226205424.071 +Germany,DEU,1978,737668356280.428 +Germany,DEU,1979,878010536975.776 +Germany,DEU,1980,946695355820.96 +Germany,DEU,1981,797443405711.813 +Germany,DEU,1982,773638200773.757 +Germany,DEU,1983,767768378016.086 +Germany,DEU,1984,722367608343.069 +Germany,DEU,1985,729763282952.432 +Germany,DEU,1986,1042300769791.95 +Germany,DEU,1987,1293264353318.82 +Germany,DEU,1988,1395931548502.06 +Germany,DEU,1989,1393674332154.37 +Germany,DEU,1990,1764967948916.6 +Germany,DEU,1991,1861873895109.02 +Germany,DEU,1992,2123130870381.97 +Germany,DEU,1993,2068555542410.98 +Germany,DEU,1994,2205966011811.5 +Germany,DEU,1995,2591620035485.19 +Germany,DEU,1996,2503665193657.4 +Germany,DEU,1997,2218689375140.99 +Germany,DEU,1998,2243225519617.65 +Germany,DEU,1999,2199957383336.88 +Germany,DEU,2000,1949953934033.54 +Germany,DEU,2001,1950648769574.94 +Germany,DEU,2002,2079136081309.99 +Germany,DEU,2003,2505733634311.51 +Germany,DEU,2004,2819245095604.67 +Germany,DEU,2005,2861410272354.18 +Germany,DEU,2006,3002446368084.31 +Germany,DEU,2007,3439953462907.2 +Germany,DEU,2008,3752365607148.09 +Germany,DEU,2009,3418005001389.27 +Germany,DEU,2010,3417094562648.95 +Germany,DEU,2011,3757698281117.55 +Germany,DEU,2012,3543983909148.01 +Germany,DEU,2013,3752513503278.41 +Germany,DEU,2014,3879276587198.91 +Germany,DEU,2015,3363599907529.78 +Germany,DEU,2016,3466756880460.62 +Ghana,GHA,1960,1217230094.97205 +Ghana,GHA,1961,1302674324.88378 +Ghana,GHA,1962,1382515654.47343 +Ghana,GHA,1963,1540797588.57221 +Ghana,GHA,1964,1731296199.52296 +Ghana,GHA,1965,2053462968.0426 +Ghana,GHA,1966,2126300672.22965 +Ghana,GHA,1967,1747187644.9031 +Ghana,GHA,1968,1666909517.65205 +Ghana,GHA,1969,1962050555.7775 +Ghana,GHA,1970,2215028588.45646 +Ghana,GHA,1971,2417108577.52739 +Ghana,GHA,1972,2112293279.98507 +Ghana,GHA,1973,2465493032.25878 +Ghana,GHA,1974,2894409912.1709 +Ghana,GHA,1975,2810106390.10618 +Ghana,GHA,1976,2765254360.20623 +Ghana,GHA,1977,3189428571.42857 +Ghana,GHA,1978,3662478172.79996 +Ghana,GHA,1979,4020227931.15097 +Ghana,GHA,1980,4445228057.45354 +Ghana,GHA,1981,4222441673.17049 +Ghana,GHA,1982,4035994383.38367 +Ghana,GHA,1983,4057275077.68156 +Ghana,GHA,1984,4412279865.40315 +Ghana,GHA,1985,4504342152.98679 +Ghana,GHA,1986,5727602648.75537 +Ghana,GHA,1987,5074829931.97279 +Ghana,GHA,1988,5197840972.6857 +Ghana,GHA,1989,5251764269.91812 +Ghana,GHA,1990,5889174833.90034 +Ghana,GHA,1991,6596546195.65217 +Ghana,GHA,1992,6413901601.83066 +Ghana,GHA,1993,5966255778.12018 +Ghana,GHA,1994,5444560669.45607 +Ghana,GHA,1995,6465137614.6789 +Ghana,GHA,1996,6934984709.48012 +Ghana,GHA,1997,6891308593.75 +Ghana,GHA,1998,7480968858.13149 +Ghana,GHA,1999,7719354838.70968 +Ghana,GHA,2000,4983024408.14828 +Ghana,GHA,2001,5314909953.92992 +Ghana,GHA,2002,6166330136.2948 +Ghana,GHA,2003,7632406552.83803 +Ghana,GHA,2004,8881368538.07671 +Ghana,GHA,2005,10731634116.7384 +Ghana,GHA,2006,20409257610.4746 +Ghana,GHA,2007,24758819717.7074 +Ghana,GHA,2008,28526891010.4925 +Ghana,GHA,2009,25977847813.7422 +Ghana,GHA,2010,32174772955.9748 +Ghana,GHA,2011,39566292432.8615 +Ghana,GHA,2012,41939728978.7281 +Ghana,GHA,2013,47805069494.9082 +Ghana,GHA,2014,38616536131.648 +Ghana,GHA,2015,37543361203.5609 +Ghana,GHA,2016,42689783733.873 +Greece,GRC,1960,4446528164.67559 +Greece,GRC,1961,5016048786.22753 +Greece,GRC,1962,5327573509.09843 +Greece,GRC,1963,5949478034.88751 +Greece,GRC,1964,6680298250.57961 +Greece,GRC,1965,7600579093.1158 +Greece,GRC,1966,8455611129.27936 +Greece,GRC,1967,9136711287.82434 +Greece,GRC,1968,9915140546.35072 +Greece,GRC,1969,11266091570.5718 +Greece,GRC,1970,13139862500 +Greece,GRC,1971,14591755681.8182 +Greece,GRC,1972,16885506818.1818 +Greece,GRC,1973,22347844649.0219 +Greece,GRC,1974,25351305681.8182 +Greece,GRC,1975,28525872476.0893 +Greece,GRC,1976,31152840485.0746 +Greece,GRC,1977,36176233117.4838 +Greece,GRC,1978,44270203153.9889 +Greece,GRC,1979,54481875804.9678 +Greece,GRC,1980,56829663469.2246 +Greece,GRC,1981,52346507380.0738 +Greece,GRC,1982,54617991326.5306 +Greece,GRC,1983,49428872678.0186 +Greece,GRC,1984,48020024788.3918 +Greece,GRC,1985,47820850974.5867 +Greece,GRC,1986,56379593719.5716 +Greece,GRC,1987,65652751132.3603 +Greece,GRC,1988,76261278404.9964 +Greece,GRC,1989,79169043642.4675 +Greece,GRC,1990,97891090928.6328 +Greece,GRC,1991,105143232379.884 +Greece,GRC,1992,116224673042.546 +Greece,GRC,1993,108809058858.502 +Greece,GRC,1994,116601802106.742 +Greece,GRC,1995,136878366230.328 +Greece,GRC,1996,145861612825.595 +Greece,GRC,1997,143157600024.959 +Greece,GRC,1998,144428172835.236 +Greece,GRC,1999,142540728958.023 +Greece,GRC,2000,130133845771.144 +Greece,GRC,2001,136191353467.562 +Greece,GRC,2002,153830947016.751 +Greece,GRC,2003,201924270316.027 +Greece,GRC,2004,240521260988.329 +Greece,GRC,2005,247783001865.44 +Greece,GRC,2006,273317737046.795 +Greece,GRC,2007,318497936901.177 +Greece,GRC,2008,354460802548.704 +Greece,GRC,2009,330000252153.376 +Greece,GRC,2010,299361576558.217 +Greece,GRC,2011,287797822093.178 +Greece,GRC,2012,245670666639.047 +Greece,GRC,2013,239862011450.103 +Greece,GRC,2014,236079774688.445 +Greece,GRC,2015,194860187692.451 +Greece,GRC,2016,194558651275.836 +Greenland,GRL,1970,69520026.6666667 +Greenland,GRL,1971,88570952.8688525 +Greenland,GRL,1972,106101175.65798 +Greenland,GRL,1973,140153748.243656 +Greenland,GRL,1974,169918948.629182 +Greenland,GRL,1975,211194305.702999 +Greenland,GRL,1976,240780413.56493 +Greenland,GRL,1977,282269373.001066 +Greenland,GRL,1978,355989047.256374 +Greenland,GRL,1979,420642463.409998 +Greenland,GRL,1980,476055288.418886 +Greenland,GRL,1981,435746974.759244 +Greenland,GRL,1982,402405069.367769 +Greenland,GRL,1983,416183706.943685 +Greenland,GRL,1984,379371608.442925 +Greenland,GRL,1985,412876071.118493 +Greenland,GRL,1986,603015696.452849 +Greenland,GRL,1987,787392365.831908 +Greenland,GRL,1988,898611007.947709 +Greenland,GRL,1989,929796722.387896 +Greenland,GRL,1990,1018970364.86443 +Greenland,GRL,1991,1016493394.8253 +Greenland,GRL,1992,1037921836.9477 +Greenland,GRL,1993,927219728.866886 +Greenland,GRL,1994,1005879948.43254 +Greenland,GRL,1995,1208946165.92889 +Greenland,GRL,1996,1197509786.67632 +Greenland,GRL,1997,1072147778.03013 +Greenland,GRL,1998,1149862702.96084 +Greenland,GRL,1999,1131561595.13775 +Greenland,GRL,2000,1068030829.75591 +Greenland,GRL,2001,1086172922.57413 +Greenland,GRL,2002,1169138789.31435 +Greenland,GRL,2003,1407866174.84099 +Greenland,GRL,2004,1621822369.84861 +Greenland,GRL,2005,1656172355.71712 +Greenland,GRL,2006,1818759669.06572 +Greenland,GRL,2007,2049139372.11823 +Greenland,GRL,2008,2310743218.06163 +Greenland,GRL,2009,2324870823.92882 +Greenland,GRL,2010,2306502373.71313 +Greenland,GRL,2011,2515245776.44495 +Greenland,GRL,2012,2408666378.93828 +Greenland,GRL,2013,2483396542.2075 +Greenland,GRL,2014,2551126948.77506 +Greenland,GRL,2015,2220380802.33059 +Grenada,GRD,1977,71494495.1851852 +Grenada,GRD,1978,88322386.2962963 +Grenada,GRD,1979,102244362.222222 +Grenada,GRD,1980,110900457.037037 +Grenada,GRD,1981,115651918.888889 +Grenada,GRD,1982,125435590 +Grenada,GRD,1983,131803552.222222 +Grenada,GRD,1984,145533310.740741 +Grenada,GRD,1985,167728455.185185 +Grenada,GRD,1986,187589522.592593 +Grenada,GRD,1987,215009569.62963 +Grenada,GRD,1988,236357523.703704 +Grenada,GRD,1989,267327642.222222 +Grenada,GRD,1990,278098762.962963 +Grenada,GRD,1991,300757900 +Grenada,GRD,1992,310160455.925926 +Grenada,GRD,1993,309812192.962963 +Grenada,GRD,1994,325111808.148148 +Grenada,GRD,1995,342172523.703704 +Grenada,GRD,1996,366911440.37037 +Grenada,GRD,1997,392190585.925926 +Grenada,GRD,1998,445903598.888889 +Grenada,GRD,1999,482009371.481481 +Grenada,GRD,2000,520044370.37037 +Grenada,GRD,2001,520444185.185185 +Grenada,GRD,2002,540336925.925926 +Grenada,GRD,2003,591018407.407407 +Grenada,GRD,2004,599118592.592593 +Grenada,GRD,2005,695370296.296296 +Grenada,GRD,2006,698518518.518518 +Grenada,GRD,2007,758518518.518518 +Grenada,GRD,2008,825925925.925926 +Grenada,GRD,2009,771278111.111111 +Grenada,GRD,2010,771015888.888889 +Grenada,GRD,2011,778648666.666667 +Grenada,GRD,2012,799882148.148148 +Grenada,GRD,2013,842571333.333333 +Grenada,GRD,2014,911481481.481481 +Grenada,GRD,2015,984074074.074074 +Grenada,GRD,2016,1016208194.81481 +Guam,GUM,2002,3385000000 +Guam,GUM,2003,3560000000 +Guam,GUM,2004,3857000000 +Guam,GUM,2005,4197000000 +Guam,GUM,2006,4213000000 +Guam,GUM,2007,4375000000 +Guam,GUM,2008,4621000000 +Guam,GUM,2009,4781000000 +Guam,GUM,2010,4895000000 +Guam,GUM,2011,4928000000 +Guam,GUM,2012,5199000000 +Guam,GUM,2013,5364000000 +Guam,GUM,2014,5566000000 +Guam,GUM,2015,5734000000 +Guatemala,GTM,1960,1043599900 +Guatemala,GTM,1961,1076699900 +Guatemala,GTM,1962,1143600000 +Guatemala,GTM,1963,1262800000 +Guatemala,GTM,1964,1299099900 +Guatemala,GTM,1965,1331399900 +Guatemala,GTM,1966,1390700000 +Guatemala,GTM,1967,1453500000 +Guatemala,GTM,1968,1610500000 +Guatemala,GTM,1969,1715399900 +Guatemala,GTM,1970,1904000000 +Guatemala,GTM,1971,1984800000 +Guatemala,GTM,1972,2101300000 +Guatemala,GTM,1973,2569200100 +Guatemala,GTM,1974,3161499900 +Guatemala,GTM,1975,3645900000 +Guatemala,GTM,1976,4365300200 +Guatemala,GTM,1977,5480500200 +Guatemala,GTM,1978,6070600200 +Guatemala,GTM,1979,6902600200 +Guatemala,GTM,1980,7878700000 +Guatemala,GTM,1981,8607500300 +Guatemala,GTM,1982,8716999700 +Guatemala,GTM,1983,9050000400 +Guatemala,GTM,1984,9470000100 +Guatemala,GTM,1985,9721652086.95652 +Guatemala,GTM,1986,7231963515.98173 +Guatemala,GTM,1987,7084399840 +Guatemala,GTM,1988,7841602824.42748 +Guatemala,GTM,1989,8410724360.79546 +Guatemala,GTM,1990,7650125217.35253 +Guatemala,GTM,1991,9406097735.09117 +Guatemala,GTM,1992,10440842165.3193 +Guatemala,GTM,1993,11399942453.0646 +Guatemala,GTM,1994,12983235568.2292 +Guatemala,GTM,1995,14655487455.7333 +Guatemala,GTM,1996,15674852771.1356 +Guatemala,GTM,1997,17790095900.9809 +Guatemala,GTM,1998,19395461989.5391 +Guatemala,GTM,1999,18318512501.0256 +Guatemala,GTM,2000,19288926545.3759 +Guatemala,GTM,2001,18702802394.8286 +Guatemala,GTM,2002,20776669466.6053 +Guatemala,GTM,2003,21917706490.5299 +Guatemala,GTM,2004,23965275995.7214 +Guatemala,GTM,2005,27211377225.2715 +Guatemala,GTM,2006,30231249362.0604 +Guatemala,GTM,2007,34113107085.6085 +Guatemala,GTM,2008,39136893345.1501 +Guatemala,GTM,2009,37733994976.4137 +Guatemala,GTM,2010,41338595380.8159 +Guatemala,GTM,2011,47654841112.8523 +Guatemala,GTM,2012,50388454861.1111 +Guatemala,GTM,2013,53851058955.2999 +Guatemala,GTM,2014,58722323918.1604 +Guatemala,GTM,2015,63767597193.9175 +Guatemala,GTM,2016,68763255963.8943 +Guinea,GIN,1986,1922600899.3841 +Guinea,GIN,1987,2041538057.02893 +Guinea,GIN,1988,2384295763.72549 +Guinea,GIN,1989,2432029380.43694 +Guinea,GIN,1990,2666616176.91609 +Guinea,GIN,1991,3014890569.04099 +Guinea,GIN,1992,3284625277.16186 +Guinea,GIN,1993,3279063317.63475 +Guinea,GIN,1994,3383218922.79336 +Guinea,GIN,1995,3693753379.05992 +Guinea,GIN,1996,3869032270.91633 +Guinea,GIN,1997,3783788551.0819 +Guinea,GIN,1998,3588376057.01536 +Guinea,GIN,1999,3461282293.64624 +Guinea,GIN,2000,2995360969.16199 +Guinea,GIN,2001,2833442750.43639 +Guinea,GIN,2002,2949637039.04424 +Guinea,GIN,2003,3446442218.89829 +Guinea,GIN,2004,3666349049.42641 +Guinea,GIN,2005,2937071767.25576 +Guinea,GIN,2006,2931625104.50109 +Guinea,GIN,2007,4134173275.1244 +Guinea,GIN,2008,4515824647.43939 +Guinea,GIN,2009,4609923756.18485 +Guinea,GIN,2010,4735956493.06479 +Guinea,GIN,2011,5067360009.39196 +Guinea,GIN,2012,5667229758.9878 +Guinea,GIN,2013,6231725484.55943 +Guinea,GIN,2014,6624068015.50039 +Guinea,GIN,2015,6699203543.29047 +Guinea,GIN,2016,6298927773.1587 +Guinea-Bissau,GNB,1970,78733594.8444943 +Guinea-Bissau,GNB,1971,78540057.1428572 +Guinea-Bissau,GNB,1972,87702828.5714286 +Guinea-Bissau,GNB,1973,89374237.2881356 +Guinea-Bissau,GNB,1974,98775328.9473684 +Guinea-Bissau,GNB,1975,108985740.159382 +Guinea-Bissau,GNB,1976,112386489.013558 +Guinea-Bissau,GNB,1977,114971207.198201 +Guinea-Bissau,GNB,1978,122666858.789625 +Guinea-Bissau,GNB,1979,118537875.125881 +Guinea-Bissau,GNB,1980,110653830.726033 +Guinea-Bissau,GNB,1981,154731969.69697 +Guinea-Bissau,GNB,1982,165523634.49692 +Guinea-Bissau,GNB,1983,163577538.330494 +Guinea-Bissau,GNB,1984,138478900.626886 +Guinea-Bissau,GNB,1985,143856253.125 +Guinea-Bissau,GNB,1986,130225018.751674 +Guinea-Bissau,GNB,1987,173836362.010107 +Guinea-Bissau,GNB,1988,164458120.314078 +Guinea-Bissau,GNB,1989,213143016.443434 +Guinea-Bissau,GNB,1990,243961995.509711 +Guinea-Bissau,GNB,1991,257150573.215747 +Guinea-Bissau,GNB,1992,226313492.713567 +Guinea-Bissau,GNB,1993,236880813.821765 +Guinea-Bissau,GNB,1994,235619994.759074 +Guinea-Bissau,GNB,1995,253966919.939838 +Guinea-Bissau,GNB,1996,270419779.418107 +Guinea-Bissau,GNB,1997,268551010.941186 +Guinea-Bissau,GNB,1998,206457553.397101 +Guinea-Bissau,GNB,1999,224446652.14622 +Guinea-Bissau,GNB,2000,370173851.946119 +Guinea-Bissau,GNB,2001,392278168.199897 +Guinea-Bissau,GNB,2002,415843481.998691 +Guinea-Bissau,GNB,2003,476388260.639232 +Guinea-Bissau,GNB,2004,531109356.165462 +Guinea-Bissau,GNB,2005,586791883.717707 +Guinea-Bissau,GNB,2006,591829908.426264 +Guinea-Bissau,GNB,2007,695606288.605845 +Guinea-Bissau,GNB,2008,864136712.986648 +Guinea-Bissau,GNB,2009,825828703.628208 +Guinea-Bissau,GNB,2010,846332456.382994 +Guinea-Bissau,GNB,2011,1105497854.79398 +Guinea-Bissau,GNB,2012,995582062.343018 +Guinea-Bissau,GNB,2013,1026664188.52724 +Guinea-Bissau,GNB,2014,1109007299.94033 +Guinea-Bissau,GNB,2015,1056776896.92865 +Guinea-Bissau,GNB,2016,1126122707.91534 +Guyana,GUY,1960,170215248.206265 +Guyana,GUY,1961,185848451.262906 +Guyana,GUY,1962,194948375.430205 +Guyana,GUY,1963,175756868.692761 +Guyana,GUY,1964,194773376.888526 +Guyana,GUY,1965,213235294.117647 +Guyana,GUY,1966,228705882.352941 +Guyana,GUY,1967,250176470.588235 +Guyana,GUY,1968,229750000 +Guyana,GUY,1969,249300000 +Guyana,GUY,1970,267800000 +Guyana,GUY,1971,282050000 +Guyana,GUY,1972,285380952.380952 +Guyana,GUY,1973,307047619.047619 +Guyana,GUY,1974,433954545.454545 +Guyana,GUY,1975,494791666.666667 +Guyana,GUY,1976,454440000 +Guyana,GUY,1977,449880000 +Guyana,GUY,1978,507080000 +Guyana,GUY,1979,530440000 +Guyana,GUY,1980,603200000 +Guyana,GUY,1981,570357107.142857 +Guyana,GUY,1982,482000000 +Guyana,GUY,1983,489333333.333333 +Guyana,GUY,1984,437631605.263158 +Guyana,GUY,1985,453488372.093023 +Guyana,GUY,1986,504651139.534884 +Guyana,GUY,1987,354591846.938775 +Guyana,GUY,1988,413799990 +Guyana,GUY,1989,379779389.705882 +Guyana,GUY,1990,396582263.291139 +Guyana,GUY,1991,336708419.499106 +Guyana,GUY,1992,368281378.896883 +Guyana,GUY,1993,442273433.179724 +Guyana,GUY,1994,540874934.201012 +Guyana,GUY,1995,621626785.915493 +Guyana,GUY,1996,705406001.424501 +Guyana,GUY,1997,749138009.564539 +Guyana,GUY,1998,717530683.169567 +Guyana,GUY,1999,694754988.258295 +Guyana,GUY,2000,712667896.727512 +Guyana,GUY,2001,696281471.678532 +Guyana,GUY,2002,722460886.371384 +Guyana,GUY,2003,741929342.788749 +Guyana,GUY,2004,785918769.587635 +Guyana,GUY,2005,824880550.343965 +Guyana,GUY,2006,1458446872.26976 +Guyana,GUY,2007,1740334781.83731 +Guyana,GUY,2008,1922598121.23066 +Guyana,GUY,2009,2025565089.48272 +Guyana,GUY,2010,2259288396.24467 +Guyana,GUY,2011,2576602497.33479 +Guyana,GUY,2012,2851154075.95385 +Guyana,GUY,2013,2990006533.77749 +Guyana,GUY,2014,3077086275.94585 +Guyana,GUY,2015,3179104116.22276 +Guyana,GUY,2016,3446266343.82567 +Haiti,HTI,1991,3473562850.25798 +Haiti,HTI,1992,2257129873.66261 +Haiti,HTI,1993,1878253818.07845 +Haiti,HTI,1994,2167569095.11746 +Haiti,HTI,1995,2813313281.80715 +Haiti,HTI,1996,2907517543.3645 +Haiti,HTI,1997,3338949151.59927 +Haiti,HTI,1998,3723903723.63772 +Haiti,HTI,1999,4153725966.87677 +Haiti,HTI,2000,3953839593.78427 +Haiti,HTI,2001,3596448035.44747 +Haiti,HTI,2002,3472194099.40131 +Haiti,HTI,2003,2960306120.93557 +Haiti,HTI,2004,3537721020.41158 +Haiti,HTI,2005,4310356252.83669 +Haiti,HTI,2006,4756204069.61876 +Haiti,HTI,2007,5885321655.91684 +Haiti,HTI,2008,6548530572.35291 +Haiti,HTI,2009,6584649419.28348 +Haiti,HTI,2010,6622541528.56888 +Haiti,HTI,2011,7516834160.25277 +Haiti,HTI,2012,7890216507.68913 +Haiti,HTI,2013,8452509315.87722 +Haiti,HTI,2014,8776360623.29898 +Haiti,HTI,2015,8724656126.49849 +Haiti,HTI,2016,8022638721.92013 +Honduras,HND,1960,335650000 +Honduras,HND,1961,356200000 +Honduras,HND,1962,387750000 +Honduras,HND,1963,410200000 +Honduras,HND,1964,457000000 +Honduras,HND,1965,508650000 +Honduras,HND,1966,549950000 +Honduras,HND,1967,598100000 +Honduras,HND,1968,646800000 +Honduras,HND,1969,668000050 +Honduras,HND,1970,723000000 +Honduras,HND,1971,731000000 +Honduras,HND,1972,802999950 +Honduras,HND,1973,912499950 +Honduras,HND,1974,1034500000 +Honduras,HND,1975,1124000000 +Honduras,HND,1976,1347999950 +Honduras,HND,1977,1669499950 +Honduras,HND,1978,1929499950 +Honduras,HND,1979,2251499950 +Honduras,HND,1980,2566000050 +Honduras,HND,1981,2819500000 +Honduras,HND,1982,2903500050 +Honduras,HND,1983,3076999950 +Honduras,HND,1984,3319000000 +Honduras,HND,1985,3639499950 +Honduras,HND,1986,3808500050 +Honduras,HND,1987,4152499950 +Honduras,HND,1988,3970386266.09442 +Honduras,HND,1989,3563448310.34483 +Honduras,HND,1990,3048881322.9572 +Honduras,HND,1991,3068444711.94538 +Honduras,HND,1992,3419487440.65916 +Honduras,HND,1993,3481990761.34498 +Honduras,HND,1994,3432356578.82219 +Honduras,HND,1995,3911053180.39625 +Honduras,HND,1996,4034037162.16216 +Honduras,HND,1997,4663193916.34981 +Honduras,HND,1998,5202215657.31167 +Honduras,HND,1999,5372543554.00697 +Honduras,HND,2000,7103529494.37412 +Honduras,HND,2001,7565869927.73763 +Honduras,HND,2002,7775078402.92785 +Honduras,HND,2003,8140271080.5604 +Honduras,HND,2004,8772194250.27021 +Honduras,HND,2005,9672035709.39793 +Honduras,HND,2006,10841742347.7968 +Honduras,HND,2007,12275501784.2971 +Honduras,HND,2008,13789715132.502 +Honduras,HND,2009,14587496229.1811 +Honduras,HND,2010,15839344591.9842 +Honduras,HND,2011,17710275997.4437 +Honduras,HND,2012,18528554861.015 +Honduras,HND,2013,18499729063.3889 +Honduras,HND,2014,19756533658.1136 +Honduras,HND,2015,20844308600.8656 +Honduras,HND,2016,21516915352.6217 +"Hong Kong SAR, China",HKG,1960,1320796651.69457 +"Hong Kong SAR, China",HKG,1961,1383681651.13776 +"Hong Kong SAR, China",HKG,1962,1612346412.26475 +"Hong Kong SAR, China",HKG,1963,1935298266.45384 +"Hong Kong SAR, China",HKG,1964,2206466461.26434 +"Hong Kong SAR, China",HKG,1965,2435078534.03141 +"Hong Kong SAR, China",HKG,1966,2489845016.64894 +"Hong Kong SAR, China",HKG,1967,2692474989.12571 +"Hong Kong SAR, China",HKG,1968,2716964388.42418 +"Hong Kong SAR, China",HKG,1969,3189740055.13982 +"Hong Kong SAR, China",HKG,1970,3800766535.62088 +"Hong Kong SAR, China",HKG,1971,4476001946.01486 +"Hong Kong SAR, China",HKG,1972,5710107420.14394 +"Hong Kong SAR, China",HKG,1973,8030117555.62033 +"Hong Kong SAR, China",HKG,1974,9388663645.7588 +"Hong Kong SAR, China",HKG,1975,10048022369.9141 +"Hong Kong SAR, China",HKG,1976,12876366008.8077 +"Hong Kong SAR, China",HKG,1977,15719433719.4337 +"Hong Kong SAR, China",HKG,1978,18315007365.9713 +"Hong Kong SAR, China",HKG,1979,22526035940.5921 +"Hong Kong SAR, China",HKG,1980,28861759209.0191 +"Hong Kong SAR, China",HKG,1981,31055409443.043 +"Hong Kong SAR, China",HKG,1982,32291306281.8168 +"Hong Kong SAR, China",HKG,1983,29907091339.5364 +"Hong Kong SAR, China",HKG,1984,33511383985.6741 +"Hong Kong SAR, China",HKG,1985,35699543050.7778 +"Hong Kong SAR, China",HKG,1986,41075570591.9291 +"Hong Kong SAR, China",HKG,1987,50622571586.1149 +"Hong Kong SAR, China",HKG,1988,59707404560.5944 +"Hong Kong SAR, China",HKG,1989,68790369107.2962 +"Hong Kong SAR, China",HKG,1990,76928290841.8701 +"Hong Kong SAR, China",HKG,1991,88959620135.8864 +"Hong Kong SAR, China",HKG,1992,104272278634.731 +"Hong Kong SAR, China",HKG,1993,120353947980.764 +"Hong Kong SAR, China",HKG,1994,135812069768.646 +"Hong Kong SAR, China",HKG,1995,144652912433.103 +"Hong Kong SAR, China",HKG,1996,159717233621.659 +"Hong Kong SAR, China",HKG,1997,177352785419.977 +"Hong Kong SAR, China",HKG,1998,168886163221.567 +"Hong Kong SAR, China",HKG,1999,165768095391.557 +"Hong Kong SAR, China",HKG,2000,171668164082.555 +"Hong Kong SAR, China",HKG,2001,169403241524.337 +"Hong Kong SAR, China",HKG,2002,166349228737.386 +"Hong Kong SAR, China",HKG,2003,161384522525.299 +"Hong Kong SAR, China",HKG,2004,169099768875.193 +"Hong Kong SAR, China",HKG,2005,181570082162.19 +"Hong Kong SAR, China",HKG,2006,193536265094.364 +"Hong Kong SAR, China",HKG,2007,211597405593.868 +"Hong Kong SAR, China",HKG,2008,219279678430.164 +"Hong Kong SAR, China",HKG,2009,214046415026.187 +"Hong Kong SAR, China",HKG,2010,228637697575.04 +"Hong Kong SAR, China",HKG,2011,248513617677.287 +"Hong Kong SAR, China",HKG,2012,262629441493.476 +"Hong Kong SAR, China",HKG,2013,275696879834.966 +"Hong Kong SAR, China",HKG,2014,291459356985.337 +"Hong Kong SAR, China",HKG,2015,309403880389.071 +"Hong Kong SAR, China",HKG,2016,320912235498.728 +Hungary,HUN,1991,34650782427.2429 +Hungary,HUN,1992,38616036221.8202 +Hungary,HUN,1993,40006243367.539 +Hungary,HUN,1994,43039008829.7659 +Hungary,HUN,1995,46288369007.4588 +Hungary,HUN,1996,46538169511.6894 +Hungary,HUN,1997,47178241568.5704 +Hungary,HUN,1998,48661666395.3691 +Hungary,HUN,1999,49074725337.7458 +Hungary,HUN,2000,47209471853.3471 +Hungary,HUN,2001,53696730223.8318 +Hungary,HUN,2002,67561285378.7259 +Hungary,HUN,2003,85050281601.04 +Hungary,HUN,2004,103694527827.457 +Hungary,HUN,2005,112589039620.207 +Hungary,HUN,2006,114801188269.404 +Hungary,HUN,2007,139198195460.551 +Hungary,HUN,2008,157290970540.917 +Hungary,HUN,2009,129965360575.699 +Hungary,HUN,2010,130255637530.908 +Hungary,HUN,2011,140091591852.976 +Hungary,HUN,2012,127321135030.078 +Hungary,HUN,2013,134680475647.645 +Hungary,HUN,2014,139294565100.565 +Hungary,HUN,2015,121715203207.647 +Hungary,HUN,2016,124342940194.419 +Iceland,ISL,1960,248434096.968726 +Iceland,ISL,1961,253885656.329253 +Iceland,ISL,1962,284916516.159537 +Iceland,ISL,1963,340061650.119898 +Iceland,ISL,1964,434267936.914583 +Iceland,ISL,1965,523694949.370689 +Iceland,ISL,1966,628893310.399926 +Iceland,ISL,1967,621225962.154708 +Iceland,ISL,1968,474399471.622359 +Iceland,ISL,1969,414709311.35296 +Iceland,ISL,1970,531004659.090909 +Iceland,ISL,1971,675722954.545455 +Iceland,ISL,1972,846506911.398142 +Iceland,ISL,1973,1163864529.01365 +Iceland,ISL,1974,1527559579.78989 +Iceland,ISL,1975,1418360312.29668 +Iceland,ISL,1976,1683117417.79656 +Iceland,ISL,1977,2226538693.61895 +Iceland,ISL,1978,2532331673.49047 +Iceland,ISL,1979,2876729410.09643 +Iceland,ISL,1980,3409023699.34967 +Iceland,ISL,1981,3521512388.91504 +Iceland,ISL,1982,3232804218.11116 +Iceland,ISL,1983,2788530415.2511 +Iceland,ISL,1984,2887825523.68452 +Iceland,ISL,1985,3008412959.52317 +Iceland,ISL,1986,4022192403.69597 +Iceland,ISL,1987,5565384032.45323 +Iceland,ISL,1988,6156487920.21202 +Iceland,ISL,1989,5718878001.74609 +Iceland,ISL,1990,6521544489.20626 +Iceland,ISL,1991,6966138525.63635 +Iceland,ISL,1992,7138787995.32199 +Iceland,ISL,1993,6269347502.78093 +Iceland,ISL,1994,6441621297.77366 +Iceland,ISL,1995,7181787873.86945 +Iceland,ISL,1996,7501950115.78947 +Iceland,ISL,1997,7596126045.95208 +Iceland,ISL,1998,8468339855.94356 +Iceland,ISL,1999,8931365460.57043 +Iceland,ISL,2000,8946079678.43696 +Iceland,ISL,2001,8146073989.52626 +Iceland,ISL,2002,9199643907.97902 +Iceland,ISL,2003,11304084266.5137 +Iceland,ISL,2004,13703315349.2507 +Iceland,ISL,2005,16691213479.471 +Iceland,ISL,2006,17043245939.014 +Iceland,ISL,2007,21295012098.9774 +Iceland,ISL,2008,17640375722.4448 +Iceland,ISL,2009,12887072301.1621 +Iceland,ISL,2010,13254818331.1893 +Iceland,ISL,2011,14674650434.6757 +Iceland,ISL,2012,14218575093.024 +Iceland,ISL,2013,15479256844.8708 +Iceland,ISL,2014,17178962757.4324 +Iceland,ISL,2015,16783714958.4498 +Iceland,ISL,2016,20047413006.3471 +India,IND,1960,36535925031.34 +India,IND,1961,38709096075.6305 +India,IND,1962,41599070242.3094 +India,IND,1963,47776000900.0302 +India,IND,1964,55726873083.5543 +India,IND,1965,58760424669.8482 +India,IND,1966,45253641303.1897 +India,IND,1967,49466168890.9507 +India,IND,1968,52377324284.1951 +India,IND,1969,57668330026.3629 +India,IND,1970,61589800519.5084 +India,IND,1971,66452561865.8332 +India,IND,1972,70509913049.4003 +India,IND,1973,84374541630.2062 +India,IND,1974,98198276856.6209 +India,IND,1975,97159222024.1364 +India,IND,1976,101346972433.934 +India,IND,1977,119866746574.408 +India,IND,1978,135468782808.69 +India,IND,1979,150950826964.424 +India,IND,1980,183839864649.15 +India,IND,1981,190909548789.769 +India,IND,1982,198037712681.605 +India,IND,1983,215350771428.331 +India,IND,1984,209328156800.867 +India,IND,1985,229410293759.071 +India,IND,1986,245664654062.873 +India,IND,1987,275311425331.64 +India,IND,1988,292632656262.687 +India,IND,1989,292093308319.642 +India,IND,1990,316697337894.513 +India,IND,1991,266502281094.117 +India,IND,1992,284363884080.101 +India,IND,1993,275570363431.902 +India,IND,1994,322909902308.892 +India,IND,1995,355475984177.451 +India,IND,1996,387656017798.596 +India,IND,1997,410320300470.283 +India,IND,1998,415730874171.13 +India,IND,1999,452699998386.914 +India,IND,2000,462146799337.698 +India,IND,2001,478965491060.771 +India,IND,2002,508068952065.901 +India,IND,2003,599592902016.345 +India,IND,2004,699688852930.276 +India,IND,2005,808901077222.839 +India,IND,2006,920316529729.747 +India,IND,2007,1201111768410.27 +India,IND,2008,1186952757636.11 +India,IND,2009,1323940295874.06 +India,IND,2010,1656617073124.71 +India,IND,2011,1823049927772.05 +India,IND,2012,1827637859136.23 +India,IND,2013,1856722121394.42 +India,IND,2014,2035393459980.06 +India,IND,2015,2111751098184.5 +India,IND,2016,2263522518124.03 +Indonesia,IDN,1967,5667756644.83099 +Indonesia,IDN,1968,7076465295.33327 +Indonesia,IDN,1969,8337423312.88344 +Indonesia,IDN,1970,9150684931.50685 +Indonesia,IDN,1971,9333536359.79807 +Indonesia,IDN,1972,10997590361.4458 +Indonesia,IDN,1973,16273253012.0482 +Indonesia,IDN,1974,25802409638.5542 +Indonesia,IDN,1975,30463855421.6867 +Indonesia,IDN,1976,37269156626.506 +Indonesia,IDN,1977,45808915662.6506 +Indonesia,IDN,1978,51455719099.9244 +Indonesia,IDN,1979,51400186379.3033 +Indonesia,IDN,1980,72482337370.3493 +Indonesia,IDN,1981,85518233450.774 +Indonesia,IDN,1982,90158449307.2387 +Indonesia,IDN,1983,81052283404.6079 +Indonesia,IDN,1984,84853699994.0508 +Indonesia,IDN,1985,85289491750.3225 +Indonesia,IDN,1986,79954072569.8533 +Indonesia,IDN,1987,75929617576.8776 +Indonesia,IDN,1988,84300174477.2018 +Indonesia,IDN,1989,94451427898.3405 +Indonesia,IDN,1990,106140727357.035 +Indonesia,IDN,1991,116621996217.133 +Indonesia,IDN,1992,128026966579.964 +Indonesia,IDN,1993,158006700301.533 +Indonesia,IDN,1994,176892143931.505 +Indonesia,IDN,1995,202132028723.115 +Indonesia,IDN,1996,227369679374.973 +Indonesia,IDN,1997,215748998609.635 +Indonesia,IDN,1998,95445547872.715 +Indonesia,IDN,1999,140001351215.462 +Indonesia,IDN,2000,165021012077.81 +Indonesia,IDN,2001,160446947784.909 +Indonesia,IDN,2002,195660611165.183 +Indonesia,IDN,2003,234772463823.808 +Indonesia,IDN,2004,256836875295.452 +Indonesia,IDN,2005,285868618224.017 +Indonesia,IDN,2006,364570514304.85 +Indonesia,IDN,2007,432216737774.861 +Indonesia,IDN,2008,510228635279.289 +Indonesia,IDN,2009,539580088908.138 +Indonesia,IDN,2010,755094160363.071 +Indonesia,IDN,2011,892969107923.094 +Indonesia,IDN,2012,917869910105.749 +Indonesia,IDN,2013,912524136718.018 +Indonesia,IDN,2014,890814755233.225 +Indonesia,IDN,2015,861256351277.359 +Indonesia,IDN,2016,932259177765.307 +"Iran, Islamic Rep.",IRN,1960,4199134389.43894 +"Iran, Islamic Rep.",IRN,1961,4426949094.38944 +"Iran, Islamic Rep.",IRN,1962,4693566415.84158 +"Iran, Islamic Rep.",IRN,1963,4928628018.48185 +"Iran, Islamic Rep.",IRN,1964,5379845647.52475 +"Iran, Islamic Rep.",IRN,1965,6197319928.71287 +"Iran, Islamic Rep.",IRN,1966,6789938671.9472 +"Iran, Islamic Rep.",IRN,1967,7555383689.76898 +"Iran, Islamic Rep.",IRN,1968,8623172959.73597 +"Iran, Islamic Rep.",IRN,1969,9743089607.92079 +"Iran, Islamic Rep.",IRN,1970,10976245153.7954 +"Iran, Islamic Rep.",IRN,1971,13731801564.3564 +"Iran, Islamic Rep.",IRN,1972,17153463263.3663 +"Iran, Islamic Rep.",IRN,1973,27081698249.1798 +"Iran, Islamic Rep.",IRN,1974,46209092072.4584 +"Iran, Islamic Rep.",IRN,1975,51776222349.8518 +"Iran, Islamic Rep.",IRN,1976,68055295080.4565 +"Iran, Islamic Rep.",IRN,1977,80600122702.2202 +"Iran, Islamic Rep.",IRN,1978,77994316621.497 +"Iran, Islamic Rep.",IRN,1979,90391877325.2927 +"Iran, Islamic Rep.",IRN,1980,94362275579.4621 +"Iran, Islamic Rep.",IRN,1981,100499312749.447 +"Iran, Islamic Rep.",IRN,1982,125948756439.161 +"Iran, Islamic Rep.",IRN,1983,156365156618.288 +"Iran, Islamic Rep.",IRN,1984,162276728619.617 +"Iran, Islamic Rep.",IRN,1985,180183629600.036 +"Iran, Islamic Rep.",IRN,1986,209094561834.095 +"Iran, Islamic Rep.",IRN,1987,134009995922.987 +"Iran, Islamic Rep.",IRN,1988,123057861333.933 +"Iran, Islamic Rep.",IRN,1989,120496362916.372 +"Iran, Islamic Rep.",IRN,1990,124813263926.374 +"Iran, Islamic Rep.",IRN,1993,63743623232.012 +"Iran, Islamic Rep.",IRN,1994,71841461172.5964 +"Iran, Islamic Rep.",IRN,1995,96419225743.6737 +"Iran, Islamic Rep.",IRN,1996,120403931885.441 +"Iran, Islamic Rep.",IRN,1997,113919163421.155 +"Iran, Islamic Rep.",IRN,1998,110276913362.508 +"Iran, Islamic Rep.",IRN,1999,113848450088.351 +"Iran, Islamic Rep.",IRN,2000,109591707802.216 +"Iran, Islamic Rep.",IRN,2001,126878750295.944 +"Iran, Islamic Rep.",IRN,2002,128626917503.72 +"Iran, Islamic Rep.",IRN,2003,153544751395.43 +"Iran, Islamic Rep.",IRN,2004,183697185041.72 +"Iran, Islamic Rep.",IRN,2005,219845971945.264 +"Iran, Islamic Rep.",IRN,2006,258645743978.386 +"Iran, Islamic Rep.",IRN,2007,337474485087.271 +"Iran, Islamic Rep.",IRN,2008,397189565318.895 +"Iran, Islamic Rep.",IRN,2009,398978104575.331 +"Iran, Islamic Rep.",IRN,2010,467790215915.476 +"Iran, Islamic Rep.",IRN,2011,592037800186.865 +"Iran, Islamic Rep.",IRN,2012,587209369682.67 +"Iran, Islamic Rep.",IRN,2013,511620875086.78 +"Iran, Islamic Rep.",IRN,2014,425326068422.881 +"Iran, Islamic Rep.",IRN,2015,393436064441.692 +Iraq,IRQ,1960,1684121534.58415 +Iraq,IRQ,1961,1831700364.04369 +Iraq,IRQ,1962,1954634836.18034 +Iraq,IRQ,1963,1978437692.5231 +Iraq,IRQ,1964,2340521142.5371 +Iraq,IRQ,1968,2896947633.71605 +Iraq,IRQ,1969,3008120974.51694 +Iraq,IRQ,1970,3281713805.65668 +Iraq,IRQ,1971,3865346534.65347 +Iraq,IRQ,1972,4113848002.40312 +Iraq,IRQ,1973,5134367778.1446 +Iraq,IRQ,1974,11516762614.2906 +Iraq,IRQ,1975,13458516762.6143 +Iraq,IRQ,1976,17754825601.0836 +Iraq,IRQ,1977,19838130714.5276 +Iraq,IRQ,1978,23762275651.8794 +Iraq,IRQ,1979,37816457839.4853 +Iraq,IRQ,1980,53405689129.6986 +Iraq,IRQ,1981,38424991534.0332 +Iraq,IRQ,1982,42595309882.7471 +Iraq,IRQ,1983,40595046638.7906 +Iraq,IRQ,1984,46802508845.2879 +Iraq,IRQ,1985,48284979092.9559 +Iraq,IRQ,1986,47127693792.2161 +Iraq,IRQ,1987,56609842393.0524 +Iraq,IRQ,1988,62503055644.9019 +Iraq,IRQ,1989,65641363782.5668 +Iraq,IRQ,1990,179885815374.719 +Iraq,IRQ,2004,36627901762.063 +Iraq,IRQ,2005,49954890353.2609 +Iraq,IRQ,2006,65140293687.5395 +Iraq,IRQ,2007,88840050497.0957 +Iraq,IRQ,2008,131613661510.475 +Iraq,IRQ,2009,111660855042.735 +Iraq,IRQ,2010,138516722649.573 +Iraq,IRQ,2011,185749664444.444 +Iraq,IRQ,2012,218000986222.639 +Iraq,IRQ,2013,234648370497.427 +Iraq,IRQ,2014,234648370497.427 +Iraq,IRQ,2015,179640210726.448 +Iraq,IRQ,2016,171489001692.047 +Ireland,IRL,1960,1939329775.43739 +Ireland,IRL,1961,2088012282.35667 +Ireland,IRL,1962,2260349684.08625 +Ireland,IRL,1963,2430843768.44553 +Ireland,IRL,1964,2766608945.87402 +Ireland,IRL,1965,2945704142.99765 +Ireland,IRL,1966,3104034393.23162 +Ireland,IRL,1967,3343636773.36759 +Ireland,IRL,1968,3278584478.33023 +Ireland,IRL,1969,3787077343.72783 +Ireland,IRL,1970,4400344547.34455 +Ireland,IRL,1971,5103293982.36872 +Ireland,IRL,1972,6324312352.47836 +Ireland,IRL,1973,7488574956.58885 +Ireland,IRL,1974,7904673172.52808 +Ireland,IRL,1975,9493191637.63066 +Ireland,IRL,1976,9463110246.24965 +Ireland,IRL,1977,11259469295.2329 +Ireland,IRL,1978,14662488976.1401 +Ireland,IRL,1979,18337460025.7898 +Ireland,IRL,1980,21769374170.5778 +Ireland,IRL,1981,20690641399.4169 +Ireland,IRL,1982,21496001229.5998 +Ireland,IRL,1983,20786594499.3638 +Ireland,IRL,1984,20126542854.7038 +Ireland,IRL,1985,21291058299.3254 +Ireland,IRL,1986,28742982513.777 +Ireland,IRL,1987,33954080524.3446 +Ireland,IRL,1988,37810270545.8908 +Ireland,IRL,1989,39277216207.166 +Ireland,IRL,1990,49354416568.9723 +Ireland,IRL,1991,49836763468.1202 +Ireland,IRL,1992,55973865067.6672 +Ireland,IRL,1993,52469340621.0024 +Ireland,IRL,1994,57154150176.6784 +Ireland,IRL,1995,69208232323.2323 +Ireland,IRL,1996,75864982358.871 +Ireland,IRL,1997,82816774116.5234 +Ireland,IRL,1998,90111618257.2614 +Ireland,IRL,1999,98781557639.0369 +Ireland,IRL,2000,99855067256.3111 +Ireland,IRL,2001,109119123042.506 +Ireland,IRL,2002,127941699604.743 +Ireland,IRL,2003,164285609480.813 +Ireland,IRL,2004,193870908865.16 +Ireland,IRL,2005,211684827757.742 +Ireland,IRL,2006,232167519759.127 +Ireland,IRL,2007,270043019436.08 +Ireland,IRL,2008,274919027391.241 +Ireland,IRL,2009,235765976660.183 +Ireland,IRL,2010,221343483668.837 +Ireland,IRL,2011,240590736123.315 +Ireland,IRL,2012,225819189160.686 +Ireland,IRL,2013,239271158532.518 +Ireland,IRL,2014,256271345442.586 +Ireland,IRL,2015,283716006697.636 +Ireland,IRL,2016,294053595685.717 +Isle of Man,IMN,1995,914727080.643268 +Isle of Man,IMN,1996,1023086918.62768 +Isle of Man,IMN,1997,1180919719.40764 +Isle of Man,IMN,1998,1382548249.78303 +Isle of Man,IMN,1999,1567465656.8505 +Isle of Man,IMN,2000,1563667799.61578 +Isle of Man,IMN,2001,1614595290.9182 +Isle of Man,IMN,2002,1897606791.43353 +Isle of Man,IMN,2003,2264911806.90354 +Isle of Man,IMN,2004,2758117365.04863 +Isle of Man,IMN,2005,2971167185.35511 +Isle of Man,IMN,2006,3344402193.24608 +Isle of Man,IMN,2007,5685988395.35814 +Isle of Man,IMN,2008,5827468750 +Isle of Man,IMN,2009,5047909331.6716 +Isle of Man,IMN,2010,5420118974.04203 +Isle of Man,IMN,2011,6066454093.89521 +Isle of Man,IMN,2012,6433357030.0158 +Isle of Man,IMN,2013,6754330154.76004 +Isle of Man,IMN,2014,7428280401.5139 +Israel,ISR,1960,2598500000 +Israel,ISR,1961,3138500000 +Israel,ISR,1962,2510000000 +Israel,ISR,1963,2992333333.33333 +Israel,ISR,1964,3405333333.33333 +Israel,ISR,1965,3663333333.33333 +Israel,ISR,1966,3980000000 +Israel,ISR,1967,4030000000 +Israel,ISR,1968,4619000000 +Israel,ISR,1969,5329333333.33333 +Israel,ISR,1970,6267666666.66667 +Israel,ISR,1971,5851750000 +Israel,ISR,1972,7496250000 +Israel,ISR,1973,9692000000 +Israel,ISR,1974,13986250000 +Israel,ISR,1975,13028166666.6667 +Israel,ISR,1976,12359875000 +Israel,ISR,1977,14390000000 +Israel,ISR,1978,13967647058.8235 +Israel,ISR,1979,17796000000 +Israel,ISR,1980,21884705882.3529 +Israel,ISR,1981,23258596491.2281 +Israel,ISR,1982,24539341563.786 +Israel,ISR,1983,27442580071.1744 +Israel,ISR,1984,26043655184.1746 +Israel,ISR,1985,24121638985.495 +Israel,ISR,1986,29702243917.1932 +Israel,ISR,1987,35477234541.5778 +Israel,ISR,1988,43893303708.7998 +Israel,ISR,1989,44599771759.5491 +Israel,ISR,1990,52490327348.4773 +Israel,ISR,1991,59170286560.4844 +Israel,ISR,1992,65771216420.6417 +Israel,ISR,1993,65925583866.2945 +Israel,ISR,1994,74669719504.5 +Israel,ISR,1995,99968784246.0067 +Israel,ISR,1996,109774101575.963 +Israel,ISR,1997,114543978662.956 +Israel,ISR,1998,115838004263.046 +Israel,ISR,1999,117212358383.458 +Israel,ISR,2000,132396684080.151 +Israel,ISR,2001,130751599020.377 +Israel,ISR,2002,121092701253.746 +Israel,ISR,2003,126749741990.734 +Israel,ISR,2004,135418563141.455 +Israel,ISR,2005,142837533703.233 +Israel,ISR,2006,154511423313.434 +Israel,ISR,2007,179564275455.807 +Israel,ISR,2008,216760312151.616 +Israel,ISR,2009,208068814688.605 +Israel,ISR,2010,233754747258.625 +Israel,ISR,2011,261374751963.332 +Israel,ISR,2012,257641795689.722 +Israel,ISR,2013,293314777888.557 +Israel,ISR,2014,308769389865.564 +Israel,ISR,2015,299415714726.768 +Israel,ISR,2016,318743685882.414 +Italy,ITA,1960,40385288344.1911 +Italy,ITA,1961,44842760293.1924 +Italy,ITA,1962,50383891898.9911 +Italy,ITA,1963,57710743059.8341 +Italy,ITA,1964,63175417019.0094 +Italy,ITA,1965,67978153850.5191 +Italy,ITA,1966,73654870011.2757 +Italy,ITA,1967,81133120065.4202 +Italy,ITA,1968,87942231678.3505 +Italy,ITA,1969,97085082807.3751 +Italy,ITA,1970,113021272614.622 +Italy,ITA,1971,124261125780.275 +Italy,ITA,1972,144780888114.21 +Italy,ITA,1973,174913182995.683 +Italy,ITA,1974,198906211372.432 +Italy,ITA,1975,226944778173.191 +Italy,ITA,1976,223976031867.876 +Italy,ITA,1977,256746611586.57 +Italy,ITA,1978,314019079397.673 +Italy,ITA,1979,392378586343.51 +Italy,ITA,1980,475682508026.227 +Italy,ITA,1981,429282144779.424 +Italy,ITA,1982,425863253400.143 +Italy,ITA,1983,441580964558.899 +Italy,ITA,1984,436443282455.367 +Italy,ITA,1985,450725817665.551 +Italy,ITA,1986,638273988310.17 +Italy,ITA,1987,803055421720.944 +Italy,ITA,1988,888667916542.696 +Italy,ITA,1989,925598071408.411 +Italy,ITA,1990,1177326298642.53 +Italy,ITA,1991,1242109402060.25 +Italy,ITA,1992,1315806990573.45 +Italy,ITA,1993,1061445229481.97 +Italy,ITA,1994,1095590837536.02 +Italy,ITA,1995,1170787357066.44 +Italy,ITA,1996,1308929305684.53 +Italy,ITA,1997,1239050936221.01 +Italy,ITA,1998,1266309223820.68 +Italy,ITA,1999,1248563148945.24 +Italy,ITA,2000,1141760021927.4 +Italy,ITA,2001,1162317840447.43 +Italy,ITA,2002,1266510668642.95 +Italy,ITA,2003,1569649631715.58 +Italy,ITA,2004,1798314755525.2 +Italy,ITA,2005,1852661936077.6 +Italy,ITA,2006,1942633841801.53 +Italy,ITA,2007,2203053327128.39 +Italy,ITA,2008,2390729210487.77 +Italy,ITA,2009,2185160158794.11 +Italy,ITA,2010,2125058270201.64 +Italy,ITA,2011,2276292459232.78 +Italy,ITA,2012,2072823111961.1 +Italy,ITA,2013,2130491269673.44 +Italy,ITA,2014,2151732834411.5 +Italy,ITA,2015,1824902219021.73 +Italy,ITA,2016,1849970464191.78 +Jamaica,JAM,1960,699050678.98642 +Jamaica,JAM,1961,748028839.423211 +Jamaica,JAM,1962,777712445.751085 +Jamaica,JAM,1963,826690466.190676 +Jamaica,JAM,1964,897931401.371972 +Jamaica,JAM,1965,972140557.188856 +Jamaica,JAM,1966,1096738065.2387 +Jamaica,JAM,1967,1148025407.34604 +Jamaica,JAM,1968,1083883355.33421 +Jamaica,JAM,1969,1191287651.50606 +Jamaica,JAM,1970,1404776071.04284 +Jamaica,JAM,1971,1539865513.92891 +Jamaica,JAM,1972,1875048859.93485 +Jamaica,JAM,1973,1905917553.19149 +Jamaica,JAM,1974,2375096249.03751 +Jamaica,JAM,1975,2860411285.88714 +Jamaica,JAM,1976,2966010229.8977 +Jamaica,JAM,1977,3249697393.02607 +Jamaica,JAM,1978,2644449232.29321 +Jamaica,JAM,1979,2425033998.18676 +Jamaica,JAM,1980,2679409453.23903 +Jamaica,JAM,1981,2979061412.37229 +Jamaica,JAM,1982,3293533288.42483 +Jamaica,JAM,1983,3619294120.69144 +Jamaica,JAM,1984,2373566957.49214 +Jamaica,JAM,1985,2100223149.71396 +Jamaica,JAM,1986,2754566176.20212 +Jamaica,JAM,1987,3286987551.71597 +Jamaica,JAM,1988,3828310734.97795 +Jamaica,JAM,1989,4404970058.83786 +Jamaica,JAM,1990,4592224067.37194 +Jamaica,JAM,1991,4071219198.03601 +Jamaica,JAM,1992,3530892749.02131 +Jamaica,JAM,1993,4859766160.89207 +Jamaica,JAM,1994,4907861405.82758 +Jamaica,JAM,1995,5779285207.92079 +Jamaica,JAM,1996,6504445801.34228 +Jamaica,JAM,1997,7450324787.38384 +Jamaica,JAM,1998,8718300136.42565 +Jamaica,JAM,1999,8795765306.12245 +Jamaica,JAM,2000,8929375580.31569 +Jamaica,JAM,2001,9087918836.80556 +Jamaica,JAM,2002,9694161516.27524 +Jamaica,JAM,2003,9399452787.8474 +Jamaica,JAM,2004,10150978154.5484 +Jamaica,JAM,2005,11204416000 +Jamaica,JAM,2006,11905525197.3285 +Jamaica,JAM,2007,12824094989.8639 +Jamaica,JAM,2008,13678551837.6303 +Jamaica,JAM,2009,12038998756.9217 +Jamaica,JAM,2010,13192229343.0991 +Jamaica,JAM,2011,14440457548.68 +Jamaica,JAM,2012,14802430172.5391 +Jamaica,JAM,2013,14276559215.7309 +Jamaica,JAM,2014,13897561173.4853 +Jamaica,JAM,2015,14261995113.6721 +Jamaica,JAM,2016,14027151472.7053 +Japan,JPN,1960,44307342950.4 +Japan,JPN,1961,53508617739.3778 +Japan,JPN,1962,60723018683.7333 +Japan,JPN,1963,69498131797.3333 +Japan,JPN,1964,81749006381.5111 +Japan,JPN,1965,90950278257.7778 +Japan,JPN,1966,105628070343.111 +Japan,JPN,1967,123781880217.6 +Japan,JPN,1968,146601072685.511 +Japan,JPN,1969,172204199480.889 +Japan,JPN,1970,211514189326.389 +Japan,JPN,1971,238914956436.922 +Japan,JPN,1972,316393344649.993 +Japan,JPN,1973,429857320166.565 +Japan,JPN,1974,477155786487.722 +Japan,JPN,1975,518855814542.728 +Japan,JPN,1976,583142956487.974 +Japan,JPN,1977,717696307916.651 +Japan,JPN,1978,1008391778690.25 +Japan,JPN,1979,1049578503045.09 +Japan,JPN,1980,1099692917412.75 +Japan,JPN,1981,1215508719880.85 +Japan,JPN,1982,1129894523635.09 +Japan,JPN,1983,1232343804284.17 +Japan,JPN,1984,1309740021609.74 +Japan,JPN,1985,1400714806812.65 +Japan,JPN,1986,2075034242192.31 +Japan,JPN,1987,2514283894261.86 +Japan,JPN,1988,3050637784817.52 +Japan,JPN,1989,3052315661954.82 +Japan,JPN,1990,3139974443543 +Japan,JPN,1991,3578139437172.02 +Japan,JPN,1992,3897826229662.86 +Japan,JPN,1993,4466565327401.26 +Japan,JPN,1994,4907039384469.68 +Japan,JPN,1995,5449116304981.1 +Japan,JPN,1996,4833712542207.1 +Japan,JPN,1997,4414732843544.43 +Japan,JPN,1998,4032509760872.94 +Japan,JPN,1999,4562078822335.45 +Japan,JPN,2000,4887519660744.86 +Japan,JPN,2001,4303544259842.72 +Japan,JPN,2002,4115116279069.77 +Japan,JPN,2003,4445658071221.86 +Japan,JPN,2004,4815148854362.11 +Japan,JPN,2005,4755410630912.14 +Japan,JPN,2006,4530377224970.4 +Japan,JPN,2007,4515264514430.57 +Japan,JPN,2008,5037908465114.48 +Japan,JPN,2009,5231382674593.7 +Japan,JPN,2010,5700098114744.41 +Japan,JPN,2011,6157459594823.72 +Japan,JPN,2012,6203213121334.12 +Japan,JPN,2013,5155717056270.83 +Japan,JPN,2014,4848733415523.53 +Japan,JPN,2015,4383076298081.86 +Japan,JPN,2016,4939383909875.27 +Jordan,JOR,1965,599831979.837581 +Jordan,JOR,1966,658078969.476337 +Jordan,JOR,1967,631755810.697284 +Jordan,JOR,1968,561187342.481098 +Jordan,JOR,1969,698963875.66508 +Jordan,JOR,1970,639596751.610193 +Jordan,JOR,1971,678241388.966676 +Jordan,JOR,1972,788574628.955475 +Jordan,JOR,1973,943700547.778454 +Jordan,JOR,1974,1197454206.76808 +Jordan,JOR,1975,1363039399.62477 +Jordan,JOR,1976,1708734939.75904 +Jordan,JOR,1977,2096568478.59095 +Jordan,JOR,1978,2602748691.09948 +Jordan,JOR,1979,3271728271.72827 +Jordan,JOR,1980,3910036925.14267 +Jordan,JOR,1981,4384685230.02421 +Jordan,JOR,1982,4680567375.88653 +Jordan,JOR,1983,4920407601.21179 +Jordan,JOR,1984,4966710013.0039 +Jordan,JOR,1985,4993829194.12063 +Jordan,JOR,1986,6401380000 +Jordan,JOR,1987,6755599113.73707 +Jordan,JOR,1988,6277197435.2124 +Jordan,JOR,1989,4220945005.22102 +Jordan,JOR,1990,4160003917.43258 +Jordan,JOR,1991,4344250257.01278 +Jordan,JOR,1992,5311329067.37276 +Jordan,JOR,1993,5605841535.57512 +Jordan,JOR,1994,6237739516.24445 +Jordan,JOR,1995,6727446632.42009 +Jordan,JOR,1996,6928359238.36389 +Jordan,JOR,1997,7246188575.45839 +Jordan,JOR,1998,7912327362.48237 +Jordan,JOR,1999,8149106064.88011 +Jordan,JOR,2000,8460424400.56418 +Jordan,JOR,2001,8975689844.8519 +Jordan,JOR,2002,9582453032.44006 +Jordan,JOR,2003,10195660789.8449 +Jordan,JOR,2004,11411390409.0268 +Jordan,JOR,2005,12588665303.244 +Jordan,JOR,2006,15056929760.2257 +Jordan,JOR,2007,17110587447.1086 +Jordan,JOR,2008,21972004086.2336 +Jordan,JOR,2009,23820230000 +Jordan,JOR,2010,26425379436.6197 +Jordan,JOR,2011,28840263380.2817 +Jordan,JOR,2012,30937277605.6338 +Jordan,JOR,2013,33593843661.9718 +Jordan,JOR,2014,35826925774.6479 +Jordan,JOR,2015,37517410281.6901 +Jordan,JOR,2016,38654727746.4789 +Kazakhstan,KAZ,1990,26932728898.8146 +Kazakhstan,KAZ,1991,24881135586.399 +Kazakhstan,KAZ,1992,24906939560.1098 +Kazakhstan,KAZ,1993,23409027475.6879 +Kazakhstan,KAZ,1994,21250839258.0901 +Kazakhstan,KAZ,1995,20374307047.115 +Kazakhstan,KAZ,1996,21035357832.8019 +Kazakhstan,KAZ,1997,22165932062.966 +Kazakhstan,KAZ,1998,22135245413.2312 +Kazakhstan,KAZ,1999,16870817134.7767 +Kazakhstan,KAZ,2000,18291990619.137 +Kazakhstan,KAZ,2001,22152689129.5583 +Kazakhstan,KAZ,2002,24636598581.0204 +Kazakhstan,KAZ,2003,30833692831.3955 +Kazakhstan,KAZ,2004,43151647002.6096 +Kazakhstan,KAZ,2005,57123671733.8952 +Kazakhstan,KAZ,2006,81003884545.4099 +Kazakhstan,KAZ,2007,104849886825.584 +Kazakhstan,KAZ,2008,133441612246.798 +Kazakhstan,KAZ,2009,115308661142.927 +Kazakhstan,KAZ,2010,148047348240.643 +Kazakhstan,KAZ,2011,192626507971.584 +Kazakhstan,KAZ,2012,207998568865.789 +Kazakhstan,KAZ,2013,236634552078.102 +Kazakhstan,KAZ,2014,221415572819.5 +Kazakhstan,KAZ,2015,184388432148.715 +Kazakhstan,KAZ,2016,133657084404.957 +Kenya,KEN,1960,791265458.813328 +Kenya,KEN,1961,792959472.134266 +Kenya,KEN,1962,868111400.008864 +Kenya,KEN,1963,926589348.567393 +Kenya,KEN,1964,998759333.637333 +Kenya,KEN,1965,997919319.974061 +Kenya,KEN,1966,1164519673.19064 +Kenya,KEN,1967,1232559505.9162 +Kenya,KEN,1968,1353295457.51798 +Kenya,KEN,1969,1458379415.39403 +Kenya,KEN,1970,1603447357.24209 +Kenya,KEN,1971,1778391289.20054 +Kenya,KEN,1972,2107279157.38336 +Kenya,KEN,1973,2502142444.14182 +Kenya,KEN,1974,2973309272.02986 +Kenya,KEN,1975,3259344935.75357 +Kenya,KEN,1976,3474542392.04597 +Kenya,KEN,1977,4494378855.32203 +Kenya,KEN,1978,5303734882.51159 +Kenya,KEN,1979,6234390975.29871 +Kenya,KEN,1980,7265315331.62273 +Kenya,KEN,1981,6854491453.91471 +Kenya,KEN,1982,6431579357.30273 +Kenya,KEN,1983,5979198463.82274 +Kenya,KEN,1984,6191437070.43467 +Kenya,KEN,1985,6135034338.30431 +Kenya,KEN,1986,7239126716.93219 +Kenya,KEN,1987,7970820530.76691 +Kenya,KEN,1988,8355380879.12955 +Kenya,KEN,1989,8283114648.38116 +Kenya,KEN,1990,8572359162.86876 +Kenya,KEN,1991,8151479004.21334 +Kenya,KEN,1992,8209129171.73649 +Kenya,KEN,1993,5751789915.05363 +Kenya,KEN,1994,7148145375.78545 +Kenya,KEN,1995,9046326059.98857 +Kenya,KEN,1996,12045858436.2399 +Kenya,KEN,1997,13115773737.5664 +Kenya,KEN,1998,14093998843.7334 +Kenya,KEN,1999,12896013576.7324 +Kenya,KEN,2000,12705357103.0056 +Kenya,KEN,2001,12986007425.8781 +Kenya,KEN,2002,13147743910.7241 +Kenya,KEN,2003,14904517649.8476 +Kenya,KEN,2004,16095337093.8366 +Kenya,KEN,2005,18737897744.7948 +Kenya,KEN,2006,25825524820.8064 +Kenya,KEN,2007,31958195182.2406 +Kenya,KEN,2008,35895153327.8497 +Kenya,KEN,2009,37021512048.8158 +Kenya,KEN,2010,39999659233.7555 +Kenya,KEN,2011,41953433591.4101 +Kenya,KEN,2012,50412754821.9795 +Kenya,KEN,2013,55097343447.5616 +Kenya,KEN,2014,61445345999.0765 +Kenya,KEN,2015,63767539356.6051 +Kenya,KEN,2016,70529014778.3251 +Kiribati,KIR,1970,14295279.5446937 +Kiribati,KIR,1971,15278632.4786325 +Kiribati,KIR,1972,18936526.9461078 +Kiribati,KIR,1973,31710657.7257811 +Kiribati,KIR,1974,85637174.3722131 +Kiribati,KIR,1975,55081816.9917528 +Kiribati,KIR,1976,41109617.4996945 +Kiribati,KIR,1977,38748059.4366822 +Kiribati,KIR,1978,45210026.3248255 +Kiribati,KIR,1979,42620165.4370668 +Kiribati,KIR,1980,38715554.5433842 +Kiribati,KIR,1981,41369800.0459664 +Kiribati,KIR,1982,40572066.1324678 +Kiribati,KIR,1983,37837837.8378378 +Kiribati,KIR,1984,41246160.596753 +Kiribati,KIR,1985,32125148.4042182 +Kiribati,KIR,1986,32085561.4973262 +Kiribati,KIR,1987,33608738.2719507 +Kiribati,KIR,1988,42972107.1958747 +Kiribati,KIR,1989,41119721.651115 +Kiribati,KIR,1990,39809538.6776989 +Kiribati,KIR,1991,47515189.2818196 +Kiribati,KIR,1992,47737955.346651 +Kiribati,KIR,1993,46919624.6430029 +Kiribati,KIR,1994,54832577.8622606 +Kiribati,KIR,1995,56338028.1690141 +Kiribati,KIR,1996,66515376.7900462 +Kiribati,KIR,1997,67537479.5903221 +Kiribati,KIR,1998,65334841.0604347 +Kiribati,KIR,1999,69032258.0645161 +Kiribati,KIR,2000,67254174.3970315 +Kiribati,KIR,2001,63101272.3699183 +Kiribati,KIR,2002,72196457.6768445 +Kiribati,KIR,2003,90231856.8000519 +Kiribati,KIR,2004,102367039.270481 +Kiribati,KIR,2005,112133944.253532 +Kiribati,KIR,2006,108545632.53012 +Kiribati,KIR,2007,130754915.906619 +Kiribati,KIR,2008,139125482.301627 +Kiribati,KIR,2009,130465372.016846 +Kiribati,KIR,2010,153275912.676573 +Kiribati,KIR,2011,177142135.121196 +Kiribati,KIR,2012,188045661.627666 +Kiribati,KIR,2013,187153601.08129 +Kiribati,KIR,2014,186066973.138634 +Kiribati,KIR,2015,160121929.231463 +Kiribati,KIR,2016,165765016.354445 +"Korea, Rep.",KOR,1960,3957873925.93719 +"Korea, Rep.",KOR,1961,2417237753.94419 +"Korea, Rep.",KOR,1962,2813933899.74577 +"Korea, Rep.",KOR,1963,3988246108.63888 +"Korea, Rep.",KOR,1964,3458518493.92483 +"Korea, Rep.",KOR,1965,3120307807.80781 +"Korea, Rep.",KOR,1966,3928171298.00251 +"Korea, Rep.",KOR,1967,4854576371.4328 +"Korea, Rep.",KOR,1968,6117260075.90819 +"Korea, Rep.",KOR,1969,7675805108.27318 +"Korea, Rep.",KOR,1970,8999227202.47295 +"Korea, Rep.",KOR,1971,9889961111.91128 +"Korea, Rep.",KOR,1972,10842220468.8335 +"Korea, Rep.",KOR,1973,13841885920.8676 +"Korea, Rep.",KOR,1974,19482038222.8595 +"Korea, Rep.",KOR,1975,21704752066.1157 +"Korea, Rep.",KOR,1976,29779338842.9752 +"Korea, Rep.",KOR,1977,38265082644.6281 +"Korea, Rep.",KOR,1978,51700619834.7107 +"Korea, Rep.",KOR,1979,66567975206.6116 +"Korea, Rep.",KOR,1980,64980820835.3226 +"Korea, Rep.",KOR,1981,72425590649.4574 +"Korea, Rep.",KOR,1982,77773431088.253 +"Korea, Rep.",KOR,1983,87024427972.9294 +"Korea, Rep.",KOR,1984,96597434179.5082 +"Korea, Rep.",KOR,1985,100273097170.18 +"Korea, Rep.",KOR,1986,115537126325.94 +"Korea, Rep.",KOR,1987,146133338196.141 +"Korea, Rep.",KOR,1988,196964195387.371 +"Korea, Rep.",KOR,1989,243526047716.915 +"Korea, Rep.",KOR,1990,279349355713.801 +"Korea, Rep.",KOR,1991,325734233312.879 +"Korea, Rep.",KOR,1992,350051111253.443 +"Korea, Rep.",KOR,1993,386302839273.923 +"Korea, Rep.",KOR,1994,455602962225.403 +"Korea, Rep.",KOR,1995,556130926912.754 +"Korea, Rep.",KOR,1996,598099073901.423 +"Korea, Rep.",KOR,1997,557503074772.151 +"Korea, Rep.",KOR,1998,374241351752.483 +"Korea, Rep.",KOR,1999,485248229336.653 +"Korea, Rep.",KOR,2000,561633125839.994 +"Korea, Rep.",KOR,2001,533052076313.527 +"Korea, Rep.",KOR,2002,609020054512.465 +"Korea, Rep.",KOR,2003,680520724062.403 +"Korea, Rep.",KOR,2004,764880644710.649 +"Korea, Rep.",KOR,2005,898137194716.188 +"Korea, Rep.",KOR,2006,1011797457138.5 +"Korea, Rep.",KOR,2007,1122679154632.41 +"Korea, Rep.",KOR,2008,1002219052967.54 +"Korea, Rep.",KOR,2009,901934953364.711 +"Korea, Rep.",KOR,2010,1094499338702.72 +"Korea, Rep.",KOR,2011,1202463682633.85 +"Korea, Rep.",KOR,2012,1222807284485.31 +"Korea, Rep.",KOR,2013,1305604981271.91 +"Korea, Rep.",KOR,2014,1411333926201.24 +"Korea, Rep.",KOR,2015,1382764027113.82 +"Korea, Rep.",KOR,2016,1411245589976.63 +Kosovo,XKX,2000,1849196082.05507 +Kosovo,XKX,2001,2535333631.88536 +Kosovo,XKX,2002,2702427046.9355 +Kosovo,XKX,2003,3355083116.58939 +Kosovo,XKX,2004,3639935347.50715 +Kosovo,XKX,2005,3736599925.38241 +Kosovo,XKX,2006,4078158323.92423 +Kosovo,XKX,2007,4833561456.33726 +Kosovo,XKX,2008,5687488208.58356 +Kosovo,XKX,2009,5653792720.20006 +Kosovo,XKX,2010,5829933774.83444 +Kosovo,XKX,2011,6649291075.89658 +Kosovo,XKX,2012,6473724784.78736 +Kosovo,XKX,2013,7072092405.73553 +Kosovo,XKX,2014,7386891336.07536 +Kosovo,XKX,2015,6440501275.36875 +Kosovo,XKX,2016,6649888888.88889 +Kuwait,KWT,1965,2097451694.2033 +Kuwait,KWT,1966,2391486978.43741 +Kuwait,KWT,1967,2441893027.16326 +Kuwait,KWT,1968,2663119574.34892 +Kuwait,KWT,1969,2769532343.88127 +Kuwait,KWT,1970,2873984878.18538 +Kuwait,KWT,1971,3880370401.57259 +Kuwait,KWT,1972,4451200972.9401 +Kuwait,KWT,1973,5408293998.65138 +Kuwait,KWT,1974,13004774556.6166 +Kuwait,KWT,1975,12024138275.8621 +Kuwait,KWT,1976,13131668946.6484 +Kuwait,KWT,1977,14135729588.2763 +Kuwait,KWT,1978,15500908760.4507 +Kuwait,KWT,1979,24746019536.903 +Kuwait,KWT,1980,28638550499.4451 +Kuwait,KWT,1981,25056672166.4275 +Kuwait,KWT,1982,21577977770.059 +Kuwait,KWT,1983,20869434305.3173 +Kuwait,KWT,1984,21697297872.3404 +Kuwait,KWT,1985,21442619680.8511 +Kuwait,KWT,1986,17903681693.0489 +Kuwait,KWT,1987,22365734481.5213 +Kuwait,KWT,1988,20692472759.8566 +Kuwait,KWT,1989,24312117767.1886 +Kuwait,KWT,1990,18427777777.7778 +Kuwait,KWT,1991,11008793176.2223 +Kuwait,KWT,1992,19858555214.7239 +Kuwait,KWT,1993,23941391390.7285 +Kuwait,KWT,1994,24848483838.3838 +Kuwait,KWT,1995,27191689008.0429 +Kuwait,KWT,1996,31493987641.9506 +Kuwait,KWT,1997,30354434553.2476 +Kuwait,KWT,1998,25941929461.9423 +Kuwait,KWT,1999,30121879434.954 +Kuwait,KWT,2000,37711864406.7797 +Kuwait,KWT,2001,34890772742.0933 +Kuwait,KWT,2002,38137545245.1464 +Kuwait,KWT,2003,47875838926.1745 +Kuwait,KWT,2004,59440108585.0017 +Kuwait,KWT,2005,80797945205.4795 +Kuwait,KWT,2006,101550654720.882 +Kuwait,KWT,2007,114641097818.438 +Kuwait,KWT,2008,147395833333.333 +Kuwait,KWT,2009,105899930507.297 +Kuwait,KWT,2010,115419050942.08 +Kuwait,KWT,2011,154027536231.884 +Kuwait,KWT,2012,174070025008.932 +Kuwait,KWT,2013,174161495063.47 +Kuwait,KWT,2014,162631763879.129 +Kuwait,KWT,2015,114041209704.221 +Kyrgyz Republic,KGZ,1990,2674000000 +Kyrgyz Republic,KGZ,1991,2570833333.33333 +Kyrgyz Republic,KGZ,1992,2316562500 +Kyrgyz Republic,KGZ,1993,2028295454.54545 +Kyrgyz Republic,KGZ,1994,1681006993.00699 +Kyrgyz Republic,KGZ,1995,1661018518.51852 +Kyrgyz Republic,KGZ,1996,1827570586.16784 +Kyrgyz Republic,KGZ,1997,1767864035.71943 +Kyrgyz Republic,KGZ,1998,1645963749.83146 +Kyrgyz Republic,KGZ,1999,1249062025.13805 +Kyrgyz Republic,KGZ,2000,1369693171.43504 +Kyrgyz Republic,KGZ,2001,1525112241.84376 +Kyrgyz Republic,KGZ,2002,1605640633.42189 +Kyrgyz Republic,KGZ,2003,1919012780.97086 +Kyrgyz Republic,KGZ,2004,2211535311.62834 +Kyrgyz Republic,KGZ,2005,2460248026.17783 +Kyrgyz Republic,KGZ,2006,2834168889.42019 +Kyrgyz Republic,KGZ,2007,3802566170.81543 +Kyrgyz Republic,KGZ,2008,5139957784.91084 +Kyrgyz Republic,KGZ,2009,4690062255.12247 +Kyrgyz Republic,KGZ,2010,4794357795.07139 +Kyrgyz Republic,KGZ,2011,6197766118.59856 +Kyrgyz Republic,KGZ,2012,6605139933.41063 +Kyrgyz Republic,KGZ,2013,7335027591.91628 +Kyrgyz Republic,KGZ,2014,7468096566.71158 +Kyrgyz Republic,KGZ,2015,6678178340.45121 +Kyrgyz Republic,KGZ,2016,6551287937.62632 +Lao PDR,LAO,1984,1757142805.71429 +Lao PDR,LAO,1985,2366666615.55556 +Lao PDR,LAO,1986,1776842041.05263 +Lao PDR,LAO,1987,1087273103.69639 +Lao PDR,LAO,1988,598961269.297879 +Lao PDR,LAO,1989,714046821.093797 +Lao PDR,LAO,1990,865559856.1639 +Lao PDR,LAO,1991,1028087972.31085 +Lao PDR,LAO,1992,1127806944.61513 +Lao PDR,LAO,1993,1327748654.65969 +Lao PDR,LAO,1994,1543606345.11684 +Lao PDR,LAO,1995,1763536304.53964 +Lao PDR,LAO,1996,1873671550.34636 +Lao PDR,LAO,1997,1747011857.33107 +Lao PDR,LAO,1998,1280177838.71905 +Lao PDR,LAO,1999,1454430642.49183 +Lao PDR,LAO,2000,1731198022.45494 +Lao PDR,LAO,2001,1768619058.34647 +Lao PDR,LAO,2002,1758176653.07746 +Lao PDR,LAO,2003,2023324407.30316 +Lao PDR,LAO,2004,2366398119.8821 +Lao PDR,LAO,2005,2735558726.25625 +Lao PDR,LAO,2006,3452882514.00166 +Lao PDR,LAO,2007,4222962987.53859 +Lao PDR,LAO,2008,5443915120.50795 +Lao PDR,LAO,2009,5832915387.08908 +Lao PDR,LAO,2010,7127792629.58294 +Lao PDR,LAO,2011,8261299199.6817 +Lao PDR,LAO,2012,10191367558.2708 +Lao PDR,LAO,2013,11942157500.4254 +Lao PDR,LAO,2014,13268297521.6066 +Lao PDR,LAO,2015,14390323462.0115 +Lao PDR,LAO,2016,15903437789.8552 +Latvia,LVA,1995,5788368511.12379 +Latvia,LVA,1996,5970044665.64574 +Latvia,LVA,1997,6525676264.21486 +Latvia,LVA,1998,7174985106.63648 +Latvia,LVA,1999,7533187605.09248 +Latvia,LVA,2000,7937758980.30127 +Latvia,LVA,2001,8350252966.19655 +Latvia,LVA,2002,9546441564.34743 +Latvia,LVA,2003,11748433157.0533 +Latvia,LVA,2004,14373269155.7174 +Latvia,LVA,2005,16922504044.804 +Latvia,LVA,2006,21447021570.1028 +Latvia,LVA,2007,30901399261.387 +Latvia,LVA,2008,35596016664.2304 +Latvia,LVA,2009,26169854045.0375 +Latvia,LVA,2010,23757368290.0955 +Latvia,LVA,2011,28223552824.7508 +Latvia,LVA,2012,28119996053.2511 +Latvia,LVA,2013,30254571077.6726 +Latvia,LVA,2014,31352249349.5712 +Latvia,LVA,2015,27026037600.3392 +Latvia,LVA,2016,27677391316.3405 +Lebanon,LBN,1988,3313540067.93246 +Lebanon,LBN,1989,2717998687.71002 +Lebanon,LBN,1990,2838485353.96187 +Lebanon,LBN,1991,4451497288.27108 +Lebanon,LBN,1992,5545921947.46583 +Lebanon,LBN,1993,7535259851.03597 +Lebanon,LBN,1994,9599127049.9375 +Lebanon,LBN,1995,11718795528.4939 +Lebanon,LBN,1996,13690217333.2697 +Lebanon,LBN,1997,15751867489.4446 +Lebanon,LBN,1998,17247179005.5219 +Lebanon,LBN,1999,17391056369.2265 +Lebanon,LBN,2000,17260364842.4544 +Lebanon,LBN,2001,17649751243.7811 +Lebanon,LBN,2002,19152238805.9701 +Lebanon,LBN,2003,20082918739.6352 +Lebanon,LBN,2004,20955223880.597 +Lebanon,LBN,2005,21287562189.0547 +Lebanon,LBN,2006,21796351575.4561 +Lebanon,LBN,2007,24577114427.8607 +Lebanon,LBN,2008,28829850746.2687 +Lebanon,LBN,2009,35139635157.5456 +Lebanon,LBN,2010,38009950248.7562 +Lebanon,LBN,2011,40078938640.1327 +Lebanon,LBN,2012,43205095854.063 +Lebanon,LBN,2013,44352417910.4478 +Lebanon,LBN,2014,45730945273.6318 +Lebanon,LBN,2015,47084703150.9121 +Lebanon,LBN,2016,47536798648.0929 +Lesotho,LSO,1960,34579308.4138317 +Lesotho,LSO,1961,35699286.0142797 +Lesotho,LSO,1962,41859162.8167437 +Lesotho,LSO,1963,47039059.2188156 +Lesotho,LSO,1964,51938961.2207756 +Lesotho,LSO,1965,54878902.4219516 +Lesotho,LSO,1966,56698866.0226795 +Lesotho,LSO,1967,59260814.7837043 +Lesotho,LSO,1968,61444771.1045779 +Lesotho,LSO,1969,65966680.6663867 +Lesotho,LSO,1970,68738625.2274955 +Lesotho,LSO,1971,76482102.9082774 +Lesotho,LSO,1972,80915831.9240276 +Lesotho,LSO,1973,121181556.195965 +Lesotho,LSO,1974,150846210.448859 +Lesotho,LSO,1975,149560513.860717 +Lesotho,LSO,1976,147654093.836247 +Lesotho,LSO,1977,193307267.709292 +Lesotho,LSO,1978,266559337.626495 +Lesotho,LSO,1979,290142517.814727 +Lesotho,LSO,1980,431561376.476631 +Lesotho,LSO,1981,434188034.188034 +Lesotho,LSO,1982,348746792.515574 +Lesotho,LSO,1983,386699344.059023 +Lesotho,LSO,1984,333158502.306626 +Lesotho,LSO,1985,268626893.690796 +Lesotho,LSO,1986,318862870.333317 +Lesotho,LSO,1987,402774850.256341 +Lesotho,LSO,1988,470389190.094405 +Lesotho,LSO,1989,495404890.865006 +Lesotho,LSO,1990,596415106.633185 +Lesotho,LSO,1991,704329193.303687 +Lesotho,LSO,1992,831033946.369022 +Lesotho,LSO,1993,835592816.316424 +Lesotho,LSO,1994,878250452.815718 +Lesotho,LSO,1995,1001889845.5807 +Lesotho,LSO,1996,946123280.510758 +Lesotho,LSO,1997,997996034.86775 +Lesotho,LSO,1998,928458201.135383 +Lesotho,LSO,1999,912771283.593936 +Lesotho,LSO,2000,887295262.184165 +Lesotho,LSO,2001,825706966.802027 +Lesotho,LSO,2002,775780697.302945 +Lesotho,LSO,2003,1157832935.83899 +Lesotho,LSO,2004,1511236652.019 +Lesotho,LSO,2005,1682350941.54943 +Lesotho,LSO,2006,1800105593.03747 +Lesotho,LSO,2007,1820597204.99096 +Lesotho,LSO,2008,1868776303.14958 +Lesotho,LSO,2009,1864004707.45587 +Lesotho,LSO,2010,2394097298.85591 +Lesotho,LSO,2011,2791545696.37485 +Lesotho,LSO,2012,2678243067.38507 +Lesotho,LSO,2013,2532392022.47022 +Lesotho,LSO,2014,2520952363.38624 +Lesotho,LSO,2015,2335194894.3494 +Lesotho,LSO,2016,2199709488.86039 +Liberia,LBR,1960,190495600 +Liberia,LBR,1961,183920900 +Liberia,LBR,1962,191861800 +Liberia,LBR,1963,200229600 +Liberia,LBR,1964,218929100 +Liberia,LBR,1965,229260800 +Liberia,LBR,1966,244459500 +Liberia,LBR,1967,261024300 +Liberia,LBR,1968,276820700 +Liberia,LBR,1969,306961800 +Liberia,LBR,1970,323099700 +Liberia,LBR,1971,341543100 +Liberia,LBR,1972,368098000 +Liberia,LBR,1973,386968300 +Liberia,LBR,1974,486955000 +Liberia,LBR,1975,577549300 +Liberia,LBR,1976,596675700 +Liberia,LBR,1977,673010600 +Liberia,LBR,1978,717240400 +Liberia,LBR,1979,814067900 +Liberia,LBR,1980,854711500 +Liberia,LBR,1981,846514500 +Liberia,LBR,1982,863933200 +Liberia,LBR,1983,823374900 +Liberia,LBR,1984,848478300 +Liberia,LBR,1985,851296100 +Liberia,LBR,1986,840964400 +Liberia,LBR,1987,972800000 +Liberia,LBR,1988,1038300000 +Liberia,LBR,1989,786300000 +Liberia,LBR,1990,384400000 +Liberia,LBR,1991,348000000 +Liberia,LBR,1992,223500000 +Liberia,LBR,1993,160400000 +Liberia,LBR,1994,132200000 +Liberia,LBR,1995,134800000 +Liberia,LBR,1996,159400000 +Liberia,LBR,1997,295900000 +Liberia,LBR,1998,359600000 +Liberia,LBR,1999,441800000 +Liberia,LBR,2000,529064600 +Liberia,LBR,2001,521000000 +Liberia,LBR,2002,543000000 +Liberia,LBR,2003,416000000 +Liberia,LBR,2004,474700000 +Liberia,LBR,2005,550000000 +Liberia,LBR,2006,604028900 +Liberia,LBR,2007,739027200 +Liberia,LBR,2008,850040500 +Liberia,LBR,2009,1155147400 +Liberia,LBR,2010,1292697100 +Liberia,LBR,2011,1545400000 +Liberia,LBR,2012,1735500000 +Liberia,LBR,2013,1946500000 +Liberia,LBR,2014,2013000000 +Liberia,LBR,2015,2034000000 +Liberia,LBR,2016,2101000000 +Libya,LBY,1990,28901836158.1921 +Libya,LBY,1991,31995012468.8279 +Libya,LBY,1992,33881392045.4545 +Libya,LBY,1993,30657030223.3903 +Libya,LBY,1994,28607921928.8175 +Libya,LBY,1995,25544128198.9955 +Libya,LBY,1996,27884615384.6154 +Libya,LBY,1997,30698633109.1343 +Libya,LBY,1998,27249786142.0017 +Libya,LBY,1999,35976714100.9056 +Libya,LBY,2000,38270206950.41 +Libya,LBY,2001,34110064452.1567 +Libya,LBY,2002,20481889763.7795 +Libya,LBY,2003,26265625000 +Libya,LBY,2004,33122307692.3077 +Libya,LBY,2005,47334148578.4164 +Libya,LBY,2006,54961936662.6066 +Libya,LBY,2007,67516236337.7158 +Libya,LBY,2008,87140405361.2292 +Libya,LBY,2009,63028320702.0343 +Libya,LBY,2010,74773444900.5368 +Libya,LBY,2011,34699395523.6073 +Liechtenstein,LIE,1970,90098330.6654471 +Liechtenstein,LIE,1971,104888628.171944 +Liechtenstein,LIE,1972,124941925.010473 +Liechtenstein,LIE,1973,165930611.729019 +Liechtenstein,LIE,1974,193983720.461869 +Liechtenstein,LIE,1975,246387479.177159 +Liechtenstein,LIE,1976,272493879.020643 +Liechtenstein,LIE,1977,303496276.263782 +Liechtenstein,LIE,1978,436918176.733781 +Liechtenstein,LIE,1979,503180669.994587 +Liechtenstein,LIE,1980,534701915.617354 +Liechtenstein,LIE,1981,511658690.561043 +Liechtenstein,LIE,1982,522090331.478107 +Liechtenstein,LIE,1983,524034109.856605 +Liechtenstein,LIE,1984,502617355.407073 +Liechtenstein,LIE,1985,529078995.563876 +Liechtenstein,LIE,1986,779365167.602424 +Liechtenstein,LIE,1987,1052843347.63948 +Liechtenstein,LIE,1988,1161757671.01756 +Liechtenstein,LIE,1989,1120000916.92646 +Liechtenstein,LIE,1990,1421466239.56234 +Liechtenstein,LIE,1991,1484152022.3152 +Liechtenstein,LIE,1992,1631197909.259 +Liechtenstein,LIE,1993,1673104493.77369 +Liechtenstein,LIE,1994,1948118227.68151 +Liechtenstein,LIE,1995,2428461395.34884 +Liechtenstein,LIE,1996,2504033252.42718 +Liechtenstein,LIE,1997,2298410390.68421 +Liechtenstein,LIE,1998,2479721340.8746 +Liechtenstein,LIE,1999,2664026095.06058 +Liechtenstein,LIE,2000,2483953102.79488 +Liechtenstein,LIE,2001,2491822706.80256 +Liechtenstein,LIE,2002,2688630822.53304 +Liechtenstein,LIE,2003,3070691319.52179 +Liechtenstein,LIE,2004,3454362685.96703 +Liechtenstein,LIE,2005,3659251525.8593 +Liechtenstein,LIE,2006,4000239272.61126 +Liechtenstein,LIE,2007,4601299566.81106 +Liechtenstein,LIE,2008,5081432924.0144 +Liechtenstein,LIE,2009,4504549214.22663 +Liechtenstein,LIE,2010,5082366478.08994 +Liechtenstein,LIE,2011,5739977477.47748 +Liechtenstein,LIE,2012,5456009384.66461 +Liechtenstein,LIE,2013,6391735893.83968 +Liechtenstein,LIE,2014,6663501418.90417 +Lithuania,LTU,1995,7870782260.51698 +Lithuania,LTU,1996,8385109020.28485 +Lithuania,LTU,1997,10120274492.8787 +Lithuania,LTU,1998,11240360897.7126 +Lithuania,LTU,1999,10972878636.1675 +Lithuania,LTU,2000,11539211480.3625 +Lithuania,LTU,2001,12252498921.0186 +Lithuania,LTU,2002,14278357283.7419 +Lithuania,LTU,2003,18802576988.1557 +Lithuania,LTU,2004,22649930576.2543 +Lithuania,LTU,2005,26125575942.2814 +Lithuania,LTU,2006,30216060233.4044 +Lithuania,LTU,2007,39738180076.6283 +Lithuania,LTU,2008,47850551148.8365 +Lithuania,LTU,2009,37440673477.8982 +Lithuania,LTU,2010,37120517693.8622 +Lithuania,LTU,2011,43476878139.2577 +Lithuania,LTU,2012,42847900765.8065 +Lithuania,LTU,2013,46473646001.5672 +Lithuania,LTU,2014,48545251795.561 +Lithuania,LTU,2015,41402022148.2053 +Lithuania,LTU,2016,42738875963.3703 +Luxembourg,LUX,1960,703925705.942958 +Luxembourg,LUX,1961,704145671.350213 +Luxembourg,LUX,1962,741509480.796284 +Luxembourg,LUX,1963,791140595.772755 +Luxembourg,LUX,1964,903158753.943622 +Luxembourg,LUX,1965,921600736.304026 +Luxembourg,LUX,1966,968440149.470951 +Luxembourg,LUX,1967,974721762.535327 +Luxembourg,LUX,1968,1066447130.82052 +Luxembourg,LUX,1969,1234878980.502 +Luxembourg,LUX,1970,1509155062.52521 +Luxembourg,LUX,1971,1572310771.77053 +Luxembourg,LUX,1972,1968733021.7212 +Luxembourg,LUX,1973,2701874663.63072 +Luxembourg,LUX,1974,3295861019.05551 +Luxembourg,LUX,1975,3233431611.27564 +Luxembourg,LUX,1976,3544268025.07837 +Luxembourg,LUX,1977,3922895891.95273 +Luxembourg,LUX,1978,4884869091.84066 +Luxembourg,LUX,1979,5711457760.04403 +Luxembourg,LUX,1980,6232005655.95255 +Luxembourg,LUX,1981,5231808670.14342 +Luxembourg,LUX,1982,4764549532.05015 +Luxembourg,LUX,1983,4683697830.37475 +Luxembourg,LUX,1984,4594891580.56409 +Luxembourg,LUX,1985,4738559684.76119 +Luxembourg,LUX,1986,6921264132.20155 +Luxembourg,LUX,1987,8614215559.15721 +Luxembourg,LUX,1988,9750161053.209 +Luxembourg,LUX,1989,10391504709.2547 +Luxembourg,LUX,1990,13229247947.8513 +Luxembourg,LUX,1991,14321878795.0384 +Luxembourg,LUX,1992,16065740777.9172 +Luxembourg,LUX,1993,16486900186.5672 +Luxembourg,LUX,1994,18325791415.4811 +Luxembourg,LUX,1995,21588170498.0843 +Luxembourg,LUX,1996,21776609771.987 +Luxembourg,LUX,1997,19731912494.3617 +Luxembourg,LUX,1998,20209122027.1171 +Luxembourg,LUX,1999,22235929043.2559 +Luxembourg,LUX,2000,21263514833.2412 +Luxembourg,LUX,2001,21272418791.9463 +Luxembourg,LUX,2002,23616328816.1114 +Luxembourg,LUX,2003,29557325056.4334 +Luxembourg,LUX,2004,34685281847.5292 +Luxembourg,LUX,2005,37347394602.6614 +Luxembourg,LUX,2006,42414308116.9239 +Luxembourg,LUX,2007,50888134410.0739 +Luxembourg,LUX,2008,55849686538.7432 +Luxembourg,LUX,2009,51370543206.4462 +Luxembourg,LUX,2010,53212476812.2957 +Luxembourg,LUX,2011,60004630234.4135 +Luxembourg,LUX,2012,56677961787.0717 +Luxembourg,LUX,2013,61808178300.1352 +Luxembourg,LUX,2014,66298060521.7586 +Luxembourg,LUX,2015,58048242436.0611 +Luxembourg,LUX,2016,59947781147.4776 +"Macao SAR, China",MAC,1982,1130457130.00739 +"Macao SAR, China",MAC,1983,1121486562.52512 +"Macao SAR, China",MAC,1984,1292297736.23885 +"Macao SAR, China",MAC,1985,1348827324.09861 +"Macao SAR, China",MAC,1986,1517496131.38322 +"Macao SAR, China",MAC,1987,1941246972.45874 +"Macao SAR, China",MAC,1988,2269233639.28065 +"Macao SAR, China",MAC,1989,2683254708.17411 +"Macao SAR, China",MAC,1990,3220920084.77746 +"Macao SAR, China",MAC,1991,3735117374.41125 +"Macao SAR, China",MAC,1992,4879018601.90911 +"Macao SAR, China",MAC,1993,5625533410.31176 +"Macao SAR, China",MAC,1994,6265844252.10105 +"Macao SAR, China",MAC,1995,6996034036.99892 +"Macao SAR, China",MAC,1996,7122539666.59972 +"Macao SAR, China",MAC,1997,7211264780.00828 +"Macao SAR, China",MAC,1998,6742367273.27418 +"Macao SAR, China",MAC,1999,6490571703.85015 +"Macao SAR, China",MAC,2000,6720492405.83611 +"Macao SAR, China",MAC,2001,6811227982.82193 +"Macao SAR, China",MAC,2002,7322677820.10108 +"Macao SAR, China",MAC,2003,8195033162.12038 +"Macao SAR, China",MAC,2004,10585624890.9277 +"Macao SAR, China",MAC,2005,12092222041.9168 +"Macao SAR, China",MAC,2006,14789661809.1834 +"Macao SAR, China",MAC,2007,18340447242.9971 +"Macao SAR, China",MAC,2008,20917444919.6394 +"Macao SAR, China",MAC,2009,21475520709.3922 +"Macao SAR, China",MAC,2010,28123640998.7253 +"Macao SAR, China",MAC,2011,36709860068.3445 +"Macao SAR, China",MAC,2012,43031577366.4251 +"Macao SAR, China",MAC,2013,51552075901.5183 +"Macao SAR, China",MAC,2014,55347998647.8196 +"Macao SAR, China",MAC,2015,45415278647.464 +"Macao SAR, China",MAC,2016,44802641829.9265 +"Macedonia, FYR",MKD,1990,4471828621.90813 +"Macedonia, FYR",MKD,1991,4694744897.95918 +"Macedonia, FYR",MKD,1992,2316618542.52603 +"Macedonia, FYR",MKD,1993,2550195043.10345 +"Macedonia, FYR",MKD,1994,3381270207.85219 +"Macedonia, FYR",MKD,1995,4449375346.45669 +"Macedonia, FYR",MKD,1996,4422160017.54386 +"Macedonia, FYR",MKD,1997,3735312142.57028 +"Macedonia, FYR",MKD,1998,3571043102.5641 +"Macedonia, FYR",MKD,1999,3673288263.62039 +"Macedonia, FYR",MKD,2000,3772851420.24763 +"Macedonia, FYR",MKD,2001,3709637829.94866 +"Macedonia, FYR",MKD,2002,4018365247.44444 +"Macedonia, FYR",MKD,2003,4946292774.79046 +"Macedonia, FYR",MKD,2004,5682719260.0763 +"Macedonia, FYR",MKD,2005,6258600713.82627 +"Macedonia, FYR",MKD,2006,6861222331.96317 +"Macedonia, FYR",MKD,2007,8336478142.08872 +"Macedonia, FYR",MKD,2008,9909548410.82744 +"Macedonia, FYR",MKD,2009,9401731495.71661 +"Macedonia, FYR",MKD,2010,9407168702.4313 +"Macedonia, FYR",MKD,2011,10494632699.3859 +"Macedonia, FYR",MKD,2012,9745251126.0109 +"Macedonia, FYR",MKD,2013,10817712138.9451 +"Macedonia, FYR",MKD,2014,11362272837.8818 +"Macedonia, FYR",MKD,2015,10051659161.1733 +"Macedonia, FYR",MKD,2016,10899583154.6499 +Madagascar,MDG,1960,673081724.075966 +Madagascar,MDG,1961,699161943.856733 +Madagascar,MDG,1962,739286906.851163 +Madagascar,MDG,1963,759345862.970929 +Madagascar,MDG,1964,802482182.923768 +Madagascar,MDG,1965,833563472.161911 +Madagascar,MDG,1966,900264583.687729 +Madagascar,MDG,1967,956436931.141842 +Madagascar,MDG,1968,1031669636.36062 +Madagascar,MDG,1969,1056391054.53794 +Madagascar,MDG,1970,1111859569.77066 +Madagascar,MDG,1971,1199507629.99222 +Madagascar,MDG,1972,1341590681.586 +Madagascar,MDG,1973,1653062347.36378 +Madagascar,MDG,1974,1917508190.04689 +Madagascar,MDG,1975,2283049233.28581 +Madagascar,MDG,1976,2181844193.92388 +Madagascar,MDG,1977,2358930406.42896 +Madagascar,MDG,1978,2669755115.50372 +Madagascar,MDG,1979,3463565881.42215 +Madagascar,MDG,1980,4042139901.36379 +Madagascar,MDG,1981,3594868208.41664 +Madagascar,MDG,1982,3526198070.09789 +Madagascar,MDG,1983,3511573991.89606 +Madagascar,MDG,1984,2939485471.50097 +Madagascar,MDG,1985,2857889712.4808 +Madagascar,MDG,1986,3258288890.58647 +Madagascar,MDG,1987,2565634382.28729 +Madagascar,MDG,1988,2442507588.38468 +Madagascar,MDG,1989,2498059014.77295 +Madagascar,MDG,1990,3081479800.28735 +Madagascar,MDG,1991,2653141958.52585 +Madagascar,MDG,1992,3024459564.32157 +Madagascar,MDG,1993,3370842210.90955 +Madagascar,MDG,1994,2977040722.47057 +Madagascar,MDG,1995,3159901231.97468 +Madagascar,MDG,1996,3995028592.78722 +Madagascar,MDG,1997,3545776697.12109 +Madagascar,MDG,1998,3738704467.51878 +Madagascar,MDG,1999,3717515282.53319 +Madagascar,MDG,2000,3877673539.09084 +Madagascar,MDG,2001,4529575347.56805 +Madagascar,MDG,2002,4397254607.61164 +Madagascar,MDG,2003,5474030080.24451 +Madagascar,MDG,2004,4363934494.37405 +Madagascar,MDG,2005,5039293030.82367 +Madagascar,MDG,2006,5515884348.54904 +Madagascar,MDG,2007,7342923489.09616 +Madagascar,MDG,2008,9413002920.97008 +Madagascar,MDG,2009,8550363974.79243 +Madagascar,MDG,2010,8729936135.74487 +Madagascar,MDG,2011,9892702357.56691 +Madagascar,MDG,2012,9919780071.28764 +Madagascar,MDG,2013,10601690871.7611 +Madagascar,MDG,2014,10673516672.6664 +Madagascar,MDG,2015,9738652322.17001 +Madagascar,MDG,2016,9990653078.19497 +Malawi,MWI,1960,162960130.465802 +Malawi,MWI,1961,174580139.768776 +Malawi,MWI,1962,183120146.605902 +Malawi,MWI,1963,190820152.770523 +Malawi,MWI,1964,194740155.908875 +Malawi,MWI,1965,229460183.705713 +Malawi,MWI,1966,260400208.476282 +Malawi,MWI,1967,269812781.79847 +Malawi,MWI,1968,245160098.113071 +Malawi,MWI,1969,265800106.373203 +Malawi,MWI,1970,290520116.266151 +Malawi,MWI,1971,365389567.21636 +Malawi,MWI,1972,406084197.385471 +Malawi,MWI,1973,444302221.260027 +Malawi,MWI,1974,548618789.94423 +Malawi,MWI,1975,613196872.560739 +Malawi,MWI,1976,670309252.98248 +Malawi,MWI,1977,806265763.845459 +Malawi,MWI,1978,948983308.780545 +Malawi,MWI,1979,1058297676.33572 +Malawi,MWI,1980,1237662066.78974 +Malawi,MWI,1981,1237686960.55408 +Malawi,MWI,1982,1180094061.48178 +Malawi,MWI,1983,1223225019.32697 +Malawi,MWI,1984,1208026079.75492 +Malawi,MWI,1985,1131349992.22735 +Malawi,MWI,1986,1183671788.12366 +Malawi,MWI,1987,1183071363.00406 +Malawi,MWI,1988,1379923808.24718 +Malawi,MWI,1989,1590201656.14301 +Malawi,MWI,1990,1880784191.81484 +Malawi,MWI,1991,2203536031.03471 +Malawi,MWI,1992,1799529357.0981 +Malawi,MWI,1993,2070647127.03808 +Malawi,MWI,1994,1181801919.66833 +Malawi,MWI,1995,1397454122.24047 +Malawi,MWI,1996,2281039097.69299 +Malawi,MWI,1997,2663238982.8009 +Malawi,MWI,1998,1750585204.44813 +Malawi,MWI,1999,1775920039.58919 +Malawi,MWI,2000,1743506287.41519 +Malawi,MWI,2001,1716502862.2954 +Malawi,MWI,2002,3495748397.63025 +Malawi,MWI,2003,3208837077.25069 +Malawi,MWI,2004,3476094498.87517 +Malawi,MWI,2005,3655909664.1423 +Malawi,MWI,2006,3997852636.24547 +Malawi,MWI,2007,4432192843.58998 +Malawi,MWI,2008,5320925102.29496 +Malawi,MWI,2009,6190991712.12014 +Malawi,MWI,2010,6959697194.02096 +Malawi,MWI,2011,8003300198.30166 +Malawi,MWI,2012,6028470988.53624 +Malawi,MWI,2013,5518901971.40057 +Malawi,MWI,2014,6054750320.3278 +Malawi,MWI,2015,6373201160.03248 +Malawi,MWI,2016,5441852138.14605 +Malaysia,MYS,1960,1916241996.60264 +Malaysia,MYS,1961,1901868548.28172 +Malaysia,MYS,1962,2001502678.6881 +Malaysia,MYS,1963,2510126747.68065 +Malaysia,MYS,1964,2674441395.53116 +Malaysia,MYS,1965,2956356984.18921 +Malaysia,MYS,1966,3143538481.64119 +Malaysia,MYS,1967,3188945511.56409 +Malaysia,MYS,1968,3330393309.81315 +Malaysia,MYS,1969,3664575983.27453 +Malaysia,MYS,1970,3864170913.36731 +Malaysia,MYS,1971,4244340333.51899 +Malaysia,MYS,1972,5043268548.73032 +Malaysia,MYS,1973,7662996766.66803 +Malaysia,MYS,1974,9496074114.07918 +Malaysia,MYS,1975,9298800799.46702 +Malaysia,MYS,1976,11050125904.9418 +Malaysia,MYS,1977,13139397879.1695 +Malaysia,MYS,1978,16358376511.2263 +Malaysia,MYS,1979,21213672089.1976 +Malaysia,MYS,1980,24488033442.0506 +Malaysia,MYS,1981,25004557093.8761 +Malaysia,MYS,1982,26804401815.5348 +Malaysia,MYS,1983,30346788437.5135 +Malaysia,MYS,1984,33943505717.6993 +Malaysia,MYS,1985,31200161095.4491 +Malaysia,MYS,1986,27734562640.4277 +Malaysia,MYS,1987,32181695507.2234 +Malaysia,MYS,1988,35271880250.4964 +Malaysia,MYS,1989,38848567631.4235 +Malaysia,MYS,1990,44024178343.0071 +Malaysia,MYS,1991,49142784405.0044 +Malaysia,MYS,1992,59167157497.9385 +Malaysia,MYS,1993,66894448545.1226 +Malaysia,MYS,1994,74477975918.3051 +Malaysia,MYS,1995,88704944178.6284 +Malaysia,MYS,1996,100854996422.609 +Malaysia,MYS,1997,100005323301.867 +Malaysia,MYS,1998,72167753770.8928 +Malaysia,MYS,1999,79148947368.4211 +Malaysia,MYS,2000,93789736842.1053 +Malaysia,MYS,2001,92783947368.4211 +Malaysia,MYS,2002,100845263157.895 +Malaysia,MYS,2003,110202368421.053 +Malaysia,MYS,2004,124749736842.105 +Malaysia,MYS,2005,143534102611.497 +Malaysia,MYS,2006,162690965596.205 +Malaysia,MYS,2007,193547824063.3 +Malaysia,MYS,2008,230813597937.526 +Malaysia,MYS,2009,202257586267.556 +Malaysia,MYS,2010,255016609232.871 +Malaysia,MYS,2011,297951960784.314 +Malaysia,MYS,2012,314442825692.826 +Malaysia,MYS,2013,323276841537.339 +Malaysia,MYS,2014,338068990803.263 +Malaysia,MYS,2015,296283190372.552 +Malaysia,MYS,2016,296359118754.525 +Maldives,MDV,1980,42463576.1589404 +Maldives,MDV,1981,44781456.9536424 +Maldives,MDV,1982,47935843.7935844 +Maldives,MDV,1983,57829787.2340425 +Maldives,MDV,1984,109503546.099291 +Maldives,MDV,1985,127154929.577465 +Maldives,MDV,1986,141902097.902098 +Maldives,MDV,1987,141268980.477223 +Maldives,MDV,1988,168610478.359909 +Maldives,MDV,1989,189535398.230089 +Maldives,MDV,1990,215089005.235602 +Maldives,MDV,1991,244468292.682927 +Maldives,MDV,1992,284853358.561968 +Maldives,MDV,1993,322326642.335766 +Maldives,MDV,1994,355884383.08887 +Maldives,MDV,1995,398988954.970263 +Maldives,MDV,1996,450382327.952421 +Maldives,MDV,1997,508223602.37893 +Maldives,MDV,1998,540096397.621071 +Maldives,MDV,1999,589239753.610875 +Maldives,MDV,2000,624337145.284622 +Maldives,MDV,2001,870179738.562091 +Maldives,MDV,2002,897031250 +Maldives,MDV,2003,1043403343.75 +Maldives,MDV,2004,1202240023.4375 +Maldives,MDV,2005,1119806500 +Maldives,MDV,2006,1474698125 +Maldives,MDV,2007,1745998937.5 +Maldives,MDV,2008,2109960937.5 +Maldives,MDV,2009,2149257812.5 +Maldives,MDV,2010,2323401757.8125 +Maldives,MDV,2011,2449576516.91549 +Maldives,MDV,2012,2518312129.02218 +Maldives,MDV,2013,2795147949.78753 +Maldives,MDV,2014,3094197810.2 +Maldives,MDV,2015,3435244658.76626 +Maldives,MDV,2016,3591112750.83939 +Mali,MLI,1967,275494520.141999 +Mali,MLI,1968,343771964.662167 +Mali,MLI,1969,339913833.096246 +Mali,MLI,1970,359772363.262207 +Mali,MLI,1971,430096738.369216 +Mali,MLI,1972,486617332.387405 +Mali,MLI,1973,563683660.31194 +Mali,MLI,1974,538747268.333356 +Mali,MLI,1975,830710615.179954 +Mali,MLI,1976,939227993.66396 +Mali,MLI,1977,1049838492.55759 +Mali,MLI,1978,1222702356.10946 +Mali,MLI,1979,1595423285.64659 +Mali,MLI,1980,1759690811.60699 +Mali,MLI,1981,1538972158.1782 +Mali,MLI,1982,1333754034.23489 +Mali,MLI,1983,1297765448.50498 +Mali,MLI,1984,1232932008.13719 +Mali,MLI,1985,1392195933.33971 +Mali,MLI,1986,1852163474.54664 +Mali,MLI,1987,2090629722.63611 +Mali,MLI,1988,2169040741.55896 +Mali,MLI,1989,2181821902.43953 +Mali,MLI,1990,2681912030.49384 +Mali,MLI,1991,2724131545.16958 +Mali,MLI,1992,2830673388.82429 +Mali,MLI,1993,2818280876.07615 +Mali,MLI,1994,2081846482.74771 +Mali,MLI,1995,2706425298.36818 +Mali,MLI,1996,2780422212.26995 +Mali,MLI,1997,2697105694.07956 +Mali,MLI,1998,2920358586.75234 +Mali,MLI,1999,3439463140.35541 +Mali,MLI,2000,2954129565.82965 +Mali,MLI,2001,3465305993.47783 +Mali,MLI,2002,3889758023.73699 +Mali,MLI,2003,4703504466.53245 +Mali,MLI,2004,5444474268.42491 +Mali,MLI,2005,6245031690.06808 +Mali,MLI,2006,6899799785.8441 +Mali,MLI,2007,8145694631.88354 +Mali,MLI,2008,9750822511.47988 +Mali,MLI,2009,10181021770.4326 +Mali,MLI,2010,10678749467.4697 +Mali,MLI,2011,12978107560.5982 +Mali,MLI,2012,12442747897.2223 +Mali,MLI,2013,12813248724.7996 +Mali,MLI,2014,14004067516.3577 +Mali,MLI,2015,12746688961.7795 +Mali,MLI,2016,14045098237.528 +Malta,MLT,1970,250721821.553678 +Malta,MLT,1971,264579879.784878 +Malta,MLT,1972,295118249.324932 +Malta,MLT,1973,345602025.375393 +Malta,MLT,1974,376094108.475331 +Malta,MLT,1975,474620439.58496 +Malta,MLT,1976,527936988.791275 +Malta,MLT,1977,625573345.532174 +Malta,MLT,1978,793675169.878579 +Malta,MLT,1979,1001300838.32335 +Malta,MLT,1980,1250242107.87969 +Malta,MLT,1981,1243469360.56838 +Malta,MLT,1982,1234518125 +Malta,MLT,1983,1165771369.00625 +Malta,MLT,1984,1101828568.76804 +Malta,MLT,1985,1117835285.50512 +Malta,MLT,1986,1435079200.34957 +Malta,MLT,1987,1751247763.41948 +Malta,MLT,1988,2019474244.19359 +Malta,MLT,1989,2118574772.11136 +Malta,MLT,1990,2547163582.33149 +Malta,MLT,1991,2750041434.26295 +Malta,MLT,1992,3021910216.71827 +Malta,MLT,1993,2709178326.78271 +Malta,MLT,1994,2998570146.54095 +Malta,MLT,1995,3439931906.61479 +Malta,MLT,1996,3570271557.88471 +Malta,MLT,1997,3705372038.70537 +Malta,MLT,1998,3923637971.04652 +Malta,MLT,1999,4127313818.33836 +Malta,MLT,2000,4306192435.82207 +Malta,MLT,2001,4331870647.71535 +Malta,MLT,2002,4689832689.83269 +Malta,MLT,2003,5456583589.39342 +Malta,MLT,2004,6062780269.0583 +Malta,MLT,2005,6394851386.64345 +Malta,MLT,2006,6757119558.3992 +Malta,MLT,2007,7880509170.54476 +Malta,MLT,2008,8977149553.24447 +Malta,MLT,2009,8528202278.41067 +Malta,MLT,2010,8741059602.64901 +Malta,MLT,2011,9500001983.37933 +Malta,MLT,2012,9198987219.66026 +Malta,MLT,2013,10131419448.978 +Malta,MLT,2014,11188785252.7566 +Malta,MLT,2015,10287007021.1557 +Malta,MLT,2016,10949092471.597 +Marshall Islands,MHL,1981,31020000 +Marshall Islands,MHL,1982,34918000 +Marshall Islands,MHL,1983,41749000 +Marshall Islands,MHL,1984,45144000 +Marshall Islands,MHL,1985,43879000 +Marshall Islands,MHL,1986,55989000 +Marshall Islands,MHL,1987,62983000 +Marshall Islands,MHL,1988,70688000 +Marshall Islands,MHL,1989,72798000 +Marshall Islands,MHL,1990,78476000 +Marshall Islands,MHL,1991,82507000 +Marshall Islands,MHL,1992,91063000 +Marshall Islands,MHL,1993,99461000 +Marshall Islands,MHL,1994,108071000 +Marshall Islands,MHL,1995,120230000 +Marshall Islands,MHL,1996,110858000 +Marshall Islands,MHL,1997,106289100 +Marshall Islands,MHL,1998,108702100 +Marshall Islands,MHL,1999,107978900 +Marshall Islands,MHL,2000,110937700 +Marshall Islands,MHL,2001,115152100 +Marshall Islands,MHL,2002,124735100 +Marshall Islands,MHL,2003,126887600 +Marshall Islands,MHL,2004,131106400 +Marshall Islands,MHL,2005,137744500 +Marshall Islands,MHL,2006,143656600 +Marshall Islands,MHL,2007,150851598.261375 +Marshall Islands,MHL,2008,152901100 +Marshall Islands,MHL,2009,152631200 +Marshall Islands,MHL,2010,164751300 +Marshall Islands,MHL,2011,172674900 +Marshall Islands,MHL,2012,185055800 +Marshall Islands,MHL,2013,190992000 +Marshall Islands,MHL,2014,183114100 +Marshall Islands,MHL,2015,179432600 +Marshall Islands,MHL,2016,183000000 +Mauritania,MRT,1960,92609222.6912849 +Mauritania,MRT,1961,107726181.218304 +Mauritania,MRT,1962,111148585.592024 +Mauritania,MRT,1963,113797356.813964 +Mauritania,MRT,1964,151897168.106199 +Mauritania,MRT,1965,172767213.286516 +Mauritania,MRT,1966,180340653.822049 +Mauritania,MRT,1967,191221777.800889 +Mauritania,MRT,1968,210695183.760251 +Mauritania,MRT,1969,199643444.567995 +Mauritania,MRT,1970,209348253.60877 +Mauritania,MRT,1971,227051054.984972 +Mauritania,MRT,1972,265009395.148159 +Mauritania,MRT,1973,333731874.379051 +Mauritania,MRT,1974,414772351.88069 +Mauritania,MRT,1975,475916514.745785 +Mauritania,MRT,1976,524407931.940588 +Mauritania,MRT,1977,540635389.589072 +Mauritania,MRT,1978,544424605.052283 +Mauritania,MRT,1979,644070364.889076 +Mauritania,MRT,1980,709041452.217718 +Mauritania,MRT,1981,747994681.876653 +Mauritania,MRT,1982,750214410.723584 +Mauritania,MRT,1983,788371855.945127 +Mauritania,MRT,1984,726937320.846135 +Mauritania,MRT,1985,683193885.003343 +Mauritania,MRT,1986,802890746.890756 +Mauritania,MRT,1987,909820553.400741 +Mauritania,MRT,1988,957377507.476686 +Mauritania,MRT,1989,981529400.534373 +Mauritania,MRT,1990,1019600770.6038 +Mauritania,MRT,1991,1443688869.96039 +Mauritania,MRT,1992,1464392416.14671 +Mauritania,MRT,1993,1249944999.42056 +Mauritania,MRT,1994,1315932644.95246 +Mauritania,MRT,1995,1415296704.11812 +Mauritania,MRT,1996,1442598431.0096 +Mauritania,MRT,1997,1401946853.20672 +Mauritania,MRT,1998,1375115534.0733 +Mauritania,MRT,1999,1405662878.85296 +Mauritania,MRT,2000,1293654175.2102 +Mauritania,MRT,2001,1295539448.36484 +Mauritania,MRT,2002,1324426606.62378 +Mauritania,MRT,2003,1563074859.52173 +Mauritania,MRT,2004,1833444740.37736 +Mauritania,MRT,2005,2184444848.97637 +Mauritania,MRT,2006,3040716679.07669 +Mauritania,MRT,2007,3356757497.1208 +Mauritania,MRT,2008,3978425730.72183 +Mauritania,MRT,2009,3670515695.69153 +Mauritania,MRT,2010,4343665119.8875 +Mauritania,MRT,2011,5179689613.50618 +Mauritania,MRT,2012,5225532807.25025 +Mauritania,MRT,2013,5724227536.49393 +Mauritania,MRT,2014,5391475878.08153 +Mauritania,MRT,2015,4844223517.89396 +Mauritania,MRT,2016,4634588338.07171 +Mauritius,MUS,1976,706991274.414428 +Mauritius,MUS,1977,827094668.018707 +Mauritius,MUS,1978,1019630847.11113 +Mauritius,MUS,1979,1216229419.31802 +Mauritius,MUS,1980,1136543003.2664 +Mauritius,MUS,1981,1147192916.68998 +Mauritius,MUS,1982,1082939379.16762 +Mauritius,MUS,1983,1094857357.63954 +Mauritius,MUS,1984,1044928624.74004 +Mauritius,MUS,1985,1080642033.34952 +Mauritius,MUS,1986,1469046114.77455 +Mauritius,MUS,1987,1888754655.15367 +Mauritius,MUS,1988,2143484487.67274 +Mauritius,MUS,1989,2191096860.28669 +Mauritius,MUS,1990,2653480001.34558 +Mauritius,MUS,1991,2856890680.60285 +Mauritius,MUS,1992,3224267547.80508 +Mauritius,MUS,1993,3263368410.01813 +Mauritius,MUS,1994,3558137040.37772 +Mauritius,MUS,1995,4040345933.29231 +Mauritius,MUS,1996,4421943910.49749 +Mauritius,MUS,1997,4187367601.73431 +Mauritius,MUS,1998,4169664285.38681 +Mauritius,MUS,1999,4291172815.63421 +Mauritius,MUS,2000,4582555124.64952 +Mauritius,MUS,2001,4536538210.66761 +Mauritius,MUS,2002,4767303153.99506 +Mauritius,MUS,2003,5609831328.0648 +Mauritius,MUS,2004,6385695187.0102 +Mauritius,MUS,2005,6283803256.01264 +Mauritius,MUS,2006,7028803365.70151 +Mauritius,MUS,2007,8150138757.15741 +Mauritius,MUS,2008,9990370016.30771 +Mauritius,MUS,2009,9128843109.15588 +Mauritius,MUS,2010,10003670690.3497 +Mauritius,MUS,2011,11518393367.2403 +Mauritius,MUS,2012,11668685524.1265 +Mauritius,MUS,2013,12129642296.4425 +Mauritius,MUS,2014,12803445933.5894 +Mauritius,MUS,2015,11681761261.0428 +Mauritius,MUS,2016,12164207329.5437 +Mexico,MEX,1960,13056168000 +Mexico,MEX,1961,14153952000 +Mexico,MEX,1962,15221056000 +Mexico,MEX,1963,16936336000 +Mexico,MEX,1964,20070136000 +Mexico,MEX,1965,21829712000 +Mexico,MEX,1966,24337232000 +Mexico,MEX,1967,26556376000 +Mexico,MEX,1968,29363632000 +Mexico,MEX,1969,32515752000 +Mexico,MEX,1970,35541712000 +Mexico,MEX,1971,39200880000 +Mexico,MEX,1972,45178120000 +Mexico,MEX,1973,55271304000 +Mexico,MEX,1974,71976544000 +Mexico,MEX,1975,88003984000 +Mexico,MEX,1976,89023915584.4156 +Mexico,MEX,1977,81825783185.8407 +Mexico,MEX,1978,102517451754.386 +Mexico,MEX,1979,134540324561.404 +Mexico,MEX,1980,194356826086.957 +Mexico,MEX,1981,250083020408.163 +Mexico,MEX,1982,173720851063.83 +Mexico,MEX,1983,148866910907.577 +Mexico,MEX,1984,175632157330.155 +Mexico,MEX,1985,184473106267.03 +Mexico,MEX,1986,129440194508.009 +Mexico,MEX,1987,140263679436.947 +Mexico,MEX,1988,183144268180.018 +Mexico,MEX,1989,222977035953.687 +Mexico,MEX,1990,262709776007.964 +Mexico,MEX,1991,314453890803.074 +Mexico,MEX,1992,363609256195.677 +Mexico,MEX,1993,503962832199.255 +Mexico,MEX,1994,527318753518.414 +Mexico,MEX,1995,343792792161.261 +Mexico,MEX,1996,397404140458.457 +Mexico,MEX,1997,480554644187.662 +Mexico,MEX,1998,502010250656.743 +Mexico,MEX,1999,579459682649.262 +Mexico,MEX,2000,683647965226.955 +Mexico,MEX,2001,724703603502.349 +Mexico,MEX,2002,741559509631.317 +Mexico,MEX,2003,713284231624.803 +Mexico,MEX,2004,770267585947.191 +Mexico,MEX,2005,866345821213.261 +Mexico,MEX,2006,965281191371.844 +Mexico,MEX,2007,1043471321169.09 +Mexico,MEX,2008,1101275278668.79 +Mexico,MEX,2009,894948748436.748 +Mexico,MEX,2010,1051128603513.77 +Mexico,MEX,2011,1171187519660.64 +Mexico,MEX,2012,1186598324461.82 +Mexico,MEX,2013,1261981728468.52 +Mexico,MEX,2014,1298398654278.73 +Mexico,MEX,2015,1151037122909.08 +Mexico,MEX,2016,1045998068645.15 +"Micronesia, Fed. Sts.",FSM,1983,106500000 +"Micronesia, Fed. Sts.",FSM,1986,112210000 +"Micronesia, Fed. Sts.",FSM,1987,116700000 +"Micronesia, Fed. Sts.",FSM,1988,124700000 +"Micronesia, Fed. Sts.",FSM,1989,135200000 +"Micronesia, Fed. Sts.",FSM,1990,147200000 +"Micronesia, Fed. Sts.",FSM,1991,166200000 +"Micronesia, Fed. Sts.",FSM,1992,178100000 +"Micronesia, Fed. Sts.",FSM,1993,198400000 +"Micronesia, Fed. Sts.",FSM,1994,202500000 +"Micronesia, Fed. Sts.",FSM,1995,222103600 +"Micronesia, Fed. Sts.",FSM,1996,218845700 +"Micronesia, Fed. Sts.",FSM,1997,206900300 +"Micronesia, Fed. Sts.",FSM,1998,219646200 +"Micronesia, Fed. Sts.",FSM,1999,220660500 +"Micronesia, Fed. Sts.",FSM,2000,233226300 +"Micronesia, Fed. Sts.",FSM,2001,240051900 +"Micronesia, Fed. Sts.",FSM,2002,241543400 +"Micronesia, Fed. Sts.",FSM,2003,244991000 +"Micronesia, Fed. Sts.",FSM,2004,239563300 +"Micronesia, Fed. Sts.",FSM,2005,249845600 +"Micronesia, Fed. Sts.",FSM,2006,252991200 +"Micronesia, Fed. Sts.",FSM,2007,255890800 +"Micronesia, Fed. Sts.",FSM,2008,261339600 +"Micronesia, Fed. Sts.",FSM,2009,277510900 +"Micronesia, Fed. Sts.",FSM,2010,294117200 +"Micronesia, Fed. Sts.",FSM,2011,310287500 +"Micronesia, Fed. Sts.",FSM,2012,325835200 +"Micronesia, Fed. Sts.",FSM,2013,315725600 +"Micronesia, Fed. Sts.",FSM,2014,318072000 +"Micronesia, Fed. Sts.",FSM,2015,314971100 +"Micronesia, Fed. Sts.",FSM,2016,322000000 +Moldova,MDA,1995,1752975841.35916 +Moldova,MDA,1996,1695130456.52174 +Moldova,MDA,1997,1930071406.92641 +Moldova,MDA,1998,1639497206.70391 +Moldova,MDA,1999,1170785047.79461 +Moldova,MDA,2000,1288429150.51394 +Moldova,MDA,2001,1480656884.38462 +Moldova,MDA,2002,1661818168.4226 +Moldova,MDA,2003,1980901553.51226 +Moldova,MDA,2004,2598231467.43671 +Moldova,MDA,2005,2988338439.31553 +Moldova,MDA,2006,3408272498.11516 +Moldova,MDA,2007,4401154128.12297 +Moldova,MDA,2008,6054806100.8468 +Moldova,MDA,2009,5439422031.39627 +Moldova,MDA,2010,5811604051.96737 +Moldova,MDA,2011,7015206498.21955 +Moldova,MDA,2012,7284686576.2835 +Moldova,MDA,2013,7985349731.46471 +Moldova,MDA,2014,7983271110.60446 +Moldova,MDA,2015,6512899540.34594 +Moldova,MDA,2016,6749515654.64419 +Monaco,MCO,1970,293073868.023221 +Monaco,MCO,1971,327651487.962757 +Monaco,MCO,1972,402460333.237637 +Monaco,MCO,1973,523552815.119127 +Monaco,MCO,1974,563939670.704419 +Monaco,MCO,1975,711922994.225545 +Monaco,MCO,1976,735339911.935065 +Monaco,MCO,1977,811250927.388998 +Monaco,MCO,1978,1000535735.38751 +Monaco,MCO,1979,1209898293.46372 +Monaco,MCO,1980,1378130995.65913 +Monaco,MCO,1981,1205166025.51592 +Monaco,MCO,1982,1143229071.77943 +Monaco,MCO,1983,1092551781.01486 +Monaco,MCO,1984,1037314956.25083 +Monaco,MCO,1985,1082851076.52158 +Monaco,MCO,1986,1515209588.2378 +Monaco,MCO,1987,1839095595.25655 +Monaco,MCO,1988,2000674667.08261 +Monaco,MCO,1989,2010116851.20284 +Monaco,MCO,1990,2481316053.85316 +Monaco,MCO,1991,2480497547.84881 +Monaco,MCO,1992,2737066955.91266 +Monaco,MCO,1993,2574439973.17387 +Monaco,MCO,1994,2720297738.93904 +Monaco,MCO,1995,3130270918.79061 +Monaco,MCO,1996,3137848783.08404 +Monaco,MCO,1997,2840182191.77105 +Monaco,MCO,1998,2934578788.86478 +Monaco,MCO,1999,2906009307.6651 +Monaco,MCO,2000,2647883820.18625 +Monaco,MCO,2001,2671401082.76436 +Monaco,MCO,2002,2905973022.1746 +Monaco,MCO,2003,3588988600.70294 +Monaco,MCO,2004,4110348444.49411 +Monaco,MCO,2005,4280072625.97622 +Monaco,MCO,2006,4663488363.0977 +Monaco,MCO,2007,5974371695.95045 +Monaco,MCO,2008,6919241412.09365 +Monaco,MCO,2009,5557245122.31576 +Monaco,MCO,2010,5350674803.33858 +Monaco,MCO,2011,6074884388.58937 +Mongolia,MNG,1981,2310099100 +Mongolia,MNG,1982,2552401933.33333 +Mongolia,MNG,1983,2725736633.33333 +Mongolia,MNG,1984,2098734600 +Mongolia,MNG,1985,2186505475 +Mongolia,MNG,1986,2896178866.66667 +Mongolia,MNG,1987,3020611600 +Mongolia,MNG,1988,3204461566.66667 +Mongolia,MNG,1989,3576966800 +Mongolia,MNG,1990,2560785660 +Mongolia,MNG,1991,2379018326.31579 +Mongolia,MNG,1992,1317611863.84977 +Mongolia,MNG,1993,768401634.154573 +Mongolia,MNG,1994,925817092.217484 +Mongolia,MNG,1995,1452165005.2384 +Mongolia,MNG,1996,1345719472.35883 +Mongolia,MNG,1997,1180934202.83801 +Mongolia,MNG,1998,1124440248.9783 +Mongolia,MNG,1999,1057408588.68269 +Mongolia,MNG,2000,1136896123.61298 +Mongolia,MNG,2001,1267997934.3125 +Mongolia,MNG,2002,1396555719.97409 +Mongolia,MNG,2003,1595297355.78349 +Mongolia,MNG,2004,1992066808.09598 +Mongolia,MNG,2005,2523471532.01083 +Mongolia,MNG,2006,3414055566.1138 +Mongolia,MNG,2007,4234999823.30839 +Mongolia,MNG,2008,5623216448.86851 +Mongolia,MNG,2009,4583850367.88972 +Mongolia,MNG,2010,7189481853.10614 +Mongolia,MNG,2011,10409797610.3499 +Mongolia,MNG,2012,12292770631.1967 +Mongolia,MNG,2013,12582122604.1921 +Mongolia,MNG,2014,12226514746.1243 +Mongolia,MNG,2015,11741338841.1321 +Mongolia,MNG,2016,11160356497.9404 +Montenegro,MNE,2000,984279598.325251 +Montenegro,MNE,2001,1159860290.16658 +Montenegro,MNE,2002,1284446123.33554 +Montenegro,MNE,2003,1707678389.68676 +Montenegro,MNE,2004,2073255525.20487 +Montenegro,MNE,2005,2257174480.78597 +Montenegro,MNE,2006,2696020574.58286 +Montenegro,MNE,2007,3668857103.75034 +Montenegro,MNE,2008,4519731946.68229 +Montenegro,MNE,2009,4141382328.42456 +Montenegro,MNE,2010,4139192052.98013 +Montenegro,MNE,2011,4538198498.74896 +Montenegro,MNE,2012,4087724527.81704 +Montenegro,MNE,2013,4464260488.58205 +Montenegro,MNE,2014,4587928884.17142 +Montenegro,MNE,2015,4019889098.36975 +Montenegro,MNE,2016,4173255530.97345 +Morocco,MAR,1960,2037150716.33238 +Morocco,MAR,1961,2025689536.60705 +Morocco,MAR,1962,2379606422.29029 +Morocco,MAR,1963,2657247327.3392 +Morocco,MAR,1964,2798339768.79755 +Morocco,MAR,1965,2948325264.30195 +Morocco,MAR,1966,2876395613.08171 +Morocco,MAR,1967,3046339294.53611 +Morocco,MAR,1968,3271415867.99723 +Morocco,MAR,1969,3651615453.01848 +Morocco,MAR,1970,3956328426.04486 +Morocco,MAR,1971,4356633663.36634 +Morocco,MAR,1972,5074117544.77482 +Morocco,MAR,1973,6242177798.33938 +Morocco,MAR,1974,7675408485.51421 +Morocco,MAR,1975,8984824182.60333 +Morocco,MAR,1976,9584323309.12136 +Morocco,MAR,1977,11049896742.3889 +Morocco,MAR,1978,13236854105.1672 +Morocco,MAR,1979,15912133569.2852 +Morocco,MAR,1980,21728770055.3777 +Morocco,MAR,1981,17788171722.4446 +Morocco,MAR,1982,17692341358.1272 +Morocco,MAR,1983,16251460689.3254 +Morocco,MAR,1984,14824728528.4604 +Morocco,MAR,1985,14991283215.7408 +Morocco,MAR,1986,19462175321.8224 +Morocco,MAR,1987,21765261041.7265 +Morocco,MAR,1988,25705296183.5037 +Morocco,MAR,1989,26314220188.0257 +Morocco,MAR,1990,30180108561.9305 +Morocco,MAR,1991,32285388165.2999 +Morocco,MAR,1992,33711069430.78 +Morocco,MAR,1993,31655473663.8348 +Morocco,MAR,1994,35604137422.5796 +Morocco,MAR,1995,39030285468.3841 +Morocco,MAR,1996,43161452678.4383 +Morocco,MAR,1997,39147844526.0838 +Morocco,MAR,1998,41806219378.6181 +Morocco,MAR,1999,41632027599.8531 +Morocco,MAR,2000,38857251336.3448 +Morocco,MAR,2001,39459581217.3759 +Morocco,MAR,2002,42236836820.6152 +Morocco,MAR,2003,52064058833.9739 +Morocco,MAR,2004,59626020162.3816 +Morocco,MAR,2005,62343022650.8742 +Morocco,MAR,2006,68640825480.9223 +Morocco,MAR,2007,79041294874.4553 +Morocco,MAR,2008,92507257783.5697 +Morocco,MAR,2009,92897320375.8176 +Morocco,MAR,2010,93216746661.5977 +Morocco,MAR,2011,101370474295.109 +Morocco,MAR,2012,98266306615.3632 +Morocco,MAR,2013,106825649872.108 +Morocco,MAR,2014,109881398474.953 +Morocco,MAR,2015,100593283696.732 +Morocco,MAR,2016,101445004812.643 +Mozambique,MOZ,1980,3526287037.03704 +Mozambique,MOZ,1981,3537099150.14164 +Mozambique,MOZ,1982,3612171957.67196 +Mozambique,MOZ,1983,3236430348.25871 +Mozambique,MOZ,1984,3376172169.81132 +Mozambique,MOZ,1985,4456240740.74074 +Mozambique,MOZ,1986,5247193069.30693 +Mozambique,MOZ,1987,2354117303.06158 +Mozambique,MOZ,1988,2093571673.65612 +Mozambique,MOZ,1989,2314159887.23319 +Mozambique,MOZ,1990,2512079324.07706 +Mozambique,MOZ,1991,3263761937.95748 +Mozambique,MOZ,1992,2291175764.66004 +Mozambique,MOZ,1993,2394823061.93212 +Mozambique,MOZ,1994,2460670287.73707 +Mozambique,MOZ,1995,2521738759.58885 +Mozambique,MOZ,1996,3523842274.89662 +Mozambique,MOZ,1997,4227273069.05991 +Mozambique,MOZ,1998,4873242526.06404 +Mozambique,MOZ,1999,5302532113.25156 +Mozambique,MOZ,2000,5016469068.50898 +Mozambique,MOZ,2001,4766928746.6914 +Mozambique,MOZ,2002,5031510908.86055 +Mozambique,MOZ,2003,5597367853.40358 +Mozambique,MOZ,2004,6831808930.39816 +Mozambique,MOZ,2005,7723846194.87446 +Mozambique,MOZ,2006,8312078525.08582 +Mozambique,MOZ,2007,9366742309.49331 +Mozambique,MOZ,2008,11494837053.4061 +Mozambique,MOZ,2009,10911698208.1015 +Mozambique,MOZ,2010,10154238250.1818 +Mozambique,MOZ,2011,13131168011.807 +Mozambique,MOZ,2012,14534278446.3087 +Mozambique,MOZ,2013,16018848990.669 +Mozambique,MOZ,2014,16961127045.8266 +Mozambique,MOZ,2015,14798399861.5582 +Mozambique,MOZ,2016,11014858591.8422 +Myanmar,MMR,2000,8905066163.58643 +Myanmar,MMR,2001,6477790688.22844 +Myanmar,MMR,2002,6777632512.0781 +Myanmar,MMR,2003,10467109977.6717 +Myanmar,MMR,2004,10567354056.4049 +Myanmar,MMR,2005,11986972418.5103 +Myanmar,MMR,2006,14502553709.8303 +Myanmar,MMR,2007,20182477480.5512 +Myanmar,MMR,2008,31862554101.9378 +Myanmar,MMR,2009,36906181380.8127 +Myanmar,MMR,2010,49540813342.4834 +Myanmar,MMR,2011,59977326085.9908 +Myanmar,MMR,2012,59731122170.0865 +Myanmar,MMR,2013,60132854536.7832 +Myanmar,MMR,2014,65574726566.3779 +Myanmar,MMR,2015,62600906116.0987 +Myanmar,MMR,2016,67429590535.8518 +Namibia,NAM,1980,2434884951.20699 +Namibia,NAM,1981,2259179124.88605 +Namibia,NAM,1982,2128089611.34647 +Namibia,NAM,1983,2308102953.05628 +Namibia,NAM,1984,1960567071.10418 +Namibia,NAM,1985,1615776820.56804 +Namibia,NAM,1986,1816754048.14004 +Namibia,NAM,1987,2310454960.70727 +Namibia,NAM,1988,2506554607.43347 +Namibia,NAM,1989,2547340984.48164 +Namibia,NAM,1990,2804379662.19611 +Namibia,NAM,1991,3012742078.00674 +Namibia,NAM,1992,3448326858.34502 +Namibia,NAM,1993,3218475900.48046 +Namibia,NAM,1994,3636645995.26867 +Namibia,NAM,1995,3942478205.72909 +Namibia,NAM,1996,3945340776.40546 +Namibia,NAM,1997,4102648719.61806 +Namibia,NAM,1998,3826527630.55551 +Namibia,NAM,1999,3818954447.99083 +Namibia,NAM,2000,3908661517.62299 +Namibia,NAM,2001,3546783708.12619 +Namibia,NAM,2002,3361251197.73829 +Namibia,NAM,2003,4931312147.21007 +Namibia,NAM,2004,6606858786.01174 +Namibia,NAM,2005,7261333794.60003 +Namibia,NAM,2006,7978734401.53585 +Namibia,NAM,2007,8740865600.24981 +Namibia,NAM,2008,8486721916.9128 +Namibia,NAM,2009,8876191120.76189 +Namibia,NAM,2010,11282192605.0374 +Namibia,NAM,2011,12409629835.6998 +Namibia,NAM,2012,13016272898.9038 +Namibia,NAM,2013,12713366873.4658 +Namibia,NAM,2014,12853963142.8124 +Namibia,NAM,2015,11491507355.6498 +Namibia,NAM,2016,10267157279.9956 +Nauru,NRU,2007,20432742.1126982 +Nauru,NRU,2008,39333572.3247894 +Nauru,NRU,2009,44290951.9252006 +Nauru,NRU,2010,49248810.5726872 +Nauru,NRU,2011,72751801.046087 +Nauru,NRU,2012,103811958.762887 +Nauru,NRU,2013,108601538.461538 +Nauru,NRU,2014,117020381.931693 +Nauru,NRU,2015,100459782.608696 +Nauru,NRU,2016,102060129.577055 +Nepal,NPL,1960,508334413.965087 +Nepal,NPL,1961,531959561.62226 +Nepal,NPL,1962,574091101.194382 +Nepal,NPL,1963,496947904.443033 +Nepal,NPL,1964,496098775.308642 +Nepal,NPL,1965,735267082.294264 +Nepal,NPL,1966,906811943.824649 +Nepal,NPL,1967,841974025.462659 +Nepal,NPL,1968,772228643.405428 +Nepal,NPL,1969,788641965.432099 +Nepal,NPL,1970,865975308.641975 +Nepal,NPL,1971,882765471.604938 +Nepal,NPL,1972,1024098804.93827 +Nepal,NPL,1973,972101724.995368 +Nepal,NPL,1974,1217953546.97604 +Nepal,NPL,1975,1575789254.46938 +Nepal,NPL,1976,1452792989.10865 +Nepal,NPL,1977,1382400000 +Nepal,NPL,1978,1604162497.45945 +Nepal,NPL,1979,1851250008.33333 +Nepal,NPL,1980,1945916583.33333 +Nepal,NPL,1981,2275583316.66667 +Nepal,NPL,1982,2395429852.43076 +Nepal,NPL,1983,2447174803.37791 +Nepal,NPL,1984,2581207387.79709 +Nepal,NPL,1985,2619913955.51556 +Nepal,NPL,1986,2850784523.37711 +Nepal,NPL,1987,2957255379.54315 +Nepal,NPL,1988,3487009748.35638 +Nepal,NPL,1989,3525228153.17361 +Nepal,NPL,1990,3627562402.66027 +Nepal,NPL,1991,3921476084.89072 +Nepal,NPL,1992,3401211581.29176 +Nepal,NPL,1993,3660041666.66667 +Nepal,NPL,1994,4066775510.20408 +Nepal,NPL,1995,4401104417.67068 +Nepal,NPL,1996,4521580381.47139 +Nepal,NPL,1997,4918691916.53516 +Nepal,NPL,1998,4856255044.39064 +Nepal,NPL,1999,5033642384.10596 +Nepal,NPL,2000,5494252207.90502 +Nepal,NPL,2001,6007061224.48979 +Nepal,NPL,2002,6050875806.66403 +Nepal,NPL,2003,6330473096.54071 +Nepal,NPL,2004,7273938314.71988 +Nepal,NPL,2005,8130258041.46706 +Nepal,NPL,2006,9043715355.8881 +Nepal,NPL,2007,10325618017.379 +Nepal,NPL,2008,12545438605.3959 +Nepal,NPL,2009,12854985464.0764 +Nepal,NPL,2010,16002656434.4746 +Nepal,NPL,2011,18913574370.76 +Nepal,NPL,2012,18851513891.066 +Nepal,NPL,2013,19271168018.482 +Nepal,NPL,2014,20002968837.9471 +Nepal,NPL,2015,21313549578.6984 +Nepal,NPL,2016,21143873417.4002 +Netherlands,NLD,1960,12276734172.0828 +Netherlands,NLD,1961,13493833739.9949 +Netherlands,NLD,1962,14647057370.1418 +Netherlands,NLD,1963,15891241386.291 +Netherlands,NLD,1964,18699380731.3465 +Netherlands,NLD,1965,21000586933.2041 +Netherlands,NLD,1966,22867203317.4022 +Netherlands,NLD,1967,25087562181.3218 +Netherlands,NLD,1968,27817605743.2503 +Netherlands,NLD,1969,31503868835.1853 +Netherlands,NLD,1970,37677621537.7123 +Netherlands,NLD,1971,44010160463.6591 +Netherlands,NLD,1972,54008338917.8797 +Netherlands,NLD,1973,70924006306.1643 +Netherlands,NLD,1974,86129928026.8875 +Netherlands,NLD,1975,98970041042.175 +Netherlands,NLD,1976,107775403067.178 +Netherlands,NLD,1977,125395875998.923 +Netherlands,NLD,1978,153870462415.971 +Netherlands,NLD,1979,177376289135.45 +Netherlands,NLD,1980,192661371425.405 +Netherlands,NLD,1981,162039376225.382 +Netherlands,NLD,1982,156456858050.673 +Netherlands,NLD,1983,151487045479.114 +Netherlands,NLD,1984,142075910370.879 +Netherlands,NLD,1985,142009922306.263 +Netherlands,NLD,1986,198298498021.227 +Netherlands,NLD,1987,241918791122.715 +Netherlands,NLD,1988,258567751142.825 +Netherlands,NLD,1989,255039560739.894 +Netherlands,NLD,1990,314267667675.178 +Netherlands,NLD,1991,323320449905.705 +Netherlands,NLD,1992,358330385839.599 +Netherlands,NLD,1993,349037818106.312 +Netherlands,NLD,1994,374291430318.44 +Netherlands,NLD,1995,446528959648.641 +Netherlands,NLD,1996,445704575163.399 +Netherlands,NLD,1997,412199006098.938 +Netherlands,NLD,1998,432476116418.574 +Netherlands,NLD,1999,441975282335.393 +Netherlands,NLD,2000,412807259996.315 +Netherlands,NLD,2001,426573601789.709 +Netherlands,NLD,2002,465368906455.863 +Netherlands,NLD,2003,571863431151.242 +Netherlands,NLD,2004,650532654581.574 +Netherlands,NLD,2005,678533764457.157 +Netherlands,NLD,2006,726649102998.369 +Netherlands,NLD,2007,839419655078.018 +Netherlands,NLD,2008,936228211513.11 +Netherlands,NLD,2009,857932759099.75 +Netherlands,NLD,2010,836389937229.197 +Netherlands,NLD,2011,893757287201.688 +Netherlands,NLD,2012,828946812396.788 +Netherlands,NLD,2013,866680000367.264 +Netherlands,NLD,2014,879635084124.987 +Netherlands,NLD,2015,750318056805.557 +Netherlands,NLD,2016,770845046231.727 +New Caledonia,NCL,1965,159594493.548808 +New Caledonia,NCL,1966,164206537.561675 +New Caledonia,NCL,1967,180036768.87301 +New Caledonia,NCL,1968,215507164.034258 +New Caledonia,NCL,1969,263108834.536684 +New Caledonia,NCL,1970,358815681.903215 +New Caledonia,NCL,1971,413634335.270097 +New Caledonia,NCL,1972,505892512.861927 +New Caledonia,NCL,1973,542294864.81243 +New Caledonia,NCL,1974,637400199.110489 +New Caledonia,NCL,1975,816647865.83143 +New Caledonia,NCL,1976,798310509.647434 +New Caledonia,NCL,1977,837616756.533737 +New Caledonia,NCL,1978,846007597.720396 +New Caledonia,NCL,1979,1047225130.24333 +New Caledonia,NCL,1980,1182457142.60648 +New Caledonia,NCL,1981,972563810.230325 +New Caledonia,NCL,1982,904619629.797268 +New Caledonia,NCL,1983,823832940.450511 +New Caledonia,NCL,1984,796018978.4713 +New Caledonia,NCL,1985,854823821.723177 +New Caledonia,NCL,1986,1201262517.87644 +New Caledonia,NCL,1987,1488113532.28584 +New Caledonia,NCL,1988,2072735787.31779 +New Caledonia,NCL,1989,2185072798.33184 +New Caledonia,NCL,1990,2529310103.83608 +New Caledonia,NCL,1991,2653781596.46008 +New Caledonia,NCL,1992,2923764926.39718 +New Caledonia,NCL,1993,3070161471.04451 +New Caledonia,NCL,1994,3038727617.03901 +New Caledonia,NCL,1995,3628440274.67 +New Caledonia,NCL,1996,3606968433.92682 +New Caledonia,NCL,1997,3291489840.57141 +New Caledonia,NCL,1998,3158806480.26107 +New Caledonia,NCL,1999,3056999988.09146 +New Caledonia,NCL,2000,2682347064.3642 +New Zealand,NZL,1960,5485854791.97096 +New Zealand,NZL,1961,5670064168.21773 +New Zealand,NZL,1962,6077496267.76294 +New Zealand,NZL,1963,6638937283.13963 +New Zealand,NZL,1964,7274144350.81809 +New Zealand,NZL,1965,5654463586.00366 +New Zealand,NZL,1966,5863733230.97616 +New Zealand,NZL,1967,5961418093.53003 +New Zealand,NZL,1968,5180597620.64135 +New Zealand,NZL,1969,5761588761.69421 +New Zealand,NZL,1971,7912290825.15868 +New Zealand,NZL,1972,9567331064.65727 +New Zealand,NZL,1973,12802281897.8712 +New Zealand,NZL,1974,13940981798.1247 +New Zealand,NZL,1975,12861983284.3912 +New Zealand,NZL,1976,13604832424.0062 +New Zealand,NZL,1977,15446825318.4556 +New Zealand,NZL,1978,18530518394.6488 +New Zealand,NZL,1979,20730241410.3977 +New Zealand,NZL,1980,23245512449.3341 +New Zealand,NZL,1981,24417617184.2478 +New Zealand,NZL,1982,24164603058.9949 +New Zealand,NZL,1983,24308622502.6288 +New Zealand,NZL,1984,21665456808.0473 +New Zealand,NZL,1985,24680306905.3708 +New Zealand,NZL,1986,30605196451.2041 +New Zealand,NZL,1987,40377592076.7564 +New Zealand,NZL,1988,45176167471.8196 +New Zealand,NZL,1989,43920222524.7085 +New Zealand,NZL,1990,45495727006.5141 +New Zealand,NZL,1991,42745329732.163 +New Zealand,NZL,1992,41649298170.9911 +New Zealand,NZL,1993,46775067750.6775 +New Zealand,NZL,1994,55315342817.0218 +New Zealand,NZL,1995,63918703506.9075 +New Zealand,NZL,1996,70140835299.0148 +New Zealand,NZL,1997,66074513017.7142 +New Zealand,NZL,1998,56227169851.0448 +New Zealand,NZL,1999,58761741657.5847 +New Zealand,NZL,2000,52623281956.7031 +New Zealand,NZL,2001,53872425916.6248 +New Zealand,NZL,2002,66628222189.3637 +New Zealand,NZL,2003,88250885550.2626 +New Zealand,NZL,2004,103905882352.941 +New Zealand,NZL,2005,114719425473.492 +New Zealand,NZL,2006,111606899682.251 +New Zealand,NZL,2007,137314617476.299 +New Zealand,NZL,2008,133279679482.674 +New Zealand,NZL,2009,121337372727.841 +New Zealand,NZL,2010,146580949348.893 +New Zealand,NZL,2011,168461998741.295 +New Zealand,NZL,2012,176192886551.397 +New Zealand,NZL,2013,190521142196.379 +New Zealand,NZL,2014,200696291789.952 +New Zealand,NZL,2015,175564427552.782 +New Zealand,NZL,2016,185017316092.654 +Nicaragua,NIC,1960,223854666.666667 +Nicaragua,NIC,1961,240524723.428571 +Nicaragua,NIC,1962,265291588.666667 +Nicaragua,NIC,1963,292916241.142857 +Nicaragua,NIC,1964,341973758.857143 +Nicaragua,NIC,1965,566542872.357143 +Nicaragua,NIC,1966,606671444 +Nicaragua,NIC,1967,657171436.714286 +Nicaragua,NIC,1968,695899980.428571 +Nicaragua,NIC,1969,747971449.571429 +Nicaragua,NIC,1970,776585681.071429 +Nicaragua,NIC,1971,826571413.428571 +Nicaragua,NIC,1972,880842890.071429 +Nicaragua,NIC,1973,1093571441.5 +Nicaragua,NIC,1974,1520900045.14286 +Nicaragua,NIC,1975,1590428522.64286 +Nicaragua,NIC,1976,1847871371.71429 +Nicaragua,NIC,1977,2239857060.57143 +Nicaragua,NIC,1978,2142128603.78571 +Nicaragua,NIC,1979,1527852635.63158 +Nicaragua,NIC,1980,2189347367.52632 +Nicaragua,NIC,1981,2448290109.65 +Nicaragua,NIC,1982,2465165179.69565 +Nicaragua,NIC,1983,2743341724.08333 +Nicaragua,NIC,1984,3105517091.41379 +Nicaragua,NIC,1985,2683816288.7907 +Nicaragua,NIC,1986,2885710608.8808 +Nicaragua,NIC,1987,3851213727.67857 +Nicaragua,NIC,1988,2630904261.83247 +Nicaragua,NIC,1989,1013184745.70715 +Nicaragua,NIC,1990,1009455476.05583 +Nicaragua,NIC,1991,1488804123.71134 +Nicaragua,NIC,1992,1792800000 +Nicaragua,NIC,1993,1756454248.36601 +Nicaragua,NIC,1994,3863185119.04762 +Nicaragua,NIC,1995,4140470000 +Nicaragua,NIC,1996,4308351902.78601 +Nicaragua,NIC,1997,4389965590.96538 +Nicaragua,NIC,1998,4635267224.84195 +Nicaragua,NIC,1999,4855717874.68247 +Nicaragua,NIC,2000,5107329007.0922 +Nicaragua,NIC,2001,5323146565.70315 +Nicaragua,NIC,2002,5224213017.54386 +Nicaragua,NIC,2003,5322454925.84746 +Nicaragua,NIC,2004,5795568204.64532 +Nicaragua,NIC,2005,6321335612.22233 +Nicaragua,NIC,2006,6763671610.70006 +Nicaragua,NIC,2007,7423377429.05927 +Nicaragua,NIC,2008,8496965842.2767 +Nicaragua,NIC,2009,8298695144.91507 +Nicaragua,NIC,2010,8758622328.66962 +Nicaragua,NIC,2011,9774316692.15985 +Nicaragua,NIC,2012,10532001129.67 +Nicaragua,NIC,2013,10982972256.3787 +Nicaragua,NIC,2014,11880438824.4494 +Nicaragua,NIC,2015,12747741539.7259 +Nicaragua,NIC,2016,13230844686.858 +Niger,NER,1960,449526872.565561 +Niger,NER,1961,485785231.729353 +Niger,NER,1962,531736599.930736 +Niger,NER,1963,586294879.4719 +Niger,NER,1964,582816396.216401 +Niger,NER,1965,673383510.242124 +Niger,NER,1966,702296079.857695 +Niger,NER,1967,665586872.839162 +Niger,NER,1968,641214226.839012 +Niger,NER,1969,625867984.42818 +Niger,NER,1970,649916621.179857 +Niger,NER,1971,693573704.422866 +Niger,NER,1972,742779659.455167 +Niger,NER,1973,946385104.967731 +Niger,NER,1974,1026137112.43707 +Niger,NER,1975,1048690931.5406 +Niger,NER,1976,1064517600.10051 +Niger,NER,1977,1291458043.7403 +Niger,NER,1978,1774365587.86851 +Niger,NER,1979,2109277663.09748 +Niger,NER,1980,2508524715.79516 +Niger,NER,1981,2170893417.98129 +Niger,NER,1982,2017612217.82752 +Niger,NER,1983,1803099561.08393 +Niger,NER,1984,1461243326.83775 +Niger,NER,1985,1440581653.32328 +Niger,NER,1986,1904097000.74963 +Niger,NER,1987,2233006101.94476 +Niger,NER,1988,2280356194.14559 +Niger,NER,1989,2179567111.0004 +Niger,NER,1990,2480673304.74309 +Niger,NER,1991,2327986215.86356 +Niger,NER,1992,2344987614.27441 +Niger,NER,1993,1606581743.78497 +Niger,NER,1994,1563207224.65066 +Niger,NER,1995,1880803361.68562 +Niger,NER,1996,1987770898.54334 +Niger,NER,1997,1845599608.44272 +Niger,NER,1998,2076737356.67897 +Niger,NER,1999,2018193703.06047 +Niger,NER,2000,1798374468.36362 +Niger,NER,2001,1945327564.65042 +Niger,NER,2002,2170481508.86916 +Niger,NER,2003,2731416346.48158 +Niger,NER,2004,3052898739.4678 +Niger,NER,2005,3405134831.8505 +Niger,NER,2006,3646728060.06463 +Niger,NER,2007,4291363390.91295 +Niger,NER,2008,5403363917.3096 +Niger,NER,2009,5397121856.35204 +Niger,NER,2010,5718589799.24366 +Niger,NER,2011,6409169889.50891 +Niger,NER,2012,6942209594.55433 +Niger,NER,2013,7667951987.6933 +Niger,NER,2014,8245312136.56543 +Niger,NER,2015,7142951342.4223 +Niger,NER,2016,7508986509.27487 +Nigeria,NGA,1960,4196092258.15484 +Nigeria,NGA,1961,4467200335.99328 +Nigeria,NGA,1962,4909302953.94092 +Nigeria,NGA,1963,5165489010.2198 +Nigeria,NGA,1964,5552822483.55033 +Nigeria,NGA,1965,5874422511.54977 +Nigeria,NGA,1966,6366792664.14672 +Nigeria,NGA,1967,5203135937.28125 +Nigeria,NGA,1968,5200895982.08036 +Nigeria,NGA,1969,6634187316.25367 +Nigeria,NGA,1970,12545849083.0183 +Nigeria,NGA,1971,9181769911.50443 +Nigeria,NGA,1972,12274416017.7976 +Nigeria,NGA,1973,15162871287.1287 +Nigeria,NGA,1974,24846641318.1242 +Nigeria,NGA,1975,27778934624.6973 +Nigeria,NGA,1976,36308883248.731 +Nigeria,NGA,1977,36035407725.3219 +Nigeria,NGA,1978,36527862208.7133 +Nigeria,NGA,1979,47259911894.2731 +Nigeria,NGA,1980,64201788122.6054 +Nigeria,NGA,1981,61076493506.4935 +Nigeria,NGA,1982,51397461685.8237 +Nigeria,NGA,1983,35451565749.2355 +Nigeria,NGA,1984,28500815241.471 +Nigeria,NGA,1985,28873977228.1115 +Nigeria,NGA,1986,20721499308.4371 +Nigeria,NGA,1987,24093203444.564 +Nigeria,NGA,1988,23272161396.8853 +Nigeria,NGA,1989,24231168858.7187 +Nigeria,NGA,1990,30757075595.3681 +Nigeria,NGA,1991,27392886872.5547 +Nigeria,NGA,1992,29300903643.0584 +Nigeria,NGA,1993,15789003752.7594 +Nigeria,NGA,1994,18086400535.5777 +Nigeria,NGA,1995,28546958641.2735 +Nigeria,NGA,1996,34987951375 +Nigeria,NGA,1997,35822342617.6978 +Nigeria,NGA,1998,32004613750 +Nigeria,NGA,1999,35870792987.9432 +Nigeria,NGA,2000,46386011231.37 +Nigeria,NGA,2001,44137994251.618 +Nigeria,NGA,2002,59116847821.5797 +Nigeria,NGA,2003,67655813930.0926 +Nigeria,NGA,2004,87845420504.485 +Nigeria,NGA,2005,112248353104.911 +Nigeria,NGA,2006,145429764861.249 +Nigeria,NGA,2007,166451213395.64 +Nigeria,NGA,2008,208064753766.47 +Nigeria,NGA,2009,169481317540.364 +Nigeria,NGA,2010,369062464570.387 +Nigeria,NGA,2011,411743801711.642 +Nigeria,NGA,2012,460953836444.364 +Nigeria,NGA,2013,514966287206.505 +Nigeria,NGA,2014,568498939784.021 +Nigeria,NGA,2015,481066152870.266 +Nigeria,NGA,2016,405082677659.868 +Northern Mariana Islands,MNP,2002,1284000000 +Northern Mariana Islands,MNP,2003,1239000000 +Northern Mariana Islands,MNP,2004,1210000000 +Northern Mariana Islands,MNP,2005,1061000000 +Northern Mariana Islands,MNP,2006,990000000 +Northern Mariana Islands,MNP,2007,938000000 +Northern Mariana Islands,MNP,2008,939000000 +Northern Mariana Islands,MNP,2009,795000000 +Northern Mariana Islands,MNP,2010,799000000 +Northern Mariana Islands,MNP,2011,733000000 +Northern Mariana Islands,MNP,2012,751000000 +Northern Mariana Islands,MNP,2013,780000000 +Northern Mariana Islands,MNP,2014,836000000 +Northern Mariana Islands,MNP,2015,922000000 +Norway,NOR,1960,5163271598.15702 +Norway,NOR,1961,5632460936.54576 +Norway,NOR,1962,6066976682.67364 +Norway,NOR,1963,6510239502.76489 +Norway,NOR,1964,7159202706.48027 +Norway,NOR,1965,8058681060.159 +Norway,NOR,1966,8696460205.3397 +Norway,NOR,1967,9514496703.39762 +Norway,NOR,1968,10159934136.7838 +Norway,NOR,1969,11063065083.4888 +Norway,NOR,1970,12814123115.2613 +Norway,NOR,1971,14583114840.0629 +Norway,NOR,1972,17358610849.701 +Norway,NOR,1973,22534253702.8686 +Norway,NOR,1974,27145693810.1341 +Norway,NOR,1975,32877805200.023 +Norway,NOR,1976,35942270686.3374 +Norway,NOR,1977,41508030431.1074 +Norway,NOR,1978,46523091009.6713 +Norway,NOR,1979,53132244623.9213 +Norway,NOR,1980,64439382896.0156 +Norway,NOR,1981,63596654760.8677 +Norway,NOR,1982,62647195537.6511 +Norway,NOR,1983,61627240831.0948 +Norway,NOR,1984,62057955032.7758 +Norway,NOR,1985,65416879914.3907 +Norway,NOR,1986,78693253275.995 +Norway,NOR,1987,94230055658.6271 +Norway,NOR,1988,101900260856.222 +Norway,NOR,1989,102633789557.535 +Norway,NOR,1990,119791683307.507 +Norway,NOR,1991,121872464483.487 +Norway,NOR,1992,130838040067.584 +Norway,NOR,1993,120579072750.596 +Norway,NOR,1994,127131461119.927 +Norway,NOR,1995,152027402449.804 +Norway,NOR,1996,163517783497.163 +Norway,NOR,1997,161354369892.838 +Norway,NOR,1998,154165219811.533 +Norway,NOR,1999,162286003692.686 +Norway,NOR,2000,171315639982.731 +Norway,NOR,2001,174003247439.305 +Norway,NOR,2002,195418347152.985 +Norway,NOR,2003,228752436371.854 +Norway,NOR,2004,264357494659.388 +Norway,NOR,2005,308722079937.912 +Norway,NOR,2006,345424664369.357 +Norway,NOR,2007,400883873279.083 +Norway,NOR,2008,461946808510.638 +Norway,NOR,2009,386383919342.271 +Norway,NOR,2010,428527064662.898 +Norway,NOR,2011,498156756965.081 +Norway,NOR,2012,509704856037.817 +Norway,NOR,2013,522746212765.957 +Norway,NOR,2014,498339751388.521 +Norway,NOR,2015,386578443732.562 +Norway,NOR,2016,370556666666.667 +Oman,OMN,1965,63287594.5113414 +Oman,OMN,1966,67768132.1758611 +Oman,OMN,1967,107152720.243027 +Oman,OMN,1968,188864890.808735 +Oman,OMN,1969,239980801.535877 +Oman,OMN,1970,256299496.040317 +Oman,OMN,1971,301010587.102984 +Oman,OMN,1972,366857738.40542 +Oman,OMN,1973,483033932.135729 +Oman,OMN,1974,1645917776.49103 +Oman,OMN,1975,2096699189.34569 +Oman,OMN,1976,2560220034.74233 +Oman,OMN,1977,2741169947.88651 +Oman,OMN,1978,2740301389.69311 +Oman,OMN,1979,3733352634.62652 +Oman,OMN,1980,5981760277.93862 +Oman,OMN,1981,7259120150.55009 +Oman,OMN,1982,7554719455.70353 +Oman,OMN,1983,7932541690.79328 +Oman,OMN,1984,8821366531.55762 +Oman,OMN,1985,10005500579.0388 +Oman,OMN,1986,7323822251.3089 +Oman,OMN,1987,7811183094.92848 +Oman,OMN,1988,8386215864.75943 +Oman,OMN,1989,9372171651.49545 +Oman,OMN,1990,11685045513.6541 +Oman,OMN,1991,11341482444.7334 +Oman,OMN,1992,12452275682.7048 +Oman,OMN,1993,12493107932.3797 +Oman,OMN,1994,12918855656.697 +Oman,OMN,1995,13802600780.2341 +Oman,OMN,1996,15277763328.9987 +Oman,OMN,1997,15837451235.3706 +Oman,OMN,1998,14085373211.9636 +Oman,OMN,1999,15710148244.4733 +Oman,OMN,2000,19507412223.6671 +Oman,OMN,2001,19452015604.6814 +Oman,OMN,2002,20142782834.8505 +Oman,OMN,2003,21633810143.0429 +Oman,OMN,2004,24763589076.723 +Oman,OMN,2005,31081924577.3732 +Oman,OMN,2006,37215864759.4278 +Oman,OMN,2007,42085305591.6775 +Oman,OMN,2008,60905331599.4798 +Oman,OMN,2009,48388296488.9467 +Oman,OMN,2010,58641621957.8941 +Oman,OMN,2011,67937307405.122 +Oman,OMN,2012,76689583316.9189 +Oman,OMN,2013,78938585285.6905 +Oman,OMN,2014,81034395037.5246 +Oman,OMN,2015,69831770995.5405 +Oman,OMN,2016,66293368010.4031 +Pakistan,PAK,1960,3707055900.88198 +Pakistan,PAK,1961,4054599181.01638 +Pakistan,PAK,1962,4233095590.0882 +Pakistan,PAK,1963,4540529105.41789 +Pakistan,PAK,1964,5130407727.84544 +Pakistan,PAK,1965,5884712095.75809 +Pakistan,PAK,1966,6466610751.78496 +Pakistan,PAK,1967,7403821902.56195 +Pakistan,PAK,1968,8090088555.2289 +Pakistan,PAK,1969,8632927257.45485 +Pakistan,PAK,1970,10027088849.223 +Pakistan,PAK,1971,10602058189.8362 +Pakistan,PAK,1972,9309109764.07784 +Pakistan,PAK,1973,6324884129.38617 +Pakistan,PAK,1974,8773030424.24242 +Pakistan,PAK,1975,11340000242.4242 +Pakistan,PAK,1976,13338484979.798 +Pakistan,PAK,1977,15126059646.4646 +Pakistan,PAK,1978,17820100626.2626 +Pakistan,PAK,1979,19707979303.0303 +Pakistan,PAK,1980,23689696767.6768 +Pakistan,PAK,1981,28100605515.1515 +Pakistan,PAK,1982,30725972786.7299 +Pakistan,PAK,1983,28691890433.0709 +Pakistan,PAK,1984,31151824658.6524 +Pakistan,PAK,1985,31144920554.0897 +Pakistan,PAK,1986,31899071053.9368 +Pakistan,PAK,1987,33351528115.351 +Pakistan,PAK,1988,38472741737.3968 +Pakistan,PAK,1989,40171019643.3511 +Pakistan,PAK,1990,40010424928.715 +Pakistan,PAK,1991,45451960731.7204 +Pakistan,PAK,1992,48635176852.7673 +Pakistan,PAK,1993,51478304859.5879 +Pakistan,PAK,1994,51894781281.8919 +Pakistan,PAK,1995,60636022422.6176 +Pakistan,PAK,1996,63320122807.1223 +Pakistan,PAK,1997,62433300338.0941 +Pakistan,PAK,1998,62191955814.3478 +Pakistan,PAK,1999,62973855718.8874 +Pakistan,PAK,2000,73952374969.7995 +Pakistan,PAK,2001,72309738921.3329 +Pakistan,PAK,2002,72306820396.2325 +Pakistan,PAK,2003,83244801092.7096 +Pakistan,PAK,2004,97977766197.6724 +Pakistan,PAK,2005,109502102510.883 +Pakistan,PAK,2006,137264061106.043 +Pakistan,PAK,2007,152385716311.916 +Pakistan,PAK,2008,170077814106.305 +Pakistan,PAK,2009,168152775283.032 +Pakistan,PAK,2010,177406854514.885 +Pakistan,PAK,2011,213587413183.996 +Pakistan,PAK,2012,224383620829.57 +Pakistan,PAK,2013,231218567178.979 +Pakistan,PAK,2014,244360888750.807 +Pakistan,PAK,2015,271049886672.733 +Pakistan,PAK,2016,283659980698.255 +Palau,PLW,1990,76888000 +Palau,PLW,1991,83855000 +Palau,PLW,1992,82451000 +Palau,PLW,1993,75907000 +Palau,PLW,1994,83527000 +Palau,PLW,1995,95237000 +Palau,PLW,1996,108203000 +Palau,PLW,1997,113213000 +Palau,PLW,1998,117320000 +Palau,PLW,1999,113485000 +Palau,PLW,2000,149300000 +Palau,PLW,2001,160000000 +Palau,PLW,2002,163500000 +Palau,PLW,2003,159900000 +Palau,PLW,2004,175300000 +Palau,PLW,2005,193300000 +Palau,PLW,2006,194700000 +Palau,PLW,2007,196000000 +Palau,PLW,2008,198100000 +Palau,PLW,2009,186400000 +Palau,PLW,2010,183800000 +Palau,PLW,2011,199900000 +Palau,PLW,2012,214200000 +Palau,PLW,2013,228700000 +Palau,PLW,2014,250900000 +Palau,PLW,2015,287400000 +Palau,PLW,2016,293000000 +Panama,PAN,1960,537147100 +Panama,PAN,1961,599026300 +Panama,PAN,1962,652120900 +Panama,PAN,1963,722784500 +Panama,PAN,1964,776137500 +Panama,PAN,1965,852485300 +Panama,PAN,1966,928833000 +Panama,PAN,1967,1034376400 +Panama,PAN,1968,1112791100 +Panama,PAN,1969,1221305700 +Panama,PAN,1970,1351006400 +Panama,PAN,1971,1523917200 +Panama,PAN,1972,1673411700 +Panama,PAN,1973,1913793400 +Panama,PAN,1974,2188307600 +Panama,PAN,1975,2435304100 +Panama,PAN,1976,2588106000 +Panama,PAN,1977,2738261900 +Panama,PAN,1978,3244558600 +Panama,PAN,1979,3704551600 +Panama,PAN,1980,4614086400 +Panama,PAN,1981,5222421500 +Panama,PAN,1982,5769767900 +Panama,PAN,1983,5923755900 +Panama,PAN,1984,6183387100 +Panama,PAN,1985,6541517100 +Panama,PAN,1986,6797834200 +Panama,PAN,1987,6827665300 +Panama,PAN,1988,5902783400 +Panama,PAN,1989,5918469800 +Panama,PAN,1990,6433967000 +Panama,PAN,1991,7074675500 +Panama,PAN,1992,8042337700 +Panama,PAN,1993,8782585400 +Panama,PAN,1994,9365289800 +Panama,PAN,1995,9573813700 +Panama,PAN,1996,9870494000 +Panama,PAN,1997,10677286100 +Panama,PAN,1998,11575486400 +Panama,PAN,1999,12130252200 +Panama,PAN,2000,12304115000 +Panama,PAN,2001,12502013400 +Panama,PAN,2002,12994310400 +Panama,PAN,2003,13693981200 +Panama,PAN,2004,15013381700 +Panama,PAN,2005,16374393900 +Panama,PAN,2006,18141666300 +Panama,PAN,2007,20958000000 +Panama,PAN,2008,24522200000 +Panama,PAN,2009,26593500000 +Panama,PAN,2010,28917200000 +Panama,PAN,2011,34373820500 +Panama,PAN,2012,39954761200 +Panama,PAN,2013,44856189500 +Panama,PAN,2014,49165773100 +Panama,PAN,2015,52132289700 +Panama,PAN,2016,55187700000 +Papua New Guinea,PNG,1960,230496032.972722 +Papua New Guinea,PNG,1961,244832035.023504 +Papua New Guinea,PNG,1962,261184037.362676 +Papua New Guinea,PNG,1963,275968039.477545 +Papua New Guinea,PNG,1964,305312043.675238 +Papua New Guinea,PNG,1965,344159480.344943 +Papua New Guinea,PNG,1966,390973233.284802 +Papua New Guinea,PNG,1967,441706910.068317 +Papua New Guinea,PNG,1968,485160824.280435 +Papua New Guinea,PNG,1969,551237316.608803 +Papua New Guinea,PNG,1970,645537126.217942 +Papua New Guinea,PNG,1971,717716130.493883 +Papua New Guinea,PNG,1972,858802035.928144 +Papua New Guinea,PNG,1973,1299105240.73285 +Papua New Guinea,PNG,1974,1467346059.99713 +Papua New Guinea,PNG,1975,1356591176.85561 +Papua New Guinea,PNG,1976,1511856584.25833 +Papua New Guinea,PNG,1977,1640763204.44781 +Papua New Guinea,PNG,1978,1947947524.33347 +Papua New Guinea,PNG,1979,2293621944.3664 +Papua New Guinea,PNG,1980,2545983007.89984 +Papua New Guinea,PNG,1981,2498068350.66865 +Papua New Guinea,PNG,1982,2368584969.53284 +Papua New Guinea,PNG,1983,2562492524.81761 +Papua New Guinea,PNG,1984,2552526263.0759 +Papua New Guinea,PNG,1985,2423373088.07358 +Papua New Guinea,PNG,1986,2648033765.69899 +Papua New Guinea,PNG,1987,3143848331.31402 +Papua New Guinea,PNG,1988,3655979702.45646 +Papua New Guinea,PNG,1989,3546460176.99115 +Papua New Guinea,PNG,1990,3219730365 +Papua New Guinea,PNG,1991,3787352286.66667 +Papua New Guinea,PNG,1992,4377984100 +Papua New Guinea,PNG,1993,4974662910 +Papua New Guinea,PNG,1994,5502648500 +Papua New Guinea,PNG,1995,4636113480.00002 +Papua New Guinea,PNG,1996,5155485419.7 +Papua New Guinea,PNG,1997,4936605079.99998 +Papua New Guinea,PNG,1998,3789428160.00001 +Papua New Guinea,PNG,1999,3477060138.33333 +Papua New Guinea,PNG,2000,3521348154.79666 +Papua New Guinea,PNG,2001,3081029665.98233 +Papua New Guinea,PNG,2002,2999542369.42117 +Papua New Guinea,PNG,2003,3536459111.2438 +Papua New Guinea,PNG,2004,3927114465.90565 +Papua New Guinea,PNG,2005,4865971718.29732 +Papua New Guinea,PNG,2006,5527856839.07482 +Papua New Guinea,PNG,2007,6340673793.54534 +Papua New Guinea,PNG,2008,8000074071.33069 +Papua New Guinea,PNG,2009,8105331929.8755 +Papua New Guinea,PNG,2010,9716103408.96554 +Papua New Guinea,PNG,2011,12873049346.2674 +Papua New Guinea,PNG,2012,15391629871.3765 +Papua New Guinea,PNG,2013,15413163674.9224 +Papua New Guinea,PNG,2014,16928680397.4185 +Paraguay,PRY,1965,400129691.269841 +Paraguay,PRY,1966,421700442.063492 +Paraguay,PRY,1967,451524124.603175 +Paraguay,PRY,1968,477012512.698413 +Paraguay,PRY,1969,512728946.031746 +Paraguay,PRY,1970,548758098.412698 +Paraguay,PRY,1971,609047284.920635 +Paraguay,PRY,1972,697291727.777778 +Paraguay,PRY,1973,889357059.52381 +Paraguay,PRY,1974,1199618980.15873 +Paraguay,PRY,1975,1351889403.1746 +Paraguay,PRY,1976,1540820245.2381 +Paraguay,PRY,1977,1912353339.68254 +Paraguay,PRY,1978,2350329157.14286 +Paraguay,PRY,1979,3135123879.36508 +Paraguay,PRY,1980,4094810488.09524 +Paraguay,PRY,1981,5219516810.31746 +Paraguay,PRY,1982,5067450002.20588 +Paraguay,PRY,1983,5237432542.46575 +Paraguay,PRY,1984,4067222369.30652 +Paraguay,PRY,1985,2966234106.19469 +Paraguay,PRY,1986,3439716561.65443 +Paraguay,PRY,1987,3778316380.23952 +Paraguay,PRY,1988,4082625952.73809 +Paraguay,PRY,1989,4599970618.44348 +Paraguay,PRY,1990,5695201563.42495 +Paraguay,PRY,1991,6984367762.90371 +Paraguay,PRY,1992,7157424031.06045 +Paraguay,PRY,1993,7249533620.30614 +Paraguay,PRY,1994,7870982170.98217 +Paraguay,PRY,1995,9062131307.88275 +Paraguay,PRY,1996,9788391732.82899 +Paraguay,PRY,1997,9965225496.5884 +Paraguay,PRY,1998,9024567484.2013 +Paraguay,PRY,1999,8392549702.31511 +Paraguay,PRY,2000,8195993230.74275 +Paraguay,PRY,2001,7662595075.90241 +Paraguay,PRY,2002,6325151760.0669 +Paraguay,PRY,2003,6588103836.34739 +Paraguay,PRY,2004,8033877360.41697 +Paraguay,PRY,2005,8734653809.49561 +Paraguay,PRY,2006,10646157920.3209 +Paraguay,PRY,2007,13794910633.8518 +Paraguay,PRY,2008,18504130752.9922 +Paraguay,PRY,2009,15929902138.1363 +Paraguay,PRY,2010,20030528042.9171 +Paraguay,PRY,2011,25099681460.8943 +Paraguay,PRY,2012,24595319573.7548 +Paraguay,PRY,2013,28965906502.2306 +Paraguay,PRY,2014,30881166852.3116 +Paraguay,PRY,2015,27282581335.7964 +Paraguay,PRY,2016,27440632933.5561 +Peru,PER,1960,2571908062.07692 +Peru,PER,1961,2899654840.36567 +Peru,PER,1962,3286773187.87687 +Peru,PER,1963,3600957771.15299 +Peru,PER,1964,4356913870.23508 +Peru,PER,1965,5166861068.42164 +Peru,PER,1966,6113607728.15672 +Peru,PER,1967,6204253758.57616 +Peru,PER,1968,5736083835.22481 +Peru,PER,1969,6420909789.63824 +Peru,PER,1970,7432223176.77261 +Peru,PER,1971,8289582883.50129 +Peru,PER,1972,9189413409.01292 +Peru,PER,1973,10994381894.7984 +Peru,PER,1974,13858441211.2196 +Peru,PER,1975,16877163792.1284 +Peru,PER,1976,15947709379.6507 +Peru,PER,1977,14620386673.8544 +Peru,PER,1978,12495779622.071 +Peru,PER,1979,15962459447.2168 +Peru,PER,1980,18134029179.6393 +Peru,PER,1981,21649137620.3055 +Peru,PER,1982,21793496819.3379 +Peru,PER,1983,17345624453.6916 +Peru,PER,1984,17599660054.286 +Peru,PER,1985,16548827018.2872 +Peru,PER,1986,15244232957.876 +Peru,PER,1987,20702298396.9717 +Peru,PER,1988,15439408447.2288 +Peru,PER,1989,22499559086.0343 +Peru,PER,1990,26410386669.3609 +Peru,PER,1991,34672122380.7687 +Peru,PER,1992,36139225287.9079 +Peru,PER,1993,35158109999.4973 +Peru,PER,1994,44882079766.8913 +Peru,PER,1995,53312793687.3836 +Peru,PER,1996,55252414130.3019 +Peru,PER,1997,58147522522.5225 +Peru,PER,1998,55501467877.381 +Peru,PER,1999,50187324567.883 +Peru,PER,2000,51744749133.213 +Peru,PER,2001,52030158775.4055 +Peru,PER,2002,54777553515.0809 +Peru,PER,2003,58731030121.8671 +Peru,PER,2004,66768703497.5687 +Peru,PER,2005,76060606060.606 +Peru,PER,2006,88643193061.748 +Peru,PER,2007,102170981144.136 +Peru,PER,2008,120550599815.441 +Peru,PER,2009,120822986521.479 +Peru,PER,2010,147528937028.778 +Peru,PER,2011,171761737046.585 +Peru,PER,2012,192648999090.082 +Peru,PER,2013,201217661645.509 +Peru,PER,2014,201049665375.132 +Peru,PER,2015,189212096470.293 +Peru,PER,2016,192093512185.011 +Philippines,PHL,1960,6684568805.06881 +Philippines,PHL,1961,7256966966.22556 +Philippines,PHL,1962,4399827767.96704 +Philippines,PHL,1963,4875309866.34017 +Philippines,PHL,1964,5271404668.36735 +Philippines,PHL,1965,5784398976.9821 +Philippines,PHL,1966,6371459304.41018 +Philippines,PHL,1967,6809134235.54298 +Philippines,PHL,1968,7591603053.43511 +Philippines,PHL,1969,8408229699.14295 +Philippines,PHL,1970,6687204834.3687 +Philippines,PHL,1971,7408305735.65309 +Philippines,PHL,1972,8017468688.2004 +Philippines,PHL,1973,10082885603.0668 +Philippines,PHL,1974,13781139969.6519 +Philippines,PHL,1975,14893969287.6557 +Philippines,PHL,1976,17097563270.2982 +Philippines,PHL,1977,19648106122.0079 +Philippines,PHL,1978,22706155475.3048 +Philippines,PHL,1979,27502168726.9573 +Philippines,PHL,1980,32450541843.0652 +Philippines,PHL,1981,35646416952.5425 +Philippines,PHL,1982,37140163934.4262 +Philippines,PHL,1983,33212180658.1659 +Philippines,PHL,1984,31408492876.691 +Philippines,PHL,1985,30734335448.9905 +Philippines,PHL,1986,29868339080.8263 +Philippines,PHL,1987,33195933429.6008 +Philippines,PHL,1988,37885440418.6834 +Philippines,PHL,1989,42575183905.5606 +Philippines,PHL,1990,44311593755.7845 +Philippines,PHL,1991,45417561302.2497 +Philippines,PHL,1992,52976344928.9564 +Philippines,PHL,1993,54368083953.1119 +Philippines,PHL,1994,64084460124.4644 +Philippines,PHL,1995,74119987244.5011 +Philippines,PHL,1996,82848140618.0266 +Philippines,PHL,1997,82344260570.6685 +Philippines,PHL,1998,72207025219.4752 +Philippines,PHL,1999,82995147089.9742 +Philippines,PHL,2000,81026297144.2795 +Philippines,PHL,2001,76262072022.215 +Philippines,PHL,2002,81357602950.1818 +Philippines,PHL,2003,83908206456.0645 +Philippines,PHL,2004,91371239764.8818 +Philippines,PHL,2005,103071585462.599 +Philippines,PHL,2006,122210719245.902 +Philippines,PHL,2007,149359920005.894 +Philippines,PHL,2008,174195135053.121 +Philippines,PHL,2009,168334599538.168 +Philippines,PHL,2010,199590774784.581 +Philippines,PHL,2011,224143083706.777 +Philippines,PHL,2012,250092093547.532 +Philippines,PHL,2013,271836123723.678 +Philippines,PHL,2014,284584522898.935 +Philippines,PHL,2015,292774099014.19 +Philippines,PHL,2016,304905406845.908 +Poland,POL,1990,65977749038.438 +Poland,POL,1991,85500935934.9901 +Poland,POL,1992,94337050693.2727 +Poland,POL,1993,96045645026.178 +Poland,POL,1994,110803391516.698 +Poland,POL,1995,142137319587.629 +Poland,POL,1996,159942880456.956 +Poland,POL,1997,159117799530.388 +Poland,POL,1998,174388271853.6 +Poland,POL,1999,169717677900.734 +Poland,POL,2000,171885598582.637 +Poland,POL,2001,190521263343.023 +Poland,POL,2002,198680637254.902 +Poland,POL,2003,217518642324.505 +Poland,POL,2004,255102252843.395 +Poland,POL,2005,306134635593.744 +Poland,POL,2006,344826430298.147 +Poland,POL,2007,429249647594.607 +Poland,POL,2008,533815789473.684 +Poland,POL,2009,439796160379.475 +Poland,POL,2010,479321128909.23 +Poland,POL,2011,528819945375.376 +Poland,POL,2012,500344281382.345 +Poland,POL,2013,524214789307.993 +Poland,POL,2014,545151778520.387 +Poland,POL,2015,477336782066.587 +Poland,POL,2016,469508680416.119 +Portugal,PRT,1960,3193200404.37297 +Portugal,PRT,1961,3417516639.37596 +Portugal,PRT,1962,3668222357.65702 +Portugal,PRT,1963,3905734459.72693 +Portugal,PRT,1964,4235608177.67102 +Portugal,PRT,1965,4687464054.83455 +Portugal,PRT,1966,5135387845.97108 +Portugal,PRT,1967,5740241165.63433 +Portugal,PRT,1968,6354262628.33537 +Portugal,PRT,1969,6969025825.62869 +Portugal,PRT,1970,8109032775.45328 +Portugal,PRT,1971,9202512367.49117 +Portugal,PRT,1972,11240223128.2431 +Portugal,PRT,1973,15092052330.3352 +Portugal,PRT,1974,17514112075.7695 +Portugal,PRT,1975,19349512941.1765 +Portugal,PRT,1976,20334835543.7666 +Portugal,PRT,1977,21441635411.2101 +Portugal,PRT,1978,23489924726.2774 +Portugal,PRT,1979,26625439344.2623 +Portugal,PRT,1980,32899759311.1734 +Portugal,PRT,1981,31980423452.7687 +Portugal,PRT,1982,30530759334.0061 +Portugal,PRT,1983,27242331885.6316 +Portugal,PRT,1984,25220451794.029 +Portugal,PRT,1985,27118476173.6675 +Portugal,PRT,1986,38749715721.7531 +Portugal,PRT,1987,48187667852.5687 +Portugal,PRT,1988,56352797353.7604 +Portugal,PRT,1989,60600056659.0272 +Portugal,PRT,1990,78721607509.4923 +Portugal,PRT,1991,89242382961.0101 +Portugal,PRT,1992,107602689040.689 +Portugal,PRT,1993,95019103603.042 +Portugal,PRT,1994,99698453260.8696 +Portugal,PRT,1995,118133634071.912 +Portugal,PRT,1996,122629812841.175 +Portugal,PRT,1997,117046198970.84 +Portugal,PRT,1998,123981736420.303 +Portugal,PRT,1999,127465545493.288 +Portugal,PRT,2000,118358489957.619 +Portugal,PRT,2001,121545880984.34 +Portugal,PRT,2002,134228697534.35 +Portugal,PRT,2003,164964195259.594 +Portugal,PRT,2004,189187437298.237 +Portugal,PRT,2005,197304513120.259 +Portugal,PRT,2006,208566948939.907 +Portugal,PRT,2007,240169336162.059 +Portugal,PRT,2008,262007590449.685 +Portugal,PRT,2009,243745748819.116 +Portugal,PRT,2010,238303443425.21 +Portugal,PRT,2011,244895101712.451 +Portugal,PRT,2012,216368178659.447 +Portugal,PRT,2013,226073492966.495 +Portugal,PRT,2014,229629822121.601 +Portugal,PRT,2015,199082291239.307 +Portugal,PRT,2016,204564700289.118 +Puerto Rico,PRI,1960,1691900000 +Puerto Rico,PRI,1961,1865100000 +Puerto Rico,PRI,1962,2094400000 +Puerto Rico,PRI,1963,2333600000 +Puerto Rico,PRI,1964,2570500000 +Puerto Rico,PRI,1965,2881500000 +Puerto Rico,PRI,1966,3170500000 +Puerto Rico,PRI,1967,3532700000 +Puerto Rico,PRI,1968,3941700000 +Puerto Rico,PRI,1969,4460700000 +Puerto Rico,PRI,1970,5034700000 +Puerto Rico,PRI,1971,5646800000 +Puerto Rico,PRI,1972,6328900000 +Puerto Rico,PRI,1973,7002400000 +Puerto Rico,PRI,1974,7684800000 +Puerto Rico,PRI,1975,8198300000 +Puerto Rico,PRI,1976,8968600000 +Puerto Rico,PRI,1977,9910900000 +Puerto Rico,PRI,1978,11165000000 +Puerto Rico,PRI,1979,12750000000 +Puerto Rico,PRI,1980,14436100000 +Puerto Rico,PRI,1981,15955700000 +Puerto Rico,PRI,1982,16764200000 +Puerto Rico,PRI,1983,17276600000 +Puerto Rico,PRI,1984,19162600000 +Puerto Rico,PRI,1985,20289200000 +Puerto Rico,PRI,1986,21969400000 +Puerto Rico,PRI,1987,23878000000 +Puerto Rico,PRI,1988,26178400000 +Puerto Rico,PRI,1989,28266800000 +Puerto Rico,PRI,1990,30603919000 +Puerto Rico,PRI,1991,32287031000 +Puerto Rico,PRI,1992,34630430000 +Puerto Rico,PRI,1993,36922456000 +Puerto Rico,PRI,1994,39690630000 +Puerto Rico,PRI,1995,42647331000 +Puerto Rico,PRI,1996,45340835000 +Puerto Rico,PRI,1997,48187039000 +Puerto Rico,PRI,1998,54086409000 +Puerto Rico,PRI,1999,57840954000 +Puerto Rico,PRI,2000,61701810000 +Puerto Rico,PRI,2001,69668635000 +Puerto Rico,PRI,2002,72546194000 +Puerto Rico,PRI,2003,75833996000 +Puerto Rico,PRI,2004,80322313000 +Puerto Rico,PRI,2005,83914521340.5431 +Puerto Rico,PRI,2006,87276164364.6388 +Puerto Rico,PRI,2007,89524131617.1909 +Puerto Rico,PRI,2008,93639316000 +Puerto Rico,PRI,2009,96385638000 +Puerto Rico,PRI,2010,98381268000 +Puerto Rico,PRI,2011,100351670000 +Puerto Rico,PRI,2012,101080738000 +Puerto Rico,PRI,2013,103134778000 +Qatar,QAT,1970,301791301.791302 +Qatar,QAT,1971,387700084.245998 +Qatar,QAT,1972,510259940.720474 +Qatar,QAT,1973,793884368.040437 +Qatar,QAT,1974,2401403227.44085 +Qatar,QAT,1975,2512784033.37828 +Qatar,QAT,1976,3284301332.18953 +Qatar,QAT,1977,3617580171.76055 +Qatar,QAT,1978,4052000412.70087 +Qatar,QAT,1979,5633000318.02401 +Qatar,QAT,1980,7829094613.07082 +Qatar,QAT,1981,8661263763.73626 +Qatar,QAT,1982,7596703214.28571 +Qatar,QAT,1983,6467582307.69231 +Qatar,QAT,1984,6704395824.17583 +Qatar,QAT,1985,6153296456.04396 +Qatar,QAT,1986,5053021950.54945 +Qatar,QAT,1987,5446428681.31868 +Qatar,QAT,1988,6038187032.96703 +Qatar,QAT,1989,6487912087.91209 +Qatar,QAT,1990,7360439423.07692 +Qatar,QAT,1991,6883516483.51648 +Qatar,QAT,1992,7646153983.51648 +Qatar,QAT,1993,7156593653.84615 +Qatar,QAT,1994,7374450769.23077 +Qatar,QAT,1995,8137911978.02198 +Qatar,QAT,1996,9059340384.61539 +Qatar,QAT,1997,11297802115.3846 +Qatar,QAT,1998,10255495027.4725 +Qatar,QAT,1999,12393131868.1319 +Qatar,QAT,2000,17759890109.8901 +Qatar,QAT,2001,17538461538.4615 +Qatar,QAT,2002,19363736263.7363 +Qatar,QAT,2003,23533791208.7912 +Qatar,QAT,2004,31734065934.0659 +Qatar,QAT,2005,44530494505.4945 +Qatar,QAT,2006,60882142857.1428 +Qatar,QAT,2007,79712087912.0879 +Qatar,QAT,2008,115270054945.055 +Qatar,QAT,2009,97798351648.3516 +Qatar,QAT,2010,125122306346.154 +Qatar,QAT,2011,167775274725.275 +Qatar,QAT,2012,186833516483.516 +Qatar,QAT,2013,198727747252.747 +Qatar,QAT,2014,206224725274.725 +Qatar,QAT,2015,164641483516.484 +Qatar,QAT,2016,152468681318.681 +Romania,ROU,1987,38413636363.6364 +Romania,ROU,1988,40809523809.5238 +Romania,ROU,1989,42105263157.8947 +Romania,ROU,1990,38995454545.4545 +Romania,ROU,1991,28998684210.5263 +Romania,ROU,1992,25121666666.6667 +Romania,ROU,1993,26362894736.8421 +Romania,ROU,1994,30074440483.3837 +Romania,ROU,1995,37662075750.123 +Romania,ROU,1996,37182938696.0752 +Romania,ROU,1997,35838588169.6429 +Romania,ROU,1998,41976002703.9207 +Romania,ROU,1999,36183003978.3474 +Romania,ROU,2000,37438527799.5302 +Romania,ROU,2001,40716836998.0386 +Romania,ROU,2002,46174557555.5892 +Romania,ROU,2003,59867801204.8193 +Romania,ROU,2004,76216441462.1442 +Romania,ROU,2005,99697566667.8107 +Romania,ROU,2006,123533036667.853 +Romania,ROU,2007,171536685395.563 +Romania,ROU,2008,208181626900.631 +Romania,ROU,2009,167422949529.4 +Romania,ROU,2010,167998080493.408 +Romania,ROU,2011,185362855081.021 +Romania,ROU,2012,171664638717.49 +Romania,ROU,2013,191549024910.604 +Romania,ROU,2014,199493490982.921 +Romania,ROU,2015,177522705145.168 +Romania,ROU,2016,186690595273.12 +Russian Federation,RUS,1989,506500154001.466 +Russian Federation,RUS,1990,516814258695.568 +Russian Federation,RUS,1991,517962962962.963 +Russian Federation,RUS,1992,460290556900.726 +Russian Federation,RUS,1993,435083713850.837 +Russian Federation,RUS,1994,395077301248.464 +Russian Federation,RUS,1995,395531066563.296 +Russian Federation,RUS,1996,391719993756.828 +Russian Federation,RUS,1997,404926534140.017 +Russian Federation,RUS,1998,270953116950.026 +Russian Federation,RUS,1999,195905767668.562 +Russian Federation,RUS,2000,259708496267.33 +Russian Federation,RUS,2001,306602673980.117 +Russian Federation,RUS,2002,345110438692.185 +Russian Federation,RUS,2003,430347770731.787 +Russian Federation,RUS,2004,591016690742.798 +Russian Federation,RUS,2005,764017107992.391 +Russian Federation,RUS,2006,989930542278.695 +Russian Federation,RUS,2007,1299705247685.76 +Russian Federation,RUS,2008,1660844408499.61 +Russian Federation,RUS,2009,1222643696991.85 +Russian Federation,RUS,2010,1524916112078.87 +Russian Federation,RUS,2011,2031768558635.85 +Russian Federation,RUS,2012,2170143623037.67 +Russian Federation,RUS,2013,2230625004653.55 +Russian Federation,RUS,2014,2063662281005.13 +Russian Federation,RUS,2015,1365865245098.18 +Russian Federation,RUS,2016,1283162348132.89 +Rwanda,RWA,1960,119000024 +Rwanda,RWA,1961,122000016 +Rwanda,RWA,1962,125000008 +Rwanda,RWA,1963,128000000 +Rwanda,RWA,1964,129999994 +Rwanda,RWA,1965,148799980 +Rwanda,RWA,1966,124525702.857143 +Rwanda,RWA,1967,159560018 +Rwanda,RWA,1968,172200018 +Rwanda,RWA,1969,188700037 +Rwanda,RWA,1970,219900006 +Rwanda,RWA,1971,222952578.196381 +Rwanda,RWA,1972,246457838.336681 +Rwanda,RWA,1973,290746157.145921 +Rwanda,RWA,1974,308458423.183854 +Rwanda,RWA,1975,571863295.740122 +Rwanda,RWA,1976,637754162.101094 +Rwanda,RWA,1977,746650558.55469 +Rwanda,RWA,1978,905709147.27019 +Rwanda,RWA,1979,1109346220.52885 +Rwanda,RWA,1980,1254765349.93185 +Rwanda,RWA,1981,1407062607.63214 +Rwanda,RWA,1982,1407242640.23211 +Rwanda,RWA,1983,1479688125.8852 +Rwanda,RWA,1984,1587412957.22263 +Rwanda,RWA,1985,1715625839.17973 +Rwanda,RWA,1986,1944711061.30888 +Rwanda,RWA,1987,2157434025.16467 +Rwanda,RWA,1988,2395493877.51365 +Rwanda,RWA,1989,2405021932.89997 +Rwanda,RWA,1990,2550185618.14774 +Rwanda,RWA,1991,1911600969.76612 +Rwanda,RWA,1992,2029026704.02707 +Rwanda,RWA,1993,1971525998.87685 +Rwanda,RWA,1994,753636370.454546 +Rwanda,RWA,1995,1293535010.94467 +Rwanda,RWA,1996,1382334879.40812 +Rwanda,RWA,1997,1851558301.7002 +Rwanda,RWA,1998,1989343495.21844 +Rwanda,RWA,1999,1817655328.06755 +Rwanda,RWA,2000,1734938264.47371 +Rwanda,RWA,2001,1674685094.01639 +Rwanda,RWA,2002,1677447150.10691 +Rwanda,RWA,2003,1845979298.99285 +Rwanda,RWA,2004,2089188828.797 +Rwanda,RWA,2005,2581465863.87859 +Rwanda,RWA,2006,3152016556.51526 +Rwanda,RWA,2007,3824811913.22869 +Rwanda,RWA,2008,4860576609.21568 +Rwanda,RWA,2009,5379378135.44102 +Rwanda,RWA,2010,5774003744.2708 +Rwanda,RWA,2011,6491683831.5094 +Rwanda,RWA,2012,7315702176.36442 +Rwanda,RWA,2013,7622526429.08839 +Rwanda,RWA,2014,8016288347.03577 +Rwanda,RWA,2015,8261034257.63248 +Rwanda,RWA,2016,8376048904.58291 +Samoa,WSM,1982,121221651.619316 +Samoa,WSM,1983,111862823.574979 +Samoa,WSM,1984,109200934.328518 +Samoa,WSM,1985,95572172.9835657 +Samoa,WSM,1986,100947848.64478 +Samoa,WSM,1987,111713922.141578 +Samoa,WSM,1988,133016065.416065 +Samoa,WSM,1989,122888609.715243 +Samoa,WSM,1990,125766269.755358 +Samoa,WSM,1991,125597205.422315 +Samoa,WSM,1992,132303041.36253 +Samoa,WSM,1993,133122897.196262 +Samoa,WSM,1994,221098106.508876 +Samoa,WSM,1995,224865731.381903 +Samoa,WSM,1996,249908970.658971 +Samoa,WSM,1997,285475591.89651 +Samoa,WSM,1998,269481523.200465 +Samoa,WSM,1999,258833766.580017 +Samoa,WSM,2000,269019710.327456 +Samoa,WSM,2001,273088357.1637 +Samoa,WSM,2002,288078881.433056 +Samoa,WSM,2003,338838639.378435 +Samoa,WSM,2004,420320176.359437 +Samoa,WSM,2005,462644663.06818 +Samoa,WSM,2006,508505414.405727 +Samoa,WSM,2007,550967295.278082 +Samoa,WSM,2008,644143266.155792 +Samoa,WSM,2009,560967765.481746 +Samoa,WSM,2010,643056627.690783 +Samoa,WSM,2011,739777274.127838 +Samoa,WSM,2012,801152293.280623 +Samoa,WSM,2013,804816205.686687 +Samoa,WSM,2014,803574789.064072 +Samoa,WSM,2015,803976511.515065 +Samoa,WSM,2016,785916937.388673 +San Marino,SMR,1999,853373879.731819 +San Marino,SMR,2000,773907642.414748 +San Marino,SMR,2001,815205233.062791 +San Marino,SMR,2002,879957209.923907 +San Marino,SMR,2003,1122981525.35502 +San Marino,SMR,2004,1317357834.61634 +San Marino,SMR,2005,1375416604.48689 +San Marino,SMR,2006,1469000145.311 +San Marino,SMR,2007,1687567364.11695 +San Marino,SMR,2008,1899879955.48332 +Sao Tome and Principe,STP,2001,72230284.4325876 +Sao Tome and Principe,STP,2002,80531992.1217606 +Sao Tome and Principe,STP,2003,96343906.4298042 +Sao Tome and Principe,STP,2004,105360801.941831 +Sao Tome and Principe,STP,2005,126194166.230985 +Sao Tome and Principe,STP,2006,134441116.924998 +Sao Tome and Principe,STP,2007,145827429.572302 +Sao Tome and Principe,STP,2008,188021168.8418 +Sao Tome and Principe,STP,2009,187821029.033169 +Sao Tome and Principe,STP,2010,197454053.145088 +Sao Tome and Principe,STP,2011,233213522.645348 +Sao Tome and Principe,STP,2012,252560557.083061 +Sao Tome and Principe,STP,2013,302925489.683914 +Sao Tome and Principe,STP,2014,348463457.918686 +Sao Tome and Principe,STP,2015,317696178.684618 +Sao Tome and Principe,STP,2016,351054248.477335 +Saudi Arabia,SAU,1968,4187777711.11111 +Saudi Arabia,SAU,1969,4485777644.44444 +Saudi Arabia,SAU,1970,5377333333.33333 +Saudi Arabia,SAU,1971,7184853347.5974 +Saudi Arabia,SAU,1972,9664157498.5524 +Saudi Arabia,SAU,1973,14947391140.1284 +Saudi Arabia,SAU,1974,45412957746.4789 +Saudi Arabia,SAU,1975,46773368205.5947 +Saudi Arabia,SAU,1976,64005665722.3796 +Saudi Arabia,SAU,1977,74188249978.724 +Saudi Arabia,SAU,1978,80265619484.6452 +Saudi Arabia,SAU,1979,111859676267.555 +Saudi Arabia,SAU,1980,164541738058.737 +Saudi Arabia,SAU,1981,184291796008.869 +Saudi Arabia,SAU,1982,153239017560.236 +Saudi Arabia,SAU,1983,129171635311.143 +Saudi Arabia,SAU,1984,119624858115.778 +Saudi Arabia,SAU,1985,103897846493.65 +Saudi Arabia,SAU,1986,86961922765.3254 +Saudi Arabia,SAU,1987,85695861148.1976 +Saudi Arabia,SAU,1988,88256074766.3551 +Saudi Arabia,SAU,1989,95344459279.0387 +Saudi Arabia,SAU,1990,117630271802.48 +Saudi Arabia,SAU,1991,132223268484.752 +Saudi Arabia,SAU,1992,137087876662.752 +Saudi Arabia,SAU,1993,132967901424.382 +Saudi Arabia,SAU,1994,135174886501.234 +Saudi Arabia,SAU,1995,143343036351.096 +Saudi Arabia,SAU,1996,158662398750.805 +Saudi Arabia,SAU,1997,165963557420.458 +Saudi Arabia,SAU,1998,146775498092.612 +Saudi Arabia,SAU,1999,161716960000 +Saudi Arabia,SAU,2000,189514926222.667 +Saudi Arabia,SAU,2001,184137469724.863 +Saudi Arabia,SAU,2002,189605920240.516 +Saudi Arabia,SAU,2003,215807655244.424 +Saudi Arabia,SAU,2004,258742133333.333 +Saudi Arabia,SAU,2005,328459608764.111 +Saudi Arabia,SAU,2006,376900133511.348 +Saudi Arabia,SAU,2007,415964509673.115 +Saudi Arabia,SAU,2008,519796800000 +Saudi Arabia,SAU,2009,429097866666.667 +Saudi Arabia,SAU,2010,528207200000 +Saudi Arabia,SAU,2011,671238840108.229 +Saudi Arabia,SAU,2012,735974843348.664 +Saudi Arabia,SAU,2013,746647127407.619 +Saudi Arabia,SAU,2014,756350347320.381 +Saudi Arabia,SAU,2015,654269902888.715 +Saudi Arabia,SAU,2016,646438380568.715 +Senegal,SEN,1960,792824707.345294 +Senegal,SEN,1961,836493109.152284 +Senegal,SEN,1962,857425916.243935 +Senegal,SEN,1963,886387156.125059 +Senegal,SEN,1964,939145851.154484 +Senegal,SEN,1965,955834893.28571 +Senegal,SEN,1966,984942988.068955 +Senegal,SEN,1967,984605369.32995 +Senegal,SEN,1968,1034293645.25718 +Senegal,SEN,1969,983621024.109038 +Senegal,SEN,1970,1024832915.04328 +Senegal,SEN,1971,1058120427.15534 +Senegal,SEN,1972,1280328245.00174 +Senegal,SEN,1973,1471913473.60034 +Senegal,SEN,1974,1658273721.28587 +Senegal,SEN,1975,2235746644.74234 +Senegal,SEN,1976,2266860655.65881 +Senegal,SEN,1977,2320786490.70314 +Senegal,SEN,1978,2591178368.03735 +Senegal,SEN,1979,3226678628.31043 +Senegal,SEN,1980,3503282102.95741 +Senegal,SEN,1981,3176771103.46059 +Senegal,SEN,1982,3109677455.66655 +Senegal,SEN,1983,2774199193.31559 +Senegal,SEN,1984,2705535756.06004 +Senegal,SEN,1985,2962199835.95355 +Senegal,SEN,1986,4189860416.18118 +Senegal,SEN,1987,5040708115.08482 +Senegal,SEN,1988,4985153202.5374 +Senegal,SEN,1989,4913065110.53161 +Senegal,SEN,1990,5716644272.04692 +Senegal,SEN,1991,5617236032.86556 +Senegal,SEN,1992,6004885321.34354 +Senegal,SEN,1993,5678827998.8247 +Senegal,SEN,1994,3877196914.93966 +Senegal,SEN,1995,4878719133.22771 +Senegal,SEN,1996,5065830414.04947 +Senegal,SEN,1997,4672503920.19866 +Senegal,SEN,1998,5030344074.0413 +Senegal,SEN,1999,5144045359.98185 +Senegal,SEN,2000,4679604753.55711 +Senegal,SEN,2001,4877602059.50983 +Senegal,SEN,2002,5333862371.27113 +Senegal,SEN,2003,6858952880.10003 +Senegal,SEN,2004,8031344381.09898 +Senegal,SEN,2005,8707015771.00113 +Senegal,SEN,2006,9358710935.43366 +Senegal,SEN,2007,11284603070.5653 +Senegal,SEN,2008,13428461873.5568 +Senegal,SEN,2009,12809044977.5918 +Senegal,SEN,2010,12937300245.1506 +Senegal,SEN,2011,14368348214.2024 +Senegal,SEN,2012,14202389641.9262 +Senegal,SEN,2013,14810978041.4667 +Senegal,SEN,2014,15308965398.5779 +Senegal,SEN,2015,13609978076.4224 +Senegal,SEN,2016,14765462631.3216 +Serbia,SRB,1995,16750000000 +Serbia,SRB,1996,20948677839.851 +Serbia,SRB,1997,24147996549.5662 +Serbia,SRB,1998,18284194680.3844 +Serbia,SRB,1999,18409364146.9794 +Serbia,SRB,2000,6540247190.33529 +Serbia,SRB,2001,12267175481.2542 +Serbia,SRB,2002,16116843146.4806 +Serbia,SRB,2003,21188704081.2428 +Serbia,SRB,2004,24861483280.6339 +Serbia,SRB,2005,26252007830.4639 +Serbia,SRB,2006,30607991862.4843 +Serbia,SRB,2007,40289556656.1455 +Serbia,SRB,2008,49259526052.7426 +Serbia,SRB,2009,42616653299.9115 +Serbia,SRB,2010,39460357730.5224 +Serbia,SRB,2011,46466728666.6103 +Serbia,SRB,2012,40742313861.1374 +Serbia,SRB,2013,45519650911.4138 +Serbia,SRB,2014,44210806365.6817 +Serbia,SRB,2015,37160332465.1645 +Serbia,SRB,2016,37745114708.3113 +Seychelles,SYC,1960,12012025.2477875 +Seychelles,SYC,1961,11592024.3649978 +Seychelles,SYC,1962,12642026.5719722 +Seychelles,SYC,1963,13923029.264481 +Seychelles,SYC,1964,15393032.3542452 +Seychelles,SYC,1965,15603032.7956401 +Seychelles,SYC,1966,16443034.5612196 +Seychelles,SYC,1967,16632032.8138977 +Seychelles,SYC,1968,16074027.3495878 +Seychelles,SYC,1969,16452027.9927472 +Seychelles,SYC,1970,18432031.3616773 +Seychelles,SYC,1971,21965951.7214804 +Seychelles,SYC,1972,30645121.0127585 +Seychelles,SYC,1973,36896278.223337 +Seychelles,SYC,1974,43134498.6932177 +Seychelles,SYC,1975,47803145.9560303 +Seychelles,SYC,1976,49278979.547035 +Seychelles,SYC,1977,64526398.6582547 +Seychelles,SYC,1978,85552369.9145942 +Seychelles,SYC,1979,127261099.24396 +Seychelles,SYC,1980,147357222.779802 +Seychelles,SYC,1981,154902869.02139 +Seychelles,SYC,1982,147912069.766502 +Seychelles,SYC,1983,146712850.50997 +Seychelles,SYC,1984,151313241.983564 +Seychelles,SYC,1985,168887539.130029 +Seychelles,SYC,1986,207850623.638215 +Seychelles,SYC,1987,249267039.781191 +Seychelles,SYC,1988,283828769.031683 +Seychelles,SYC,1989,304832867.395046 +Seychelles,SYC,1990,368584758.942457 +Seychelles,SYC,1991,374359556.084926 +Seychelles,SYC,1992,433667193.814795 +Seychelles,SYC,1993,473916819.453826 +Seychelles,SYC,1994,486451204.557142 +Seychelles,SYC,1995,508221508.221508 +Seychelles,SYC,1996,503068472.20266 +Seychelles,SYC,1997,562958836.519905 +Seychelles,SYC,1998,608369282.225727 +Seychelles,SYC,1999,622985493.682733 +Seychelles,SYC,2000,614879764.780006 +Seychelles,SYC,2001,622262057.191635 +Seychelles,SYC,2002,697518248.175182 +Seychelles,SYC,2003,705704816.042365 +Seychelles,SYC,2004,839319927.272727 +Seychelles,SYC,2005,919103254.545455 +Seychelles,SYC,2006,1016418229.25159 +Seychelles,SYC,2007,1033561654.0568 +Seychelles,SYC,2008,967199593.960157 +Seychelles,SYC,2009,847397850.094417 +Seychelles,SYC,2010,969936525.298729 +Seychelles,SYC,2011,1065826669.89742 +Seychelles,SYC,2012,1134267367.19206 +Seychelles,SYC,2013,1411061260.70839 +Seychelles,SYC,2014,1422530791.5588 +Seychelles,SYC,2015,1437722206.38754 +Seychelles,SYC,2016,1427323889.0961 +Sierra Leone,SLE,1960,322009471.57364 +Sierra Leone,SLE,1961,327834680.563822 +Sierra Leone,SLE,1962,342721579.824661 +Sierra Leone,SLE,1963,348546952.141512 +Sierra Leone,SLE,1964,371848114.755577 +Sierra Leone,SLE,1965,359379856.248057 +Sierra Leone,SLE,1966,375479849.80806 +Sierra Leone,SLE,1967,348795303.000385 +Sierra Leone,SLE,1968,329860091.944037 +Sierra Leone,SLE,1969,408690163.476065 +Sierra Leone,SLE,1970,434410373.76415 +Sierra Leone,SLE,1971,419549425.077086 +Sierra Leone,SLE,1972,465381089.98454 +Sierra Leone,SLE,1973,575230234.387058 +Sierra Leone,SLE,1974,648590642.939888 +Sierra Leone,SLE,1975,679335901.117451 +Sierra Leone,SLE,1976,594895672.333848 +Sierra Leone,SLE,1977,691777758.395115 +Sierra Leone,SLE,1978,960728338.93643 +Sierra Leone,SLE,1979,1109374722.08294 +Sierra Leone,SLE,1980,1100685844.92284 +Sierra Leone,SLE,1981,1114830471.91787 +Sierra Leone,SLE,1982,1295361885.92419 +Sierra Leone,SLE,1983,995104305.347074 +Sierra Leone,SLE,1984,1087471861.98928 +Sierra Leone,SLE,1985,856890498.625834 +Sierra Leone,SLE,1986,490181456.62441 +Sierra Leone,SLE,1987,701307602.28443 +Sierra Leone,SLE,1988,1055083945.37738 +Sierra Leone,SLE,1989,932974411.917142 +Sierra Leone,SLE,1990,649644826.800447 +Sierra Leone,SLE,1991,779981458.921489 +Sierra Leone,SLE,1992,679997997.597117 +Sierra Leone,SLE,1993,768812334.801762 +Sierra Leone,SLE,1994,911915970.683484 +Sierra Leone,SLE,1995,870758739.40678 +Sierra Leone,SLE,1996,941742152.709895 +Sierra Leone,SLE,1997,850218033.622007 +Sierra Leone,SLE,1998,672375927.347148 +Sierra Leone,SLE,1999,669384768.87263 +Sierra Leone,SLE,2000,635874002.198748 +Sierra Leone,SLE,2001,1079478387.83576 +Sierra Leone,SLE,2002,1239004287.75607 +Sierra Leone,SLE,2003,1371442565.69701 +Sierra Leone,SLE,2004,1431208677.30352 +Sierra Leone,SLE,2005,1627854494.80246 +Sierra Leone,SLE,2006,1885112201.85278 +Sierra Leone,SLE,2007,2158496872.85796 +Sierra Leone,SLE,2008,2505458705.03338 +Sierra Leone,SLE,2009,2489985963.16808 +Sierra Leone,SLE,2010,2616610911.07222 +Sierra Leone,SLE,2011,2942546781.04548 +Sierra Leone,SLE,2012,3801862611.36414 +Sierra Leone,SLE,2013,4920343194.99339 +Sierra Leone,SLE,2014,5015157815.73406 +Sierra Leone,SLE,2015,4251779857.0134 +Sierra Leone,SLE,2016,3668876080.33846 +Singapore,SGP,1960,704462302.365086 +Singapore,SGP,1961,764308114.464916 +Singapore,SGP,1962,825885273.748857 +Singapore,SGP,1963,917222004.442702 +Singapore,SGP,1964,893734483.209199 +Singapore,SGP,1965,974193126.878348 +Singapore,SGP,1966,1095910100.61414 +Singapore,SGP,1967,1237423232.7192 +Singapore,SGP,1968,1425029400.2352 +Singapore,SGP,1969,1659055272.44218 +Singapore,SGP,1970,1919508689.40285 +Singapore,SGP,1971,2262544100.3528 +Singapore,SGP,1972,2719900350.73917 +Singapore,SGP,1973,3693760000 +Singapore,SGP,1974,5216773825.99496 +Singapore,SGP,1975,5633386679.7981 +Singapore,SGP,1976,6326445409.69089 +Singapore,SGP,1977,6617532782.90432 +Singapore,SGP,1978,7515823563.17127 +Singapore,SGP,1979,9294635004.39754 +Singapore,SGP,1980,11893405683.8039 +Singapore,SGP,1981,14171819540.4446 +Singapore,SGP,1982,16078856439.627 +Singapore,SGP,1983,17775280373.8318 +Singapore,SGP,1984,19735920492.1912 +Singapore,SGP,1985,19138296376.1661 +Singapore,SGP,1986,18569292304.8952 +Singapore,SGP,1987,20897630201.1573 +Singapore,SGP,1988,25337226970.5603 +Singapore,SGP,1989,30423573842.1785 +Singapore,SGP,1990,36152027893.1446 +Singapore,SGP,1991,45474442836.4689 +Singapore,SGP,1992,52156414978.5144 +Singapore,SGP,1993,60644572348.0629 +Singapore,SGP,1994,73777792326.8299 +Singapore,SGP,1995,87890009877.24 +Singapore,SGP,1996,96403758865.2482 +Singapore,SGP,1997,100163995150.862 +Singapore,SGP,1998,85707636233.2696 +Singapore,SGP,1999,86283126843.6578 +Singapore,SGP,2000,95833932714.6172 +Singapore,SGP,2001,89286208628.6767 +Singapore,SGP,2002,91941192896.2359 +Singapore,SGP,2003,97001377568.5914 +Singapore,SGP,2004,114188557567.152 +Singapore,SGP,2005,127417688055.756 +Singapore,SGP,2006,147797218201.271 +Singapore,SGP,2007,179981288567.447 +Singapore,SGP,2008,192225881687.752 +Singapore,SGP,2009,192408387762.118 +Singapore,SGP,2010,236421782178.218 +Singapore,SGP,2011,275599459373.509 +Singapore,SGP,2012,289162118908.538 +Singapore,SGP,2013,302510668904.339 +Singapore,SGP,2014,308142766948.149 +Singapore,SGP,2015,296840704102.415 +Singapore,SGP,2016,296965712342.019 +Slovak Republic,SVK,1990,12694544692.7374 +Slovak Republic,SVK,1991,14213045493.8806 +Slovak Republic,SVK,1992,15431288006.2104 +Slovak Republic,SVK,1993,16452201100.9604 +Slovak Republic,SVK,1994,20079363625.5784 +Slovak Republic,SVK,1995,25733043137.2549 +Slovak Republic,SVK,1996,27821913814.9556 +Slovak Republic,SVK,1997,27660149541.1805 +Slovak Republic,SVK,1998,29828899205.7277 +Slovak Republic,SVK,1999,30415095887.492 +Slovak Republic,SVK,2000,29114875621.8905 +Slovak Republic,SVK,2001,30703017449.6644 +Slovak Republic,SVK,2002,35083608130.9994 +Slovak Republic,SVK,2003,46731767494.3567 +Slovak Republic,SVK,2004,57240535137.8197 +Slovak Republic,SVK,2005,62697540106.9519 +Slovak Republic,SVK,2006,70596729394.0534 +Slovak Republic,SVK,2007,86304245825.349 +Slovak Republic,SVK,2008,100324627215.468 +Slovak Republic,SVK,2009,88945625173.6593 +Slovak Republic,SVK,2010,89501012915.7314 +Slovak Republic,SVK,2011,98181259740.0919 +Slovak Republic,SVK,2012,93413992955.8972 +Slovak Republic,SVK,2013,98478349315.3252 +Slovak Republic,SVK,2014,100760596988.198 +Slovak Republic,SVK,2015,87267593788.1986 +Slovak Republic,SVK,2016,89551834322.5767 +Slovenia,SVN,1995,21273055398.3017 +Slovenia,SVN,1996,21480023016.9972 +Slovenia,SVN,1997,20749140606.2425 +Slovenia,SVN,1998,22125435372.187 +Slovenia,SVN,1999,22689994990.1121 +Slovenia,SVN,2000,20342201356.0052 +Slovenia,SVN,2001,20875387068.1145 +Slovenia,SVN,2002,23563576758.1047 +Slovenia,SVN,2003,29697448108.2957 +Slovenia,SVN,2004,34470227453.9113 +Slovenia,SVN,2005,36346974008.2079 +Slovenia,SVN,2006,39587732028.6037 +Slovenia,SVN,2007,48114688201.4782 +Slovenia,SVN,2008,55589849128.4605 +Slovenia,SVN,2009,50244793831.6199 +Slovenia,SVN,2010,48013606745.4803 +Slovenia,SVN,2011,51290792018.1074 +Slovenia,SVN,2012,46258247574.7506 +Slovenia,SVN,2013,47688566993.1107 +Slovenia,SVN,2014,49530147015.8794 +Slovenia,SVN,2015,42776716631.0769 +Slovenia,SVN,2016,43990635176.0523 +Solomon Islands,SLB,1967,25203524.0325638 +Solomon Islands,SLB,1968,28084252.7582748 +Solomon Islands,SLB,1969,28606411.398041 +Solomon Islands,SLB,1971,50056882.8213879 +Solomon Islands,SLB,1972,40606712.050639 +Solomon Islands,SLB,1973,55272108.8435374 +Solomon Islands,SLB,1974,84539332.282562 +Solomon Islands,SLB,1975,74617096.4785967 +Solomon Islands,SLB,1976,83099107.9066357 +Solomon Islands,SLB,1977,93147039.2548237 +Solomon Islands,SLB,1978,111022089.96223 +Solomon Islands,SLB,1979,151270207.852194 +Solomon Islands,SLB,1980,168715353.097132 +Solomon Islands,SLB,1981,187313261.319237 +Solomon Islands,SLB,1982,188446092.06055 +Solomon Islands,SLB,1983,180219397.527425 +Solomon Islands,SLB,1984,252806783.386983 +Solomon Islands,SLB,1985,232306861.156132 +Solomon Islands,SLB,1986,210737869.652598 +Solomon Islands,SLB,1987,238606299.605651 +Solomon Islands,SLB,1988,310684273.709484 +Solomon Islands,SLB,1989,332286760.858189 +Solomon Islands,SLB,1990,302515026.890225 +Solomon Islands,SLB,1991,320355090.61441 +Solomon Islands,SLB,1992,378778047.197842 +Solomon Islands,SLB,1993,410923236.189102 +Solomon Islands,SLB,1994,464756638.512487 +Solomon Islands,SLB,1995,519334096.714525 +Solomon Islands,SLB,1996,565163750.56079 +Solomon Islands,SLB,1997,567919502.811483 +Solomon Islands,SLB,1998,471177008.057148 +Solomon Islands,SLB,1999,482214092.308964 +Solomon Islands,SLB,2000,435103853.485036 +Solomon Islands,SLB,2001,400463452.065176 +Solomon Islands,SLB,2002,341661643.551446 +Solomon Islands,SLB,2003,332738245.913215 +Solomon Islands,SLB,2004,375111894.932329 +Solomon Islands,SLB,2005,413909879.281265 +Solomon Islands,SLB,2006,456705433.996978 +Solomon Islands,SLB,2007,516074228.959749 +Solomon Islands,SLB,2008,608293860.271816 +Solomon Islands,SLB,2009,597765363.128492 +Solomon Islands,SLB,2010,671585343.170686 +Solomon Islands,SLB,2011,886498370.696086 +Solomon Islands,SLB,2012,1025125081.57494 +Solomon Islands,SLB,2013,1059695156.18795 +Solomon Islands,SLB,2014,1156563122.85602 +Solomon Islands,SLB,2015,1129164718.81436 +Solomon Islands,SLB,2016,1202125000 +Somalia,SOM,2013,5352000000 +Somalia,SOM,2014,5647000000 +Somalia,SOM,2015,5925000000 +Somalia,SOM,2016,6217000000 +South Africa,ZAF,1960,7575248495.0301 +South Africa,ZAF,1961,7972840543.18914 +South Africa,ZAF,1962,8497830043.39913 +South Africa,ZAF,1963,9423211535.76928 +South Africa,ZAF,1964,10373792524.1495 +South Africa,ZAF,1965,11334173316.5337 +South Africa,ZAF,1966,12354752904.9419 +South Africa,ZAF,1967,13777124457.5108 +South Africa,ZAF,1968,14894302113.9577 +South Africa,ZAF,1969,16780064398.712 +South Africa,ZAF,1970,18418031639.3672 +South Africa,ZAF,1971,20334172259.5078 +South Africa,ZAF,1972,21358137114.6091 +South Africa,ZAF,1973,29293948126.8012 +South Africa,ZAF,1974,36806475349.5217 +South Africa,ZAF,1975,38114942528.7356 +South Africa,ZAF,1976,36601885924.563 +South Africa,ZAF,1977,40649724011.0396 +South Africa,ZAF,1978,46737580496.7801 +South Africa,ZAF,1979,57647268408.5511 +South Africa,ZAF,1980,82984078068.8238 +South Africa,ZAF,1981,89629496832.7955 +South Africa,ZAF,1982,82696902010.2943 +South Africa,ZAF,1983,88786580362.8407 +South Africa,ZAF,1984,87880468268.6383 +South Africa,ZAF,1985,69208451592.5576 +South Africa,ZAF,1986,82107924006.1732 +South Africa,ZAF,1987,107414974090.178 +South Africa,ZAF,1988,118331510445.149 +South Africa,ZAF,1989,128902675070.723 +South Africa,ZAF,1990,115553279480.54 +South Africa,ZAF,1991,123943432441.241 +South Africa,ZAF,1992,134545231416.55 +South Africa,ZAF,1993,134309759157.817 +South Africa,ZAF,1994,139752450152.078 +South Africa,ZAF,1995,155460285076.232 +South Africa,ZAF,1996,147607982694.857 +South Africa,ZAF,1997,152586154513.889 +South Africa,ZAF,1998,137774361015.14 +South Africa,ZAF,1999,136631966609.379 +South Africa,ZAF,2000,136361854808.496 +South Africa,ZAF,2001,121516070204.783 +South Africa,ZAF,2002,115482368343.658 +South Africa,ZAF,2003,175256916996.047 +South Africa,ZAF,2004,228593566165.088 +South Africa,ZAF,2005,257772710832.953 +South Africa,ZAF,2006,271638484826.109 +South Africa,ZAF,2007,299415505152.298 +South Africa,ZAF,2008,286769839732.726 +South Africa,ZAF,2009,295936485832.635 +South Africa,ZAF,2010,375349396273.835 +South Africa,ZAF,2011,416418862155.872 +South Africa,ZAF,2012,396327771010.962 +South Africa,ZAF,2013,366623856821.783 +South Africa,ZAF,2014,350850571747.123 +South Africa,ZAF,2015,317406594612.388 +South Africa,ZAF,2016,294840648284.114 +South Sudan,SSD,2008,15550136278.8696 +South Sudan,SSD,2009,12231362022.6859 +South Sudan,SSD,2010,15727363443.0995 +South Sudan,SSD,2011,17826697892.2717 +South Sudan,SSD,2012,10368813559.322 +South Sudan,SSD,2013,13257635694.9153 +South Sudan,SSD,2014,13282084033.8983 +South Sudan,SSD,2015,9015221096.24474 +Spain,ESP,1960,12072126075.397 +Spain,ESP,1961,13834300571.4849 +Spain,ESP,1962,16138545209.246 +Spain,ESP,1963,19074913947.7196 +Spain,ESP,1964,21343844643.7341 +Spain,ESP,1965,24756958694.9238 +Spain,ESP,1966,28721062242.1634 +Spain,ESP,1967,31647119228.1982 +Spain,ESP,1968,31475548481.4095 +Spain,ESP,1969,36038711599.541 +Spain,ESP,1970,40881655098.6451 +Spain,ESP,1971,46492797365.2695 +Spain,ESP,1972,58971806626.9739 +Spain,ESP,1973,78425934894.3461 +Spain,ESP,1974,97009800115.3735 +Spain,ESP,1975,114465300289.855 +Spain,ESP,1976,118185307386.222 +Spain,ESP,1977,132089531434.83 +Spain,ESP,1978,160163483072.917 +Spain,ESP,1979,214019077342.588 +Spain,ESP,1980,232134606637.271 +Spain,ESP,1981,202257045774.013 +Spain,ESP,1982,195464408602.151 +Spain,ESP,1983,170486866357.309 +Spain,ESP,1984,171635463361.623 +Spain,ESP,1985,180302412230.92 +Spain,ESP,1986,250638463466.793 +Spain,ESP,1987,317882187036.787 +Spain,ESP,1988,375138723325.239 +Spain,ESP,1989,413630538018.271 +Spain,ESP,1990,535101248775.71 +Spain,ESP,1991,575598537069.656 +Spain,ESP,1992,629202392003.901 +Spain,ESP,1993,523649481762.322 +Spain,ESP,1994,529121577319.588 +Spain,ESP,1995,612939685081.398 +Spain,ESP,1996,640998292394.588 +Spain,ESP,1997,588692045454.545 +Spain,ESP,1998,617041986858.225 +Spain,ESP,1999,633194118900.49 +Spain,ESP,2000,595402616546.895 +Spain,ESP,2001,625975838926.175 +Spain,ESP,2002,705145868624.13 +Spain,ESP,2003,906853273137.698 +Spain,ESP,2004,1069555500372.49 +Spain,ESP,2005,1157276458151.97 +Spain,ESP,2006,1264551499184.54 +Spain,ESP,2007,1479341637010.68 +Spain,ESP,2008,1634989014208.29 +Spain,ESP,2009,1499074742984.16 +Spain,ESP,2010,1431587612302.26 +Spain,ESP,2011,1488017213511.01 +Spain,ESP,2012,1335945712662.3 +Spain,ESP,2013,1361775869855.87 +Spain,ESP,2014,1375856057716.82 +Spain,ESP,2015,1192955480686.43 +Spain,ESP,2016,1232088185030.31 +Sri Lanka,LKA,1960,1409873949.57983 +Sri Lanka,LKA,1961,1444327731.09244 +Sri Lanka,LKA,1962,1434156378.60082 +Sri Lanka,LKA,1963,1240672268.90756 +Sri Lanka,LKA,1964,1309747899.15966 +Sri Lanka,LKA,1965,1698319327.73109 +Sri Lanka,LKA,1966,1751470588.23529 +Sri Lanka,LKA,1967,1859465020.57613 +Sri Lanka,LKA,1968,1801344537.81513 +Sri Lanka,LKA,1969,1965546218.48739 +Sri Lanka,LKA,1970,2296470588.23529 +Sri Lanka,LKA,1971,2369308600.33727 +Sri Lanka,LKA,1972,2553936348.40871 +Sri Lanka,LKA,1973,2875625000 +Sri Lanka,LKA,1974,3574586466.16541 +Sri Lanka,LKA,1975,3791298145.50642 +Sri Lanka,LKA,1976,3591319857.31272 +Sri Lanka,LKA,1977,4104509582.86359 +Sri Lanka,LKA,1978,2733183856.50224 +Sri Lanka,LKA,1979,3364611432.24149 +Sri Lanka,LKA,1980,4024621899.57653 +Sri Lanka,LKA,1981,4415844155.84416 +Sri Lanka,LKA,1982,4768765016.81884 +Sri Lanka,LKA,1983,5167913302.16745 +Sri Lanka,LKA,1984,6043474842.76729 +Sri Lanka,LKA,1985,5978460972.01767 +Sri Lanka,LKA,1986,6405210563.88294 +Sri Lanka,LKA,1987,6682167119.56522 +Sri Lanka,LKA,1988,6978371581.26375 +Sri Lanka,LKA,1989,6987267683.77254 +Sri Lanka,LKA,1990,8032551173.24014 +Sri Lanka,LKA,1991,9000362581.58086 +Sri Lanka,LKA,1992,9703011635.86585 +Sri Lanka,LKA,1993,10338679635.7616 +Sri Lanka,LKA,1994,11717604208.8223 +Sri Lanka,LKA,1995,13029697560.9756 +Sri Lanka,LKA,1996,13897738375.2488 +Sri Lanka,LKA,1997,15091913883.7091 +Sri Lanka,LKA,1998,15794972847.1683 +Sri Lanka,LKA,1999,15656327859.5696 +Sri Lanka,LKA,2000,16330814179.9766 +Sri Lanka,LKA,2001,15746229581.5619 +Sri Lanka,LKA,2002,16536535647.0834 +Sri Lanka,LKA,2003,18881765437.2151 +Sri Lanka,LKA,2004,20662525941.2986 +Sri Lanka,LKA,2005,24406252456.5141 +Sri Lanka,LKA,2006,28279814924.5918 +Sri Lanka,LKA,2007,32350248410.8216 +Sri Lanka,LKA,2008,40713812309.7316 +Sri Lanka,LKA,2009,42066217871.5349 +Sri Lanka,LKA,2010,56725745039.336 +Sri Lanka,LKA,2011,65292741296.5382 +Sri Lanka,LKA,2012,68434399083.41 +Sri Lanka,LKA,2013,74317806754.5267 +Sri Lanka,LKA,2014,79356456990.2891 +Sri Lanka,LKA,2015,80611989527.2158 +Sri Lanka,LKA,2016,81321876307.2556 +St. Kitts and Nevis,KNA,1960,12366563.6119699 +St. Kitts and Nevis,KNA,1961,12483229.3064224 +St. Kitts and Nevis,KNA,1962,12541562.1536487 +St. Kitts and Nevis,KNA,1963,12833226.3897801 +St. Kitts and Nevis,KNA,1964,13416554.8620428 +St. Kitts and Nevis,KNA,1965,13593932.3220537 +St. Kitts and Nevis,KNA,1966,14469078.1796966 +St. Kitts and Nevis,KNA,1967,16742338.2519864 +St. Kitts and Nevis,KNA,1968,14600000 +St. Kitts and Nevis,KNA,1969,15850000 +St. Kitts and Nevis,KNA,1970,16300000 +St. Kitts and Nevis,KNA,1971,19624746.4503043 +St. Kitts and Nevis,KNA,1972,22944849.1155047 +St. Kitts and Nevis,KNA,1973,24196018.3767228 +St. Kitts and Nevis,KNA,1974,31514856.3078422 +St. Kitts and Nevis,KNA,1975,33364055.2995392 +St. Kitts and Nevis,KNA,1976,30095602.2944551 +St. Kitts and Nevis,KNA,1977,44680000 +St. Kitts and Nevis,KNA,1978,49095407.4074074 +St. Kitts and Nevis,KNA,1979,58296666.6666667 +St. Kitts and Nevis,KNA,1980,67715444.4444444 +St. Kitts and Nevis,KNA,1981,79026037.037037 +St. Kitts and Nevis,KNA,1982,84381407.4074074 +St. Kitts and Nevis,KNA,1983,85100481.4814815 +St. Kitts and Nevis,KNA,1984,95898444.4444444 +St. Kitts and Nevis,KNA,1985,106057000 +St. Kitts and Nevis,KNA,1986,125272259.259259 +St. Kitts and Nevis,KNA,1987,140705629.62963 +St. Kitts and Nevis,KNA,1988,165745740.740741 +St. Kitts and Nevis,KNA,1989,185094777.777778 +St. Kitts and Nevis,KNA,1990,208740444.444444 +St. Kitts and Nevis,KNA,1991,209880962.962963 +St. Kitts and Nevis,KNA,1992,229434518.518519 +St. Kitts and Nevis,KNA,1993,249676000 +St. Kitts and Nevis,KNA,1994,277567259.259259 +St. Kitts and Nevis,KNA,1995,299699666.666667 +St. Kitts and Nevis,KNA,1996,318742962.962963 +St. Kitts and Nevis,KNA,1997,357237682.126571 +St. Kitts and Nevis,KNA,1998,364975456.93842 +St. Kitts and Nevis,KNA,1999,389984428.873318 +St. Kitts and Nevis,KNA,2000,420515112.890668 +St. Kitts and Nevis,KNA,2001,461078096.244393 +St. Kitts and Nevis,KNA,2002,483120201.312424 +St. Kitts and Nevis,KNA,2003,465850733.325919 +St. Kitts and Nevis,KNA,2004,502561637.037037 +St. Kitts and Nevis,KNA,2005,543167674.444444 +St. Kitts and Nevis,KNA,2006,636218025.185185 +St. Kitts and Nevis,KNA,2007,674008481.481481 +St. Kitts and Nevis,KNA,2008,738942555.555555 +St. Kitts and Nevis,KNA,2009,723209111.111111 +St. Kitts and Nevis,KNA,2010,705015370.37037 +St. Kitts and Nevis,KNA,2011,753225962.962963 +St. Kitts and Nevis,KNA,2012,734462666.666667 +St. Kitts and Nevis,KNA,2013,788163888.888889 +St. Kitts and Nevis,KNA,2014,847778185.185185 +St. Kitts and Nevis,KNA,2015,876478555.555555 +St. Kitts and Nevis,KNA,2016,916896555.555555 +St. Lucia,LCA,1977,87350296.2962963 +St. Lucia,LCA,1978,102094111.111111 +St. Lucia,LCA,1979,123935518.518519 +St. Lucia,LCA,1980,146341370.37037 +St. Lucia,LCA,1981,167970111.111111 +St. Lucia,LCA,1982,182754000 +St. Lucia,LCA,1983,197228777.777778 +St. Lucia,LCA,1984,217663037.037037 +St. Lucia,LCA,1985,241273000 +St. Lucia,LCA,1986,289689703.703704 +St. Lucia,LCA,1987,319999000 +St. Lucia,LCA,1988,366541074.074074 +St. Lucia,LCA,1989,415518111.111111 +St. Lucia,LCA,1990,483962444.444444 +St. Lucia,LCA,1991,513753814.814815 +St. Lucia,LCA,1992,566894740.740741 +St. Lucia,LCA,1993,574870407.407407 +St. Lucia,LCA,1994,600005555.555556 +St. Lucia,LCA,1995,640449518.518518 +St. Lucia,LCA,1996,662196185.185185 +St. Lucia,LCA,1997,676949592.592593 +St. Lucia,LCA,1998,737554888.888889 +St. Lucia,LCA,1999,775934814.814815 +St. Lucia,LCA,2000,784159222.222222 +St. Lucia,LCA,2001,743808074.074074 +St. Lucia,LCA,2002,748346592.592593 +St. Lucia,LCA,2003,823837148.148148 +St. Lucia,LCA,2004,893107222.222222 +St. Lucia,LCA,2005,951207370.37037 +St. Lucia,LCA,2006,1062617148.14815 +St. Lucia,LCA,2007,1150526259.25926 +St. Lucia,LCA,2008,1187075814.81481 +St. Lucia,LCA,2009,1180949888.88889 +St. Lucia,LCA,2010,1241892814.81481 +St. Lucia,LCA,2011,1280623888.88889 +St. Lucia,LCA,2012,1298815407.40741 +St. Lucia,LCA,2013,1318052185.18519 +St. Lucia,LCA,2014,1386188629.62963 +St. Lucia,LCA,2015,1431135703.7037 +St. Lucia,LCA,2016,1378627407.40741 +St. Vincent and the Grenadines,VCT,1960,13066557.7786852 +St. Vincent and the Grenadines,VCT,1961,13999883.3343055 +St. Vincent and the Grenadines,VCT,1962,14524878.959342 +St. Vincent and the Grenadines,VCT,1963,13708219.0981742 +St. Vincent and the Grenadines,VCT,1964,14758210.3482471 +St. Vincent and the Grenadines,VCT,1965,15108207.4316047 +St. Vincent and the Grenadines,VCT,1966,16099865.8344514 +St. Vincent and the Grenadines,VCT,1967,15835177.9329133 +St. Vincent and the Grenadines,VCT,1968,15350000 +St. Vincent and the Grenadines,VCT,1969,16650000 +St. Vincent and the Grenadines,VCT,1970,18450000 +St. Vincent and the Grenadines,VCT,1971,20051648.1847182 +St. Vincent and the Grenadines,VCT,1972,27585488.9918284 +St. Vincent and the Grenadines,VCT,1973,30165373.6218865 +St. Vincent and the Grenadines,VCT,1974,32924215.8581726 +St. Vincent and the Grenadines,VCT,1975,33237164.715642 +St. Vincent and the Grenadines,VCT,1976,32792480.9729606 +St. Vincent and the Grenadines,VCT,1977,49353148.1481481 +St. Vincent and the Grenadines,VCT,1978,60844777.7777778 +St. Vincent and the Grenadines,VCT,1979,71096370.3703704 +St. Vincent and the Grenadines,VCT,1980,82340333.3333333 +St. Vincent and the Grenadines,VCT,1981,102086555.555556 +St. Vincent and the Grenadines,VCT,1982,113759185.185185 +St. Vincent and the Grenadines,VCT,1983,122255333.333333 +St. Vincent and the Grenadines,VCT,1984,135025000 +St. Vincent and the Grenadines,VCT,1985,145641703.703704 +St. Vincent and the Grenadines,VCT,1986,160846666.666667 +St. Vincent and the Grenadines,VCT,1987,175580629.62963 +St. Vincent and the Grenadines,VCT,1988,200726703.703704 +St. Vincent and the Grenadines,VCT,1989,214745000 +St. Vincent and the Grenadines,VCT,1990,240365259.259259 +St. Vincent and the Grenadines,VCT,1991,254829629.62963 +St. Vincent and the Grenadines,VCT,1992,277954111.111111 +St. Vincent and the Grenadines,VCT,1993,286307814.814815 +St. Vincent and the Grenadines,VCT,1994,289438481.481481 +St. Vincent and the Grenadines,VCT,1995,316008481.481481 +St. Vincent and the Grenadines,VCT,1996,331489703.703704 +St. Vincent and the Grenadines,VCT,1997,347770000 +St. Vincent and the Grenadines,VCT,1998,373619851.851852 +St. Vincent and the Grenadines,VCT,1999,390719148.148148 +St. Vincent and the Grenadines,VCT,2000,396270000 +St. Vincent and the Grenadines,VCT,2001,430040370.37037 +St. Vincent and the Grenadines,VCT,2002,461883444.444444 +St. Vincent and the Grenadines,VCT,2003,481806296.296296 +St. Vincent and the Grenadines,VCT,2004,521975111.111111 +St. Vincent and the Grenadines,VCT,2005,550728666.666667 +St. Vincent and the Grenadines,VCT,2006,610930044.444444 +St. Vincent and the Grenadines,VCT,2007,651833314.814815 +St. Vincent and the Grenadines,VCT,2008,695428851.851852 +St. Vincent and the Grenadines,VCT,2009,674922481.481482 +St. Vincent and the Grenadines,VCT,2010,681225962.962963 +St. Vincent and the Grenadines,VCT,2011,676129407.407407 +St. Vincent and the Grenadines,VCT,2012,692933740.740741 +St. Vincent and the Grenadines,VCT,2013,721207148.148148 +St. Vincent and the Grenadines,VCT,2014,727912814.814815 +St. Vincent and the Grenadines,VCT,2015,737683555.555555 +St. Vincent and the Grenadines,VCT,2016,770796555.555556 +Sudan,SDN,1960,1307333333.33333 +Sudan,SDN,1961,1419333333.33333 +Sudan,SDN,1962,1541666666.66667 +Sudan,SDN,1963,1568333333.33333 +Sudan,SDN,1964,1611333333.33333 +Sudan,SDN,1965,1679333333.33333 +Sudan,SDN,1966,1723000000 +Sudan,SDN,1967,1865666666.66667 +Sudan,SDN,1968,1947333333.33333 +Sudan,SDN,1969,2144333333.33333 +Sudan,SDN,1970,2437666666.66667 +Sudan,SDN,1971,2656000000 +Sudan,SDN,1972,2882000000 +Sudan,SDN,1973,3571666666.66667 +Sudan,SDN,1974,4595000000 +Sudan,SDN,1975,5598000000 +Sudan,SDN,1976,6979333333.33333 +Sudan,SDN,1977,8704000000 +Sudan,SDN,1978,7670500000 +Sudan,SDN,1979,9032250000 +Sudan,SDN,1980,7459833333.33333 +Sudan,SDN,1981,10016500000 +Sudan,SDN,1982,9240000000 +Sudan,SDN,1983,8230153846.15384 +Sudan,SDN,1984,9701357142.85714 +Sudan,SDN,1985,12403733333.3333 +Sudan,SDN,1986,15769062500 +Sudan,SDN,1987,20155555555.5556 +Sudan,SDN,1988,15399166666.6667 +Sudan,SDN,1989,15291507936.5079 +Sudan,SDN,1990,12408647540.9836 +Sudan,SDN,1991,11379222222.2222 +Sudan,SDN,1992,7034219712.52567 +Sudan,SDN,1993,8881785938.48085 +Sudan,SDN,1994,12794192334.2541 +Sudan,SDN,1995,13829744878.6366 +Sudan,SDN,1996,9018243044.45155 +Sudan,SDN,1997,11681494637.3041 +Sudan,SDN,1998,11250327988.0478 +Sudan,SDN,1999,10682045258.3647 +Sudan,SDN,2000,12257418326.0734 +Sudan,SDN,2001,13182979783.533 +Sudan,SDN,2002,14803189092.7044 +Sudan,SDN,2003,17646503525.1743 +Sudan,SDN,2004,21457470202.7839 +Sudan,SDN,2005,26524538565.7403 +Sudan,SDN,2006,35822408611.5588 +Sudan,SDN,2007,45898948564.0593 +Sudan,SDN,2008,54526580231.5568 +Sudan,SDN,2009,53150209167.934 +Sudan,SDN,2010,65634109236.7736 +Sudan,SDN,2011,67327289319.733 +Sudan,SDN,2012,68125631150.2939 +Sudan,SDN,2013,72065940085.772 +Sudan,SDN,2014,82151588418.8325 +Sudan,SDN,2015,97156119150 +Sudan,SDN,2016,95584380032.2061 +Suriname,SUR,1960,93850000 +Suriname,SUR,1961,98400000 +Suriname,SUR,1962,103500000 +Suriname,SUR,1963,110000000 +Suriname,SUR,1964,120850000 +Suriname,SUR,1965,138650000 +Suriname,SUR,1966,171100000 +Suriname,SUR,1967,198450000 +Suriname,SUR,1968,220600000 +Suriname,SUR,1969,233450000 +Suriname,SUR,1970,247150000 +Suriname,SUR,1971,270650000 +Suriname,SUR,1972,287600000 +Suriname,SUR,1973,305300000 +Suriname,SUR,1974,368600000 +Suriname,SUR,1975,465000000 +Suriname,SUR,1976,505500000 +Suriname,SUR,1977,641000000 +Suriname,SUR,1978,735500000 +Suriname,SUR,1979,783000000 +Suriname,SUR,1980,794900000 +Suriname,SUR,1981,889050000 +Suriname,SUR,1982,915150000 +Suriname,SUR,1983,883600000 +Suriname,SUR,1984,864150000 +Suriname,SUR,1985,873250000 +Suriname,SUR,1986,891000000 +Suriname,SUR,1987,979850000 +Suriname,SUR,1988,1160900000 +Suriname,SUR,1989,542520000 +Suriname,SUR,1990,388300000 +Suriname,SUR,1991,448300000 +Suriname,SUR,1992,404600000 +Suriname,SUR,1993,428794117.647059 +Suriname,SUR,1994,605492537.313433 +Suriname,SUR,1995,693970588.235294 +Suriname,SUR,1996,860630922.693267 +Suriname,SUR,1997,929607500 +Suriname,SUR,1998,945000000 +Suriname,SUR,1999,885444186.046512 +Suriname,SUR,2000,892164393.939394 +Suriname,SUR,2001,763465550.458716 +Suriname,SUR,2002,1078402127.65957 +Suriname,SUR,2003,1271196078.43137 +Suriname,SUR,2004,1484092538.40527 +Suriname,SUR,2005,1793754804.70037 +Suriname,SUR,2006,2626380435.17877 +Suriname,SUR,2007,2936612021.85792 +Suriname,SUR,2008,3532969034.60838 +Suriname,SUR,2009,3875409836.06557 +Suriname,SUR,2010,4368398047.64333 +Suriname,SUR,2011,4422276621.78703 +Suriname,SUR,2012,4980000000 +Suriname,SUR,2013,5145757575.75758 +Suriname,SUR,2014,5240606060.60606 +Suriname,SUR,2015,4878731707.26948 +Suriname,SUR,2016,3620699735.1962 +Swaziland,SWZ,1960,35076158.4768305 +Swaziland,SWZ,1961,43025199.4960101 +Swaziland,SWZ,1962,45927061.4587708 +Swaziland,SWZ,1963,54128377.4324513 +Swaziland,SWZ,1964,64979280.4143917 +Swaziland,SWZ,1965,70278594.4281114 +Swaziland,SWZ,1966,76858462.8307434 +Swaziland,SWZ,1967,74758504.8299034 +Swaziland,SWZ,1968,79798404.0319194 +Swaziland,SWZ,1969,105417891.642167 +Swaziland,SWZ,1970,112137757.244855 +Swaziland,SWZ,1971,136465324.384787 +Swaziland,SWZ,1972,146741251.46351 +Swaziland,SWZ,1973,221902017.291066 +Swaziland,SWZ,1974,264311994.113319 +Swaziland,SWZ,1975,288302907.369844 +Swaziland,SWZ,1976,272539098.436063 +Swaziland,SWZ,1977,304047838.086477 +Swaziland,SWZ,1978,340616375.344986 +Swaziland,SWZ,1979,412093133.760988 +Swaziland,SWZ,1980,542000513.610683 +Swaziland,SWZ,1981,571542674.577818 +Swaziland,SWZ,1982,537575980.843618 +Swaziland,SWZ,1983,555336145.767884 +Swaziland,SWZ,1984,494475699.857656 +Swaziland,SWZ,1985,361014890.45841 +Swaziland,SWZ,1986,449146608.315098 +Swaziland,SWZ,1987,584135559.921414 +Swaziland,SWZ,1988,692016714.317132 +Swaziland,SWZ,1989,696915430.663057 +Swaziland,SWZ,1990,1114703088.1614 +Swaziland,SWZ,1991,1156141998.33412 +Swaziland,SWZ,1992,1284766234.2216 +Swaziland,SWZ,1993,1357206995.74624 +Swaziland,SWZ,1994,1419293454.99606 +Swaziland,SWZ,1995,1698982437.76019 +Swaziland,SWZ,1996,1602760100.48147 +Swaziland,SWZ,1997,1716699913.19444 +Swaziland,SWZ,1998,1576904292.4588 +Swaziland,SWZ,1999,1547884442.26205 +Swaziland,SWZ,2000,1738100848.09721 +Swaziland,SWZ,2001,1542477354.99355 +Swaziland,SWZ,2002,1432228172.702 +Swaziland,SWZ,2003,2197612760.58535 +Swaziland,SWZ,2004,2770082815.20915 +Swaziland,SWZ,2005,3178126547.9298 +Swaziland,SWZ,2006,3291353812.85535 +Swaziland,SWZ,2007,3469363931.16431 +Swaziland,SWZ,2008,3294093359.62088 +Swaziland,SWZ,2009,3580417156.54024 +Swaziland,SWZ,2010,4438778553.63533 +Swaziland,SWZ,2011,4820499498.18209 +Swaziland,SWZ,2012,4807282468.0268 +Swaziland,SWZ,2013,4575596300.78922 +Swaziland,SWZ,2014,4486261555.30421 +Swaziland,SWZ,2015,4137638726.69274 +Swaziland,SWZ,2016,3727303664.17403 +Sweden,SWE,1960,14842870293.4207 +Sweden,SWE,1961,16147160122.7882 +Sweden,SWE,1962,17511477311.4463 +Sweden,SWE,1963,18954132365.5148 +Sweden,SWE,1964,21137242560.8543 +Sweden,SWE,1965,23260320646.2745 +Sweden,SWE,1966,25302033132.3312 +Sweden,SWE,1967,27463409201.8822 +Sweden,SWE,1968,29143383490.5896 +Sweden,SWE,1969,31649203885.888 +Sweden,SWE,1970,37555366021.0315 +Sweden,SWE,1971,40980345656.3725 +Sweden,SWE,1972,48263914958.8443 +Sweden,SWE,1973,58567384058.8006 +Sweden,SWE,1974,65082581294.7696 +Sweden,SWE,1975,81716751697.8951 +Sweden,SWE,1976,88102107647.0993 +Sweden,SWE,1977,93136775102.6419 +Sweden,SWE,1978,102969762221.976 +Sweden,SWE,1979,121646718574.328 +Sweden,SWE,1980,140088635568.375 +Sweden,SWE,1981,127858412114.39 +Sweden,SWE,1982,112767844570.719 +Sweden,SWE,1983,103533702638.547 +Sweden,SWE,1984,107661673734.858 +Sweden,SWE,1985,112514448261.835 +Sweden,SWE,1986,148376104539.839 +Sweden,SWE,1987,180429286795.786 +Sweden,SWE,1988,204068257817.6 +Sweden,SWE,1989,214875344909.957 +Sweden,SWE,1990,258154283908.9 +Sweden,SWE,1991,270362531376.602 +Sweden,SWE,1992,280312318915.485 +Sweden,SWE,1993,209950792712.696 +Sweden,SWE,1994,226079963711.768 +Sweden,SWE,1995,264051981551.316 +Sweden,SWE,1996,288103936773.039 +Sweden,SWE,1997,264477727278.681 +Sweden,SWE,1998,266800462898.904 +Sweden,SWE,1999,270847937645.236 +Sweden,SWE,2000,259802012617.057 +Sweden,SWE,2001,239917320966.977 +Sweden,SWE,2002,263926220332.543 +Sweden,SWE,2003,331108912605.271 +Sweden,SWE,2004,381705425301.746 +Sweden,SWE,2005,389042298376.845 +Sweden,SWE,2006,420032121655.688 +Sweden,SWE,2007,487816328342.309 +Sweden,SWE,2008,513965650650.119 +Sweden,SWE,2009,429657033107.737 +Sweden,SWE,2010,488377689564.921 +Sweden,SWE,2011,563109663291.177 +Sweden,SWE,2012,543880647757.404 +Sweden,SWE,2013,578742001487.571 +Sweden,SWE,2014,573817719109.402 +Sweden,SWE,2015,495694356611.551 +Sweden,SWE,2016,510999796581.597 +Switzerland,CHE,1960,9522746719.21614 +Switzerland,CHE,1961,10712712465.0522 +Switzerland,CHE,1962,11879982758.5619 +Switzerland,CHE,1963,13063643795.7884 +Switzerland,CHE,1964,14480556571.5476 +Switzerland,CHE,1965,15346741669.7575 +Switzerland,CHE,1966,16480058704.8531 +Switzerland,CHE,1967,17740013179.26 +Switzerland,CHE,1968,18942729779.1 +Switzerland,CHE,1969,20524886616.4789 +Switzerland,CHE,1980,118710309542.281 +Switzerland,CHE,1981,108721034568.781 +Switzerland,CHE,1982,111431738019.012 +Switzerland,CHE,1983,111035571006.622 +Switzerland,CHE,1984,106019113631.527 +Switzerland,CHE,1985,107496240242.562 +Switzerland,CHE,1986,154095512368.67 +Switzerland,CHE,1987,192981619165.773 +Switzerland,CHE,1988,208774024533.588 +Switzerland,CHE,1989,201572650956.66 +Switzerland,CHE,1990,257420293190.325 +Switzerland,CHE,1991,260459896582.985 +Switzerland,CHE,1992,271133679206.372 +Switzerland,CHE,1993,263691005481.862 +Switzerland,CHE,1994,291913801052.862 +Switzerland,CHE,1995,341759012938.689 +Switzerland,CHE,1996,329619351051.78 +Switzerland,CHE,1997,286604024805.347 +Switzerland,CHE,1998,294977518761.208 +Switzerland,CHE,1999,289884127679.404 +Switzerland,CHE,2000,271659728209.379 +Switzerland,CHE,2001,278628772872.719 +Switzerland,CHE,2002,301127808995.252 +Switzerland,CHE,2003,351982634291.23 +Switzerland,CHE,2004,393541693928.428 +Switzerland,CHE,2005,407535656039.19 +Switzerland,CHE,2006,429195591242.622 +Switzerland,CHE,2007,477407802315.895 +Switzerland,CHE,2008,551546962699.658 +Switzerland,CHE,2009,539528229942.101 +Switzerland,CHE,2010,581208562423.374 +Switzerland,CHE,2011,696278717728.137 +Switzerland,CHE,2012,665054050620.785 +Switzerland,CHE,2013,684835034384.327 +Switzerland,CHE,2014,702705544908.583 +Switzerland,CHE,2015,670789928809.882 +Switzerland,CHE,2016,659827235193.83 +Syrian Arab Republic,SYR,1960,857704431.686497 +Syrian Arab Republic,SYR,1961,945244992.211306 +Syrian Arab Republic,SYR,1962,1110565863.53737 +Syrian Arab Republic,SYR,1963,1200447429.35563 +Syrian Arab Republic,SYR,1964,1339494290.42432 +Syrian Arab Republic,SYR,1965,1472036550.70992 +Syrian Arab Republic,SYR,1966,1342287556.59602 +Syrian Arab Republic,SYR,1967,1580229795.10881 +Syrian Arab Republic,SYR,1968,1753746369.66049 +Syrian Arab Republic,SYR,1969,2245011571.98652 +Syrian Arab Republic,SYR,1970,2140383695.94618 +Syrian Arab Republic,SYR,1971,2589851693.01656 +Syrian Arab Republic,SYR,1972,3059682162.06566 +Syrian Arab Republic,SYR,1973,3239488104.60091 +Syrian Arab Republic,SYR,1974,5159557176.25012 +Syrian Arab Republic,SYR,1975,6826980766.8048 +Syrian Arab Republic,SYR,1976,7633528920.63247 +Syrian Arab Republic,SYR,1977,7696011359.94156 +Syrian Arab Republic,SYR,1978,9275203105.57946 +Syrian Arab Republic,SYR,1979,9929682184.32718 +Syrian Arab Republic,SYR,1980,13062421024.9337 +Syrian Arab Republic,SYR,1981,15518199247.3393 +Syrian Arab Republic,SYR,1982,16298905397.0701 +Syrian Arab Republic,SYR,1983,17589184556.6946 +Syrian Arab Republic,SYR,1984,17503082982.2832 +Syrian Arab Republic,SYR,1985,16403544510.5268 +Syrian Arab Republic,SYR,1986,13293209270.1036 +Syrian Arab Republic,SYR,1987,11356215712.9326 +Syrian Arab Republic,SYR,1988,10577042354.799 +Syrian Arab Republic,SYR,1989,9853396225.58749 +Syrian Arab Republic,SYR,1990,12308624283.9787 +Syrian Arab Republic,SYR,1991,12981833333.3333 +Syrian Arab Republic,SYR,1992,13253565898.9558 +Syrian Arab Republic,SYR,1993,13695962019.2084 +Syrian Arab Republic,SYR,1994,10122020000 +Syrian Arab Republic,SYR,1995,11396706586.8263 +Syrian Arab Republic,SYR,1996,13789560878.2435 +Syrian Arab Republic,SYR,1997,14505233968.8716 +Syrian Arab Republic,SYR,1998,15200846138.4615 +Syrian Arab Republic,SYR,1999,15873875968.9922 +Syrian Arab Republic,SYR,2000,19325894913.1254 +Syrian Arab Republic,SYR,2001,21099833783.503 +Syrian Arab Republic,SYR,2002,21582248881.6592 +Syrian Arab Republic,SYR,2003,21828144686.0394 +Syrian Arab Republic,SYR,2004,25086930693.0693 +Syrian Arab Republic,SYR,2005,28858965517.2414 +Syrian Arab Republic,SYR,2006,33332844574.7801 +Syrian Arab Republic,SYR,2007,40405006007.2086 +Tajikistan,TJK,1990,2629395066.27017 +Tajikistan,TJK,1991,2534720480.3244 +Tajikistan,TJK,1992,1909246640.80838 +Tajikistan,TJK,1993,1646693642.11088 +Tajikistan,TJK,1994,1346074611.47792 +Tajikistan,TJK,1995,1231523034.78397 +Tajikistan,TJK,1996,1043893062.60575 +Tajikistan,TJK,1997,921843144.229059 +Tajikistan,TJK,1998,1320126706.15503 +Tajikistan,TJK,1999,1086567377.60543 +Tajikistan,TJK,2000,860550305.832491 +Tajikistan,TJK,2001,1080774007.25065 +Tajikistan,TJK,2002,1221113780.25397 +Tajikistan,TJK,2003,1554125530.8029 +Tajikistan,TJK,2004,2076148695.50581 +Tajikistan,TJK,2005,2312319579.02843 +Tajikistan,TJK,2006,2830236053.84429 +Tajikistan,TJK,2007,3719497371.09659 +Tajikistan,TJK,2008,5161336170.46084 +Tajikistan,TJK,2009,4979481980.35098 +Tajikistan,TJK,2010,5642178579.58438 +Tajikistan,TJK,2011,6522732202.50748 +Tajikistan,TJK,2012,7633049792.09321 +Tajikistan,TJK,2013,8506674782.75471 +Tajikistan,TJK,2014,9236309138.04277 +Tajikistan,TJK,2015,7853450374.0001 +Tajikistan,TJK,2016,6951657158.90093 +Tanzania,TZA,1988,5100405772.46327 +Tanzania,TZA,1989,4420168102.39306 +Tanzania,TZA,1990,4258743262.82876 +Tanzania,TZA,1991,4956588278.56144 +Tanzania,TZA,1992,4601413263.52894 +Tanzania,TZA,1993,4257702196.53864 +Tanzania,TZA,1994,4510846967.8742 +Tanzania,TZA,1995,5255221424.80962 +Tanzania,TZA,1996,6496195450.61034 +Tanzania,TZA,1997,7683852496.84499 +Tanzania,TZA,1998,9345174219.07253 +Tanzania,TZA,1999,9697847263.63196 +Tanzania,TZA,2000,10185786382.8283 +Tanzania,TZA,2001,10383560602.8537 +Tanzania,TZA,2002,10805599892.7355 +Tanzania,TZA,2003,11659129888.8021 +Tanzania,TZA,2004,12825801580.9281 +Tanzania,TZA,2005,16929976600.142 +Tanzania,TZA,2006,18610460326.5437 +Tanzania,TZA,2007,21501741757.484 +Tanzania,TZA,2008,27368386358.131 +Tanzania,TZA,2009,28573777052.4542 +Tanzania,TZA,2010,31407908612.0943 +Tanzania,TZA,2011,33878631649.4157 +Tanzania,TZA,2012,39087748240.4403 +Tanzania,TZA,2013,44333456244.744 +Tanzania,TZA,2014,48197218326.7942 +Tanzania,TZA,2015,45628247290.4618 +Tanzania,TZA,2016,47431038892.2441 +Thailand,THA,1960,2760747471.88624 +Thailand,THA,1961,3034043574.06071 +Thailand,THA,1962,3308912796.93487 +Thailand,THA,1963,3540403456.55305 +Thailand,THA,1964,3889129942.30769 +Thailand,THA,1965,4388937649.03846 +Thailand,THA,1966,5279230817.30769 +Thailand,THA,1967,5638461442.30769 +Thailand,THA,1968,6081009427.88461 +Thailand,THA,1969,6695336567.30769 +Thailand,THA,1970,7086538437.5 +Thailand,THA,1971,7375000024.03846 +Thailand,THA,1972,8177884552.88461 +Thailand,THA,1973,10838587357.7466 +Thailand,THA,1974,13703000530.0587 +Thailand,THA,1975,14882747955.0328 +Thailand,THA,1976,16985211146.0238 +Thailand,THA,1977,19779315170.0237 +Thailand,THA,1978,24006570178.1561 +Thailand,THA,1979,27371699082.7126 +Thailand,THA,1980,32353440726.8856 +Thailand,THA,1981,34846107862.3673 +Thailand,THA,1982,36589797857.4006 +Thailand,THA,1983,40042826244.2337 +Thailand,THA,1984,41797592963.4424 +Thailand,THA,1985,38900692712.1496 +Thailand,THA,1986,43096746122.4614 +Thailand,THA,1987,50535438696.4094 +Thailand,THA,1988,61667199834.7428 +Thailand,THA,1989,72250877410.3183 +Thailand,THA,1990,85343063965.9182 +Thailand,THA,1991,98234695722.0341 +Thailand,THA,1992,111452869378.467 +Thailand,THA,1993,128889832382.818 +Thailand,THA,1994,146683499005.964 +Thailand,THA,1995,169278552851.272 +Thailand,THA,1996,183035154107.494 +Thailand,THA,1997,150180268649.388 +Thailand,THA,1998,113675706127.265 +Thailand,THA,1999,126668932159.508 +Thailand,THA,2000,126392308497.749 +Thailand,THA,2001,120296746256.631 +Thailand,THA,2002,134300851255.002 +Thailand,THA,2003,152280653543.725 +Thailand,THA,2004,172895476152.592 +Thailand,THA,2005,189318499954.003 +Thailand,THA,2006,221758486880.313 +Thailand,THA,2007,262942650543.771 +Thailand,THA,2008,291383081231.82 +Thailand,THA,2009,281710095724.761 +Thailand,THA,2010,341105009515.333 +Thailand,THA,2011,370818747396.833 +Thailand,THA,2012,397559992407.45 +Thailand,THA,2013,420528737876.717 +Thailand,THA,2014,406521561093.357 +Thailand,THA,2015,399234547137.472 +Thailand,THA,2016,406839679301.943 +Timor-Leste,TLS,2000,368000000 +Timor-Leste,TLS,2001,452000000 +Timor-Leste,TLS,2002,444000000 +Timor-Leste,TLS,2003,453000000 +Timor-Leste,TLS,2004,466000000 +Timor-Leste,TLS,2005,491000000 +Timor-Leste,TLS,2006,463000000 +Timor-Leste,TLS,2007,559000000 +Timor-Leste,TLS,2008,694000000 +Timor-Leste,TLS,2009,827000000 +Timor-Leste,TLS,2010,943000000 +Timor-Leste,TLS,2011,1148000000 +Timor-Leste,TLS,2012,1293000000 +Timor-Leste,TLS,2013,1312000000 +Timor-Leste,TLS,2014,1399000000 +Timor-Leste,TLS,2015,1441718600 +Togo,TGO,1960,121128073.114022 +Togo,TGO,1961,126396469.707058 +Togo,TGO,1962,132237441.630863 +Togo,TGO,1963,143255784.510751 +Togo,TGO,1964,166104067.630043 +Togo,TGO,1965,187300336.365369 +Togo,TGO,1966,216136263.912497 +Togo,TGO,1967,231706475.464114 +Togo,TGO,1968,241956910.658103 +Togo,TGO,1969,267732446.378413 +Togo,TGO,1970,253976626.166639 +Togo,TGO,1971,286537524.990331 +Togo,TGO,1972,335677636.893737 +Togo,TGO,1973,406479906.159652 +Togo,TGO,1974,560437742.594972 +Togo,TGO,1975,617321669.390877 +Togo,TGO,1976,619375134.18051 +Togo,TGO,1977,777435020.475847 +Togo,TGO,1978,824263841.539264 +Togo,TGO,1979,891775906.631015 +Togo,TGO,1980,1136408814.19692 +Togo,TGO,1981,962347000.991788 +Togo,TGO,1982,821651918.724626 +Togo,TGO,1983,765746590.616849 +Togo,TGO,1984,718148959.610872 +Togo,TGO,1985,762359722.701402 +Togo,TGO,1986,1060911735.26065 +Togo,TGO,1987,1249099130.02277 +Togo,TGO,1988,1378847487.41137 +Togo,TGO,1989,1352949662.75172 +Togo,TGO,1990,1628427515.41881 +Togo,TGO,1991,1602299862.9243 +Togo,TGO,1992,1692959110.18022 +Togo,TGO,1993,1233496846.33493 +Togo,TGO,1994,982624324.505898 +Togo,TGO,1995,1309382885.33029 +Togo,TGO,1996,1465448290.34132 +Togo,TGO,1997,1498950899.08774 +Togo,TGO,1998,1587345950.9743 +Togo,TGO,1999,1576094566.48548 +Togo,TGO,2000,1294250233.18894 +Togo,TGO,2001,1332328999.09077 +Togo,TGO,2002,1474630207.08242 +Togo,TGO,2003,1673690429.61609 +Togo,TGO,2004,1937074572.08687 +Togo,TGO,2005,2115154262.03025 +Togo,TGO,2006,2202809251.31304 +Togo,TGO,2007,2523462557.38975 +Togo,TGO,2008,3163416242.05877 +Togo,TGO,2009,3163000528.8167 +Togo,TGO,2010,3172945644.5585 +Togo,TGO,2011,3756023159.96 +Togo,TGO,2012,3866617462.61854 +Togo,TGO,2013,4080929201.27925 +Togo,TGO,2014,4482880424.33988 +Togo,TGO,2015,4087628275.95594 +Togo,TGO,2016,4399995986.56477 +Tonga,TON,1975,32506741.7201204 +Tonga,TON,1976,30036416.9619944 +Tonga,TON,1977,34139387.8908849 +Tonga,TON,1978,41567471.6721987 +Tonga,TON,1979,44667002.0120724 +Tonga,TON,1980,53260077.4311091 +Tonga,TON,1981,62242013.3302689 +Tonga,TON,1982,62068161.0711025 +Tonga,TON,1983,60863963.963964 +Tonga,TON,1984,64248354.5414656 +Tonga,TON,1985,60058663.3144773 +Tonga,TON,1986,68195855.6149733 +Tonga,TON,1987,81667133.4546982 +Tonga,TON,1988,106657267.367342 +Tonga,TON,1989,106344854.986095 +Tonga,TON,1990,113563821.577404 +Tonga,TON,1991,132201141.446861 +Tonga,TON,1992,137066290.550071 +Tonga,TON,1993,138489884.393064 +Tonga,TON,1994,193775943.038933 +Tonga,TON,1995,202547013.927138 +Tonga,TON,1996,219583570.094975 +Tonga,TON,1997,212155124.65374 +Tonga,TON,1998,188686997.319035 +Tonga,TON,1999,196686674.669868 +Tonga,TON,2000,202363492.160332 +Tonga,TON,2001,181244788.473329 +Tonga,TON,2002,182737040.095422 +Tonga,TON,2003,202543202.004099 +Tonga,TON,2004,229358214.792003 +Tonga,TON,2005,262176133.72543 +Tonga,TON,2006,294137737.070038 +Tonga,TON,2007,300143056.873221 +Tonga,TON,2008,349459648.569023 +Tonga,TON,2009,318151987.342379 +Tonga,TON,2010,369435481.362435 +Tonga,TON,2011,423015937.994651 +Tonga,TON,2012,472441382.972447 +Tonga,TON,2013,449387934.017765 +Tonga,TON,2014,443475142.084644 +Tonga,TON,2015,435430325.223892 +Tonga,TON,2016,395159628.7518 +Trinidad and Tobago,TTO,1960,535670127.748935 +Trinidad and Tobago,TTO,1961,584961208.656595 +Trinidad and Tobago,TTO,1962,619319197.340022 +Trinidad and Tobago,TTO,1963,678235373.038558 +Trinidad and Tobago,TTO,1964,711893367.55527 +Trinidad and Tobago,TTO,1965,736568861.926151 +Trinidad and Tobago,TTO,1966,723735635.536371 +Trinidad and Tobago,TTO,1967,761981474.023359 +Trinidad and Tobago,TTO,1968,758899950 +Trinidad and Tobago,TTO,1969,779200000 +Trinidad and Tobago,TTO,1970,821850000 +Trinidad and Tobago,TTO,1971,896754316.674262 +Trinidad and Tobago,TTO,1972,1083381044.08473 +Trinidad and Tobago,TTO,1973,1308799458.96284 +Trinidad and Tobago,TTO,1974,2042031901.42217 +Trinidad and Tobago,TTO,1975,2442667573.04821 +Trinidad and Tobago,TTO,1976,2500410583.79177 +Trinidad and Tobago,TTO,1977,3138666666.66667 +Trinidad and Tobago,TTO,1978,3562333458.33333 +Trinidad and Tobago,TTO,1979,4602416625 +Trinidad and Tobago,TTO,1980,6235833333.33333 +Trinidad and Tobago,TTO,1981,6992083333.33333 +Trinidad and Tobago,TTO,1982,8140416666.66667 +Trinidad and Tobago,TTO,1983,7763750000 +Trinidad and Tobago,TTO,1984,7757083333.33333 +Trinidad and Tobago,TTO,1985,7375918367.34694 +Trinidad and Tobago,TTO,1986,4794444444.44444 +Trinidad and Tobago,TTO,1987,4797777777.77778 +Trinidad and Tobago,TTO,1988,4496852073.46896 +Trinidad and Tobago,TTO,1989,4323058823.52941 +Trinidad and Tobago,TTO,1990,5068000000 +Trinidad and Tobago,TTO,1991,5307905882.35294 +Trinidad and Tobago,TTO,1992,5439552941.17647 +Trinidad and Tobago,TTO,1993,4669488516.37981 +Trinidad and Tobago,TTO,1994,4947205860.01451 +Trinidad and Tobago,TTO,1995,5329214163.22001 +Trinidad and Tobago,TTO,1996,5759537726.26601 +Trinidad and Tobago,TTO,1997,5737751331.63779 +Trinidad and Tobago,TTO,1998,6043694330.21609 +Trinidad and Tobago,TTO,1999,6808982520.75759 +Trinidad and Tobago,TTO,2000,8154338232.95978 +Trinidad and Tobago,TTO,2001,8824873259.32105 +Trinidad and Tobago,TTO,2002,9008273720.93395 +Trinidad and Tobago,TTO,2003,11305459802.0683 +Trinidad and Tobago,TTO,2004,13280275123.0354 +Trinidad and Tobago,TTO,2005,15982282462.3786 +Trinidad and Tobago,TTO,2006,18369070085.3888 +Trinidad and Tobago,TTO,2007,21642304045.512 +Trinidad and Tobago,TTO,2008,27870257894.2347 +Trinidad and Tobago,TTO,2009,19175196445.7936 +Trinidad and Tobago,TTO,2010,22157948396.2042 +Trinidad and Tobago,TTO,2011,25433011405.3017 +Trinidad and Tobago,TTO,2012,25694164489.2373 +Trinidad and Tobago,TTO,2013,26436221401.2976 +Trinidad and Tobago,TTO,2014,26175906133.4665 +Trinidad and Tobago,TTO,2015,23559287483.9276 +Trinidad and Tobago,TTO,2016,20989155539.8436 +Tunisia,TUN,1965,991047619.047619 +Tunisia,TUN,1966,1040952380.95238 +Tunisia,TUN,1967,1085714285.71429 +Tunisia,TUN,1968,1214666666.66667 +Tunisia,TUN,1969,1289904761.90476 +Tunisia,TUN,1970,1439238095.2381 +Tunisia,TUN,1971,1685217058.71103 +Tunisia,TUN,1972,2237476420.03773 +Tunisia,TUN,1973,2730787476.28084 +Tunisia,TUN,1974,3545933562.42841 +Tunisia,TUN,1975,4328610489.68432 +Tunisia,TUN,1976,4507929104.47761 +Tunisia,TUN,1977,5109324009.32401 +Tunisia,TUN,1978,5968044209.51466 +Tunisia,TUN,1979,7188191881.91882 +Tunisia,TUN,1980,8744134354.16152 +Tunisia,TUN,1981,8428513568.24625 +Tunisia,TUN,1982,8133401049.60217 +Tunisia,TUN,1983,8350176782.55746 +Tunisia,TUN,1984,8254891864.05767 +Tunisia,TUN,1985,8410185739.96405 +Tunisia,TUN,1986,9018136020.15113 +Tunisia,TUN,1987,9696271268.25148 +Tunisia,TUN,1988,10096292842.1543 +Tunisia,TUN,1989,10102075213.3151 +Tunisia,TUN,1990,12290568181.8182 +Tunisia,TUN,1991,13074782608.6957 +Tunisia,TUN,1992,15497286295.7938 +Tunisia,TUN,1993,14608946896.483 +Tunisia,TUN,1994,15632463424.2784 +Tunisia,TUN,1995,18030876599.3444 +Tunisia,TUN,1996,19587322786.1105 +Tunisia,TUN,1997,20746360430.4187 +Tunisia,TUN,1998,21803372266.6198 +Tunisia,TUN,1999,22943685719.103 +Tunisia,TUN,2000,21473188881.5933 +Tunisia,TUN,2001,22066101341.4888 +Tunisia,TUN,2002,23142294436.2383 +Tunisia,TUN,2003,27453084982.5378 +Tunisia,TUN,2004,31183139301.4853 +Tunisia,TUN,2005,32273007553.5687 +Tunisia,TUN,2006,34378437265.2141 +Tunisia,TUN,2007,38908069299.204 +Tunisia,TUN,2008,44856586316.0458 +Tunisia,TUN,2009,43454935940.1614 +Tunisia,TUN,2010,44050929160.2627 +Tunisia,TUN,2011,45810626509.4474 +Tunisia,TUN,2012,45044176963.9542 +Tunisia,TUN,2013,46255308672.3703 +Tunisia,TUN,2014,47603227896.5659 +Tunisia,TUN,2015,43156606851.5498 +Tunisia,TUN,2016,42062549394.7859 +Turkey,TUR,1960,13995067817.5092 +Turkey,TUR,1961,8022222222.22222 +Turkey,TUR,1962,8922222222.22222 +Turkey,TUR,1963,10355555555.5556 +Turkey,TUR,1964,11177777777.7778 +Turkey,TUR,1965,11944444444.4444 +Turkey,TUR,1966,14122222222.2222 +Turkey,TUR,1967,15666666666.6667 +Turkey,TUR,1968,17500000000 +Turkey,TUR,1969,19466666666.6667 +Turkey,TUR,1970,17086956521.7391 +Turkey,TUR,1971,16256619963.7997 +Turkey,TUR,1972,20431095406.3604 +Turkey,TUR,1973,25724381625.4417 +Turkey,TUR,1974,35599913836.4328 +Turkey,TUR,1975,44633707242.7642 +Turkey,TUR,1976,51280134554.2889 +Turkey,TUR,1977,58676813687.3681 +Turkey,TUR,1978,65147022485.7919 +Turkey,TUR,1979,89394085658.2038 +Turkey,TUR,1980,68789289565.7434 +Turkey,TUR,1981,71040020140.4436 +Turkey,TUR,1982,64546332580.7583 +Turkey,TUR,1983,61678280115.4987 +Turkey,TUR,1984,59989909457.8379 +Turkey,TUR,1985,67234948264.5987 +Turkey,TUR,1986,75728009962.7878 +Turkey,TUR,1987,87172789528.3316 +Turkey,TUR,1988,90852814004.9917 +Turkey,TUR,1989,107143348667.094 +Turkey,TUR,1990,150676291094.21 +Turkey,TUR,1991,150027833333.333 +Turkey,TUR,1992,158459130434.783 +Turkey,TUR,1993,180169736363.636 +Turkey,TUR,1994,130690172297.297 +Turkey,TUR,1995,169485941048.035 +Turkey,TUR,1996,181475555282.555 +Turkey,TUR,1997,189834649111.257 +Turkey,TUR,1998,275768695818.949 +Turkey,TUR,1999,255884300382.044 +Turkey,TUR,2000,272979390595.01 +Turkey,TUR,2001,200254104151.474 +Turkey,TUR,2002,238423907922.754 +Turkey,TUR,2003,311825946795.017 +Turkey,TUR,2004,404776328437.599 +Turkey,TUR,2005,501422832613.554 +Turkey,TUR,2006,552504962256.438 +Turkey,TUR,2007,675754121015.013 +Turkey,TUR,2008,764322933264.927 +Turkey,TUR,2009,644656538878.423 +Turkey,TUR,2010,771876943465.616 +Turkey,TUR,2011,832546462299.564 +Turkey,TUR,2012,873981840596.288 +Turkey,TUR,2013,950595641011.836 +Turkey,TUR,2014,934167774215.031 +Turkey,TUR,2015,859383637728.94 +Turkey,TUR,2016,857748989287.642 +Turkmenistan,TKM,1987,2331358819.75954 +Turkmenistan,TKM,1988,3010982414.24425 +Turkmenistan,TKM,1989,3006988216.55045 +Turkmenistan,TKM,1990,3189539641.3171 +Turkmenistan,TKM,1991,3208098919.0146 +Turkmenistan,TKM,1992,3200539816.0601 +Turkmenistan,TKM,1993,3179225948.58114 +Turkmenistan,TKM,1994,2561118608.35516 +Turkmenistan,TKM,1995,2482228439.71407 +Turkmenistan,TKM,1996,2379281767.9558 +Turkmenistan,TKM,1997,2450084970.24741 +Turkmenistan,TKM,1998,2605688065.08338 +Turkmenistan,TKM,1999,2450686659.778 +Turkmenistan,TKM,2000,2904662604.82053 +Turkmenistan,TKM,2001,3534771968.51189 +Turkmenistan,TKM,2002,4462028988.72949 +Turkmenistan,TKM,2003,5977440582.80171 +Turkmenistan,TKM,2004,6838351088.46688 +Turkmenistan,TKM,2005,8104355716.8784 +Turkmenistan,TKM,2006,10277598152.4249 +Turkmenistan,TKM,2007,12664165103.1895 +Turkmenistan,TKM,2008,19271523178.8079 +Turkmenistan,TKM,2009,20214385964.9123 +Turkmenistan,TKM,2010,22583157894.7368 +Turkmenistan,TKM,2011,29233333333.3333 +Turkmenistan,TKM,2012,35164210526.3158 +Turkmenistan,TKM,2013,39197543859.6491 +Turkmenistan,TKM,2014,43524210526.3158 +Turkmenistan,TKM,2015,35799628571.4286 +Turkmenistan,TKM,2016,36179885714.2857 +Tuvalu,TUV,1990,8824447.74022325 +Tuvalu,TUV,1991,9365165.91369372 +Tuvalu,TUV,1992,9742949.47121034 +Tuvalu,TUV,1993,9630762.95389637 +Tuvalu,TUV,1994,10886825.5592923 +Tuvalu,TUV,1995,11025945.1445515 +Tuvalu,TUV,1996,12334846.2320995 +Tuvalu,TUV,1997,12700905.4475286 +Tuvalu,TUV,1998,12757632.8684508 +Tuvalu,TUV,1999,13687141.1058778 +Tuvalu,TUV,2000,13742057.0500928 +Tuvalu,TUV,2001,13196544.946726 +Tuvalu,TUV,2002,15450994.2410084 +Tuvalu,TUV,2003,18231078.5394643 +Tuvalu,TUV,2004,21534931.6075894 +Tuvalu,TUV,2005,21839098.8927071 +Tuvalu,TUV,2006,22902861.4457831 +Tuvalu,TUV,2007,27030374.0272781 +Tuvalu,TUV,2008,30290219.7617849 +Tuvalu,TUV,2009,27101076.2751521 +Tuvalu,TUV,2010,31823518.6204366 +Tuvalu,TUV,2011,39312016.5033522 +Tuvalu,TUV,2012,39875750.6730172 +Tuvalu,TUV,2013,38322359.5288666 +Tuvalu,TUV,2014,37259689.9224806 +Tuvalu,TUV,2015,32673277.7402149 +Tuvalu,TUV,2016,34218878.4390841 +Uganda,UGA,1960,423008385.744235 +Uganda,UGA,1961,441524109.014675 +Uganda,UGA,1962,449012578.616352 +Uganda,UGA,1963,516147798.742138 +Uganda,UGA,1964,589056603.773585 +Uganda,UGA,1965,884873949.579832 +Uganda,UGA,1966,925770308.123249 +Uganda,UGA,1967,967647058.823529 +Uganda,UGA,1968,1037815126.05042 +Uganda,UGA,1969,1169047619.04762 +Uganda,UGA,1970,1260084033.61345 +Uganda,UGA,1971,1417787114.84594 +Uganda,UGA,1972,1491596638.65546 +Uganda,UGA,1973,1702521008.40336 +Uganda,UGA,1974,2100142653.35235 +Uganda,UGA,1975,2359555555.55556 +Uganda,UGA,1976,2447300000 +Uganda,UGA,1977,2936470588.23529 +Uganda,UGA,1978,2420260869.56522 +Uganda,UGA,1979,2139025000 +Uganda,UGA,1980,1244610000 +Uganda,UGA,1981,1337300000 +Uganda,UGA,1982,2177500000 +Uganda,UGA,1983,2240333333.33333 +Uganda,UGA,1984,3615647477.05434 +Uganda,UGA,1985,3519666338.52454 +Uganda,UGA,1986,3923232122.12784 +Uganda,UGA,1987,6269511614.66235 +Uganda,UGA,1988,6508931651.66667 +Uganda,UGA,1989,5276480985.99937 +Uganda,UGA,1990,4304398865.88268 +Uganda,UGA,1991,3321729057.12215 +Uganda,UGA,1992,2857457860.05088 +Uganda,UGA,1993,3220439044.18949 +Uganda,UGA,1994,3990430446.71216 +Uganda,UGA,1995,5755818947.42125 +Uganda,UGA,1996,6044585326.938 +Uganda,UGA,1997,6269333313.17108 +Uganda,UGA,1998,6584815846.52754 +Uganda,UGA,1999,5998563257.94659 +Uganda,UGA,2000,6193246837.09687 +Uganda,UGA,2001,5840503868.57245 +Uganda,UGA,2002,6178563590.89254 +Uganda,UGA,2003,6336696288.98214 +Uganda,UGA,2004,7940362799.17997 +Uganda,UGA,2005,9013834373.41246 +Uganda,UGA,2006,9942597779.99265 +Uganda,UGA,2007,12292813603.2327 +Uganda,UGA,2008,14239026629.639 +Uganda,UGA,2009,21203769124.656 +Uganda,UGA,2010,20179411062.934 +Uganda,UGA,2011,20508595015.4506 +Uganda,UGA,2012,23516083900.4013 +Uganda,UGA,2013,24879053946.9135 +Uganda,UGA,2014,27927875335.8068 +Uganda,UGA,2015,27856380083.2478 +Uganda,UGA,2016,25527910090.6285 +Ukraine,UKR,1987,64087694038.2333 +Ukraine,UKR,1988,74703517902.6642 +Ukraine,UKR,1989,82709161099.1244 +Ukraine,UKR,1990,81456918678.5008 +Ukraine,UKR,1991,77464561149.5103 +Ukraine,UKR,1992,73942235330.437 +Ukraine,UKR,1993,65648559903.0571 +Ukraine,UKR,1994,52549555149.1978 +Ukraine,UKR,1995,48213868178.0873 +Ukraine,UKR,1996,44558077827.135 +Ukraine,UKR,1997,50150399791.647 +Ukraine,UKR,1998,41883241471.7365 +Ukraine,UKR,1999,31580639045.454 +Ukraine,UKR,2000,31261527363.144 +Ukraine,UKR,2001,38009344576.6088 +Ukraine,UKR,2002,42392896031.2394 +Ukraine,UKR,2003,50132953288.203 +Ukraine,UKR,2004,64883060725.7003 +Ukraine,UKR,2005,86142018069.3504 +Ukraine,UKR,2006,107753069306.931 +Ukraine,UKR,2007,142719009900.99 +Ukraine,UKR,2008,179992405832.321 +Ukraine,UKR,2009,117227769791.56 +Ukraine,UKR,2010,136013155905.036 +Ukraine,UKR,2011,163159671670.265 +Ukraine,UKR,2012,175781379051.433 +Ukraine,UKR,2013,183310146378.081 +Ukraine,UKR,2014,133503411375.739 +Ukraine,UKR,2015,91030959454.6961 +Ukraine,UKR,2016,93270479388.5243 +United Arab Emirates,ARE,1975,14720672506.5004 +United Arab Emirates,ARE,1976,19213022691.0526 +United Arab Emirates,ARE,1977,24871775164.6043 +United Arab Emirates,ARE,1978,23775831783.4263 +United Arab Emirates,ARE,1979,31225463217.7582 +United Arab Emirates,ARE,1980,43598748449.0479 +United Arab Emirates,ARE,1981,49333424135.1131 +United Arab Emirates,ARE,1982,46622718605.2847 +United Arab Emirates,ARE,1983,42803323345.1376 +United Arab Emirates,ARE,1984,41807954235.903 +United Arab Emirates,ARE,1985,40603650231.5445 +United Arab Emirates,ARE,1986,33943612094.7971 +United Arab Emirates,ARE,1987,36384908744.2114 +United Arab Emirates,ARE,1988,36275674203.2144 +United Arab Emirates,ARE,1989,41464995913.9199 +United Arab Emirates,ARE,1990,50701443748.2975 +United Arab Emirates,ARE,1991,51552165622.4462 +United Arab Emirates,ARE,1992,54239171887.769 +United Arab Emirates,ARE,1993,55625170253.337 +United Arab Emirates,ARE,1994,59305093979.842 +United Arab Emirates,ARE,1995,65743666575.8649 +United Arab Emirates,ARE,1996,73571233996.1863 +United Arab Emirates,ARE,1997,78839008444.5655 +United Arab Emirates,ARE,1998,75674336283.1858 +United Arab Emirates,ARE,1999,84445473110.9598 +United Arab Emirates,ARE,2000,104337372362.151 +United Arab Emirates,ARE,2001,103311640571.818 +United Arab Emirates,ARE,2002,109816201497.617 +United Arab Emirates,ARE,2003,124346358066.712 +United Arab Emirates,ARE,2004,147824370319.946 +United Arab Emirates,ARE,2005,180617018379.85 +United Arab Emirates,ARE,2006,222116541865.214 +United Arab Emirates,ARE,2007,257916133424.098 +United Arab Emirates,ARE,2008,315474615738.598 +United Arab Emirates,ARE,2009,253547358747.447 +United Arab Emirates,ARE,2010,289880430197.25 +United Arab Emirates,ARE,2011,350908390046.358 +United Arab Emirates,ARE,2012,374817974113.476 +United Arab Emirates,ARE,2013,390427289210.786 +United Arab Emirates,ARE,2014,403197682887.717 +United Arab Emirates,ARE,2015,357949199759.586 +United Arab Emirates,ARE,2016,348743265715.395 +United Kingdom,GBR,1960,72328047042.1588 +United Kingdom,GBR,1961,76694360635.9159 +United Kingdom,GBR,1962,80601939635.2483 +United Kingdom,GBR,1963,85443766670.4279 +United Kingdom,GBR,1964,93387598813.9269 +United Kingdom,GBR,1965,100595782309.165 +United Kingdom,GBR,1966,107090721447.057 +United Kingdom,GBR,1967,111185383409.521 +United Kingdom,GBR,1968,104702736248.084 +United Kingdom,GBR,1969,112676874821.987 +United Kingdom,GBR,1970,130671946244.3 +United Kingdom,GBR,1971,148113896325.14 +United Kingdom,GBR,1972,169965034965.035 +United Kingdom,GBR,1973,192537971582.558 +United Kingdom,GBR,1974,206131369798.971 +United Kingdom,GBR,1975,241756637168.142 +United Kingdom,GBR,1976,232614555256.065 +United Kingdom,GBR,1977,263066457352.172 +United Kingdom,GBR,1978,335883029721.956 +United Kingdom,GBR,1979,438994070309.191 +United Kingdom,GBR,1980,564947710899.373 +United Kingdom,GBR,1981,540765675241.158 +United Kingdom,GBR,1982,515048916841.37 +United Kingdom,GBR,1983,489618008185.539 +United Kingdom,GBR,1984,461487097632.349 +United Kingdom,GBR,1985,489285164271.047 +United Kingdom,GBR,1986,601452653180.885 +United Kingdom,GBR,1987,745162608269.325 +United Kingdom,GBR,1988,910122732123.799 +United Kingdom,GBR,1989,926884816753.927 +United Kingdom,GBR,1990,1093169389204.55 +United Kingdom,GBR,1991,1142797178130.51 +United Kingdom,GBR,1992,1179659529659.53 +United Kingdom,GBR,1993,1061388722255.55 +United Kingdom,GBR,1994,1140489745944.29 +United Kingdom,GBR,1995,1320255641470.73 +United Kingdom,GBR,1996,1392979719188.77 +United Kingdom,GBR,1997,1537090700720.37 +United Kingdom,GBR,1998,1623564094070.88 +United Kingdom,GBR,1999,1652167933991.26 +United Kingdom,GBR,2000,1635441065214.1 +United Kingdom,GBR,2001,1613034403339.57 +United Kingdom,GBR,2002,1757571942446.04 +United Kingdom,GBR,2003,2028488163265.31 +United Kingdom,GBR,2004,2389004027828.63 +United Kingdom,GBR,2005,2508103636363.64 +United Kingdom,GBR,2006,2678277828886.84 +United Kingdom,GBR,2007,3063005202080.83 +United Kingdom,GBR,2008,2875463235294.12 +United Kingdom,GBR,2009,2367127278392.27 +United Kingdom,GBR,2010,2429680444512.61 +United Kingdom,GBR,2011,2608824654243.59 +United Kingdom,GBR,2012,2646002634059.62 +United Kingdom,GBR,2013,2719509472492.7 +United Kingdom,GBR,2014,2998833559195.71 +United Kingdom,GBR,2015,2861090726739.55 +United Kingdom,GBR,2016,2618885692029.18 +United States,USA,1960,543300000000 +United States,USA,1961,563300000000 +United States,USA,1962,605100000000 +United States,USA,1963,638600000000 +United States,USA,1964,685800000000 +United States,USA,1965,743700000000 +United States,USA,1966,815000000000 +United States,USA,1967,861700000000 +United States,USA,1968,942500000000 +United States,USA,1969,1019900000000 +United States,USA,1970,1075884000000 +United States,USA,1971,1167770000000 +United States,USA,1972,1282449000000 +United States,USA,1973,1428549000000 +United States,USA,1974,1548825000000 +United States,USA,1975,1688923000000 +United States,USA,1976,1877587000000 +United States,USA,1977,2085951000000 +United States,USA,1978,2356571000000 +United States,USA,1979,2632143000000 +United States,USA,1980,2862505000000 +United States,USA,1981,3210956000000 +United States,USA,1982,3344991000000 +United States,USA,1983,3638137000000 +United States,USA,1984,4040693000000 +United States,USA,1985,4346734000000 +United States,USA,1986,4590155000000 +United States,USA,1987,4870217000000 +United States,USA,1988,5252629000000 +United States,USA,1989,5657693000000 +United States,USA,1990,5979589000000 +United States,USA,1991,6174043000000 +United States,USA,1992,6539299000000 +United States,USA,1993,6878718000000 +United States,USA,1994,7308755000000 +United States,USA,1995,7664060000000 +United States,USA,1996,8100201000000 +United States,USA,1997,8608515000000 +United States,USA,1998,9089168000000 +United States,USA,1999,9660624000000 +United States,USA,2000,10284779000000 +United States,USA,2001,10621824000000 +United States,USA,2002,10977514000000 +United States,USA,2003,11510670000000 +United States,USA,2004,12274928000000 +United States,USA,2005,13093726000000 +United States,USA,2006,13855888000000 +United States,USA,2007,14477635000000 +United States,USA,2008,14718582000000 +United States,USA,2009,14418739000000 +United States,USA,2010,14964372000000 +United States,USA,2011,15517926000000 +United States,USA,2012,16155255000000 +United States,USA,2013,16691517000000 +United States,USA,2014,17393103000000 +United States,USA,2015,18036648000000 +United States,USA,2016,18569100000000 +Uruguay,URY,1960,1242289212.04285 +Uruguay,URY,1961,1547388812.89969 +Uruguay,URY,1962,1710004464.40897 +Uruguay,URY,1963,1539681533.63786 +Uruguay,URY,1964,1975701727.50862 +Uruguay,URY,1965,1890769326.14221 +Uruguay,URY,1966,1809183974.52669 +Uruguay,URY,1967,1597721080.00991 +Uruguay,URY,1968,1593675330.16467 +Uruguay,URY,1969,2004435483.87097 +Uruguay,URY,1970,2137096774.19355 +Uruguay,URY,1971,2807258064.51613 +Uruguay,URY,1972,2189418001.37898 +Uruguay,URY,1973,3964295672.52444 +Uruguay,URY,1974,4090209681.97172 +Uruguay,URY,1975,3538283322.07726 +Uruguay,URY,1976,3667161241.48372 +Uruguay,URY,1977,4114667062.64917 +Uruguay,URY,1978,4910257282.93153 +Uruguay,URY,1979,7181185277.98651 +Uruguay,URY,1980,10163020115.7344 +Uruguay,URY,1981,11048335541.4933 +Uruguay,URY,1982,9178802162.6616 +Uruguay,URY,1983,5102281255.99986 +Uruguay,URY,1984,4850241442.17643 +Uruguay,URY,1985,4732017873.38369 +Uruguay,URY,1986,5880112788.40947 +Uruguay,URY,1987,7367494080.40014 +Uruguay,URY,1988,8213515458.51139 +Uruguay,URY,1989,8438951476.06644 +Uruguay,URY,1990,9298839655.23139 +Uruguay,URY,1991,11206193313.0458 +Uruguay,URY,1992,12878157305.7481 +Uruguay,URY,1993,15002144584.3663 +Uruguay,URY,1994,17474578502.4346 +Uruguay,URY,1995,19297663096.5506 +Uruguay,URY,1996,20515465834.0682 +Uruguay,URY,1997,23969746849.9221 +Uruguay,URY,1998,25385928198.3212 +Uruguay,URY,1999,23983945190.6202 +Uruguay,URY,2000,22823255801.8447 +Uruguay,URY,2001,20898788416.6348 +Uruguay,URY,2002,13606494599.4261 +Uruguay,URY,2003,12045631092.5353 +Uruguay,URY,2004,13686329890.1191 +Uruguay,URY,2005,17362857683.8545 +Uruguay,URY,2006,19579457966.0538 +Uruguay,URY,2007,23410572621.533 +Uruguay,URY,2008,30366213095.4256 +Uruguay,URY,2009,31660911290.3226 +Uruguay,URY,2010,40284481661.8726 +Uruguay,URY,2011,47962439293.3697 +Uruguay,URY,2012,51264390121.4144 +Uruguay,URY,2013,57531233350.9101 +Uruguay,URY,2014,57236013077.5187 +Uruguay,URY,2015,53274304214.8174 +Uruguay,URY,2016,52419720713.7316 +Uzbekistan,UZB,1990,13360607990.6751 +Uzbekistan,UZB,1991,13677622222.2222 +Uzbekistan,UZB,1992,12941297376.0933 +Uzbekistan,UZB,1993,13099013835.5111 +Uzbekistan,UZB,1994,12899156990.6156 +Uzbekistan,UZB,1995,13350468917.4115 +Uzbekistan,UZB,1996,13948892215.5689 +Uzbekistan,UZB,1997,14744603773.5849 +Uzbekistan,UZB,1998,14988971210.8383 +Uzbekistan,UZB,1999,17078465982.0282 +Uzbekistan,UZB,2000,13760374487.51 +Uzbekistan,UZB,2001,11401351420.1718 +Uzbekistan,UZB,2002,9687951055.22541 +Uzbekistan,UZB,2003,10128112401.4248 +Uzbekistan,UZB,2004,12030023547.8807 +Uzbekistan,UZB,2005,14307509838.8053 +Uzbekistan,UZB,2006,17330833852.919 +Uzbekistan,UZB,2007,22311393927.8817 +Uzbekistan,UZB,2008,29549438883.8338 +Uzbekistan,UZB,2009,33689223673.2577 +Uzbekistan,UZB,2010,39332770928.9426 +Uzbekistan,UZB,2011,45915191189.3237 +Uzbekistan,UZB,2012,51821573338.1312 +Uzbekistan,UZB,2013,57690453460.6205 +Uzbekistan,UZB,2014,63067077178.5381 +Uzbekistan,UZB,2015,66903804142.5395 +Uzbekistan,UZB,2016,67220335569.6147 +Vanuatu,VUT,1979,119258835.335525 +Vanuatu,VUT,1980,113423181.338956 +Vanuatu,VUT,1981,98746405.3924806 +Vanuatu,VUT,1982,98144643.8965575 +Vanuatu,VUT,1983,110123779.812821 +Vanuatu,VUT,1984,135553763.982667 +Vanuatu,VUT,1985,123698506.111363 +Vanuatu,VUT,1986,118691396.764915 +Vanuatu,VUT,1987,130834145.053665 +Vanuatu,VUT,1988,148545381.418421 +Vanuatu,VUT,1989,144482170.248703 +Vanuatu,VUT,1990,158397403.041175 +Vanuatu,VUT,1991,188869985.673352 +Vanuatu,VUT,1992,196142585.014816 +Vanuatu,VUT,1993,188080374.400605 +Vanuatu,VUT,1994,219260341.050642 +Vanuatu,VUT,1995,233902114.8683 +Vanuatu,VUT,1996,245177633.168933 +Vanuatu,VUT,1997,255890221.800293 +Vanuatu,VUT,1998,262301252.769228 +Vanuatu,VUT,1999,267999225.256634 +Vanuatu,VUT,2000,272014693.050806 +Vanuatu,VUT,2001,257926881.72043 +Vanuatu,VUT,2002,262603781.799059 +Vanuatu,VUT,2003,314463144.04219 +Vanuatu,VUT,2004,364996869.129618 +Vanuatu,VUT,2005,394962552.336108 +Vanuatu,VUT,2006,439376794.094041 +Vanuatu,VUT,2007,526428309.945088 +Vanuatu,VUT,2008,607958616.143415 +Vanuatu,VUT,2009,610066628.693058 +Vanuatu,VUT,2010,700804286.224354 +Vanuatu,VUT,2011,792149700.679116 +Vanuatu,VUT,2012,781702874.106058 +Vanuatu,VUT,2013,801787555.861121 +Vanuatu,VUT,2014,814954306.971033 +Vanuatu,VUT,2015,742432131.041002 +Vanuatu,VUT,2016,773502895.927602 +"Venezuela, RB",VEN,1960,8736939393.93939 +"Venezuela, RB",VEN,1961,9058121212.12121 +"Venezuela, RB",VEN,1962,10022000000 +"Venezuela, RB",VEN,1963,10823878787.8788 +"Venezuela, RB",VEN,1964,9111000000 +"Venezuela, RB",VEN,1965,9496244444.44444 +"Venezuela, RB",VEN,1966,9984400000 +"Venezuela, RB",VEN,1967,10356422222.2222 +"Venezuela, RB",VEN,1968,11343444444.4444 +"Venezuela, RB",VEN,1969,11795044444.4444 +"Venezuela, RB",VEN,1970,12848755555.5556 +"Venezuela, RB",VEN,1971,14625295454.5455 +"Venezuela, RB",VEN,1972,15922863636.3636 +"Venezuela, RB",VEN,1973,19466279069.7674 +"Venezuela, RB",VEN,1974,28985627906.9767 +"Venezuela, RB",VEN,1975,31303581395.3488 +"Venezuela, RB",VEN,1976,36187023255.814 +"Venezuela, RB",VEN,1977,42263209302.3256 +"Venezuela, RB",VEN,1978,46426511627.907 +"Venezuela, RB",VEN,1979,55653325581.3953 +"Venezuela, RB",VEN,1980,67018023255.814 +"Venezuela, RB",VEN,1981,75367139534.8837 +"Venezuela, RB",VEN,1982,76559883720.9302 +"Venezuela, RB",VEN,1983,78540255813.9535 +"Venezuela, RB",VEN,1984,56091900000 +"Venezuela, RB",VEN,1985,57935746666.6667 +"Venezuela, RB",VEN,1986,58793864197.5309 +"Venezuela, RB",VEN,1987,45343793103.4483 +"Venezuela, RB",VEN,1988,58428406896.5517 +"Venezuela, RB",VEN,1989,42119835734.8703 +"Venezuela, RB",VEN,1990,47028010660.9808 +"Venezuela, RB",VEN,1991,51749026408.4507 +"Venezuela, RB",VEN,1992,58450099415.2047 +"Venezuela, RB",VEN,1993,58124193832.5991 +"Venezuela, RB",VEN,1994,56531046464.6465 +"Venezuela, RB",VEN,1995,74906532239.819 +"Venezuela, RB",VEN,1996,68263823148.8138 +"Venezuela, RB",VEN,1997,85843534588.6206 +"Venezuela, RB",VEN,1998,91331203433.1629 +"Venezuela, RB",VEN,1999,97976886247.3172 +"Venezuela, RB",VEN,2000,117140723529.412 +"Venezuela, RB",VEN,2001,122903960204.505 +"Venezuela, RB",VEN,2002,92893587733.6549 +"Venezuela, RB",VEN,2003,83620628582.1082 +"Venezuela, RB",VEN,2004,112453382329.615 +"Venezuela, RB",VEN,2005,145510008134.75 +"Venezuela, RB",VEN,2006,183477522123.894 +"Venezuela, RB",VEN,2007,230364012575.687 +"Venezuela, RB",VEN,2008,315953388510.678 +"Venezuela, RB",VEN,2009,329787628928.472 +"Venezuela, RB",VEN,2010,393190682070.491 +"Venezuela, RB",VEN,2011,316482190800.364 +"Venezuela, RB",VEN,2012,381286237847.667 +"Venezuela, RB",VEN,2013,371006299120.244 +Vietnam,VNM,1985,14094687820.7445 +Vietnam,VNM,1986,26336617261.6954 +Vietnam,VNM,1987,36658108340.6777 +Vietnam,VNM,1988,25423812719.4906 +Vietnam,VNM,1989,6293304840.51995 +Vietnam,VNM,1990,6471740490.99897 +Vietnam,VNM,1991,9613369548.20359 +Vietnam,VNM,1992,9866990092.18743 +Vietnam,VNM,1993,13180953965.6854 +Vietnam,VNM,1994,16286434068.4834 +Vietnam,VNM,1995,20736163924.0492 +Vietnam,VNM,1996,24657470352.545 +Vietnam,VNM,1997,26843701147.496 +Vietnam,VNM,1998,27209601995.8245 +Vietnam,VNM,1999,28683657995.128 +Vietnam,VNM,2000,33640085738.648 +Vietnam,VNM,2001,35291349197.4254 +Vietnam,VNM,2002,37947904054.452 +Vietnam,VNM,2003,42717072869.3917 +Vietnam,VNM,2004,49424107709.8946 +Vietnam,VNM,2005,57633255618.2731 +Vietnam,VNM,2006,66371664817.0436 +Vietnam,VNM,2007,77414425532.2452 +Vietnam,VNM,2008,99130304099.1274 +Vietnam,VNM,2009,106014601171.036 +Vietnam,VNM,2010,115931749697.241 +Vietnam,VNM,2011,135539487317.008 +Vietnam,VNM,2012,155820001920.492 +Vietnam,VNM,2013,171222025117.381 +Vietnam,VNM,2014,186204652922.262 +Vietnam,VNM,2015,193241108709.536 +Vietnam,VNM,2016,202615893443.73 +Virgin Islands (U.S.),VIR,1960,24200000 +Virgin Islands (U.S.),VIR,1961,25700000 +Virgin Islands (U.S.),VIR,1962,36900000 +Virgin Islands (U.S.),VIR,1963,41400000 +Virgin Islands (U.S.),VIR,1964,53800000 +Virgin Islands (U.S.),VIR,1965,66500000 +Virgin Islands (U.S.),VIR,1966,84100000 +Virgin Islands (U.S.),VIR,1967,115400000 +Virgin Islands (U.S.),VIR,1968,173800000 +Virgin Islands (U.S.),VIR,1969,211300000 +Virgin Islands (U.S.),VIR,1970,219000000 +Virgin Islands (U.S.),VIR,1971,257000000 +Virgin Islands (U.S.),VIR,1972,307100000 +Virgin Islands (U.S.),VIR,1973,351600000 +Virgin Islands (U.S.),VIR,1974,395400000 +Virgin Islands (U.S.),VIR,1975,399800000 +Virgin Islands (U.S.),VIR,1976,440000000 +Virgin Islands (U.S.),VIR,1977,461800000 +Virgin Islands (U.S.),VIR,1978,512900000 +Virgin Islands (U.S.),VIR,1979,606700032 +Virgin Islands (U.S.),VIR,1980,727800000 +Virgin Islands (U.S.),VIR,1981,821800000 +Virgin Islands (U.S.),VIR,1982,832600000 +Virgin Islands (U.S.),VIR,1983,916899968 +Virgin Islands (U.S.),VIR,1984,985400000 +Virgin Islands (U.S.),VIR,1985,990400000 +Virgin Islands (U.S.),VIR,1986,1035600000 +Virgin Islands (U.S.),VIR,1987,1147800064 +Virgin Islands (U.S.),VIR,1988,1204600064 +Virgin Islands (U.S.),VIR,1989,1343900032 +Virgin Islands (U.S.),VIR,1990,1564700032 +Virgin Islands (U.S.),VIR,1991,1671200000 +Virgin Islands (U.S.),VIR,1992,1770899968 +Virgin Islands (U.S.),VIR,1993,1996000000 +Virgin Islands (U.S.),VIR,2002,3269000000 +Virgin Islands (U.S.),VIR,2003,3453000000 +Virgin Islands (U.S.),VIR,2004,3799000000 +Virgin Islands (U.S.),VIR,2005,4439000000 +Virgin Islands (U.S.),VIR,2006,4504000000 +Virgin Islands (U.S.),VIR,2007,4803000000 +Virgin Islands (U.S.),VIR,2008,4250000000 +Virgin Islands (U.S.),VIR,2009,4203000000 +Virgin Islands (U.S.),VIR,2010,4339000000 +Virgin Islands (U.S.),VIR,2011,4239000000 +Virgin Islands (U.S.),VIR,2012,4095000000 +Virgin Islands (U.S.),VIR,2013,3764000000 +Virgin Islands (U.S.),VIR,2014,3624000000 +Virgin Islands (U.S.),VIR,2015,3765000000 +West Bank and Gaza,PSE,1994,2843300000 +West Bank and Gaza,PSE,1995,3282800000 +West Bank and Gaza,PSE,1996,3409600000 +West Bank and Gaza,PSE,1997,3759800000 +West Bank and Gaza,PSE,1998,4067800000 +West Bank and Gaza,PSE,1999,4271200000 +West Bank and Gaza,PSE,2000,4313600000 +West Bank and Gaza,PSE,2001,4003700000 +West Bank and Gaza,PSE,2002,3555800000 +West Bank and Gaza,PSE,2003,3968000000 +West Bank and Gaza,PSE,2004,4329200000 +West Bank and Gaza,PSE,2005,4831800000 +West Bank and Gaza,PSE,2006,4910100000 +West Bank and Gaza,PSE,2007,5505800000 +West Bank and Gaza,PSE,2008,6673500000 +West Bank and Gaza,PSE,2009,7268200000 +West Bank and Gaza,PSE,2010,8913100000 +West Bank and Gaza,PSE,2011,10465400000 +West Bank and Gaza,PSE,2012,11279400000 +West Bank and Gaza,PSE,2013,12476000000 +West Bank and Gaza,PSE,2014,12715600000 +West Bank and Gaza,PSE,2015,12673000000 +West Bank and Gaza,PSE,2016,13397100000 +"Yemen, Rep.",YEM,1990,5647251908.39695 +"Yemen, Rep.",YEM,1991,5930370370.37037 +"Yemen, Rep.",YEM,1992,6463649985.01648 +"Yemen, Rep.",YEM,1993,5368270614.8468 +"Yemen, Rep.",YEM,1994,4167356037.1517 +"Yemen, Rep.",YEM,1995,4258788725.44991 +"Yemen, Rep.",YEM,1996,5785685310.86668 +"Yemen, Rep.",YEM,1997,6839039029.748 +"Yemen, Rep.",YEM,1998,6325219772.93811 +"Yemen, Rep.",YEM,1999,7641101221.43876 +"Yemen, Rep.",YEM,2000,9636342274.82408 +"Yemen, Rep.",YEM,2001,9854042164.67463 +"Yemen, Rep.",YEM,2002,10693278291.8149 +"Yemen, Rep.",YEM,2003,11777768086.8693 +"Yemen, Rep.",YEM,2004,13873500887.5612 +"Yemen, Rep.",YEM,2005,16753769531.6987 +"Yemen, Rep.",YEM,2006,19081722875.3022 +"Yemen, Rep.",YEM,2007,21656517484.2538 +"Yemen, Rep.",YEM,2008,26910851361.7555 +"Yemen, Rep.",YEM,2009,25130274124.2524 +"Yemen, Rep.",YEM,2010,30906749533.221 +"Yemen, Rep.",YEM,2011,32726417878.391 +"Yemen, Rep.",YEM,2012,35401339869.3055 +"Yemen, Rep.",YEM,2013,40415233436.1767 +"Yemen, Rep.",YEM,2014,43228583935.0365 +"Yemen, Rep.",YEM,2015,37733919936.2465 +"Yemen, Rep.",YEM,2016,27317605346.0714 +Zambia,ZMB,1960,713000000 +Zambia,ZMB,1961,696285714.285714 +Zambia,ZMB,1962,693142857.142857 +Zambia,ZMB,1963,718714285.714286 +Zambia,ZMB,1964,839428571.428571 +Zambia,ZMB,1965,1082857142.85714 +Zambia,ZMB,1966,1264285714.28571 +Zambia,ZMB,1967,1368000000 +Zambia,ZMB,1968,1605857142.85714 +Zambia,ZMB,1969,1965714285.71429 +Zambia,ZMB,1970,1825285714.28571 +Zambia,ZMB,1971,1687000000 +Zambia,ZMB,1972,1910714285.71429 +Zambia,ZMB,1973,2268714285.71429 +Zambia,ZMB,1974,3121833333.33333 +Zambia,ZMB,1975,2618666666.66667 +Zambia,ZMB,1976,2746714285.71429 +Zambia,ZMB,1977,2483000000 +Zambia,ZMB,1978,2813375000 +Zambia,ZMB,1979,3325500000 +Zambia,ZMB,1980,3829500000 +Zambia,ZMB,1981,3872666666.66667 +Zambia,ZMB,1982,3994777777.77778 +Zambia,ZMB,1983,3216307692.30769 +Zambia,ZMB,1984,2739444444.44445 +Zambia,ZMB,1985,2281258064.51613 +Zambia,ZMB,1986,1661948717.94872 +Zambia,ZMB,1987,2269894736.84211 +Zambia,ZMB,1988,3713614457.83133 +Zambia,ZMB,1989,3998637681.15942 +Zambia,ZMB,1990,3285217391.30435 +Zambia,ZMB,1991,3378882352.94118 +Zambia,ZMB,1992,3181921787.7095 +Zambia,ZMB,1993,3273237853.35689 +Zambia,ZMB,1994,3656647744.24858 +Zambia,ZMB,1995,3807067121.8609 +Zambia,ZMB,1996,3597220962.00017 +Zambia,ZMB,1997,4303281932.29365 +Zambia,ZMB,1998,3537683046.02331 +Zambia,ZMB,1999,3404311976.54941 +Zambia,ZMB,2000,3600683039.73254 +Zambia,ZMB,2001,4094480988.11931 +Zambia,ZMB,2002,4193845678.17033 +Zambia,ZMB,2003,4901839731.26571 +Zambia,ZMB,2004,6221077674.77871 +Zambia,ZMB,2005,8331870169.14977 +Zambia,ZMB,2006,12756858899.2812 +Zambia,ZMB,2007,14056957976.2648 +Zambia,ZMB,2008,17910858637.9048 +Zambia,ZMB,2009,15328342303.9575 +Zambia,ZMB,2010,20265556273.582 +Zambia,ZMB,2011,23460098339.7453 +Zambia,ZMB,2012,25503370699.2015 +Zambia,ZMB,2013,28045460442.1876 +Zambia,ZMB,2014,27150630607.2032 +Zambia,ZMB,2015,21154394545.895 +Zambia,ZMB,2016,19551093303.3377 +Zimbabwe,ZWE,1960,1052990400 +Zimbabwe,ZWE,1961,1096646600 +Zimbabwe,ZWE,1962,1117601600 +Zimbabwe,ZWE,1963,1159511700 +Zimbabwe,ZWE,1964,1217138000 +Zimbabwe,ZWE,1965,1311435800 +Zimbabwe,ZWE,1966,1281749500 +Zimbabwe,ZWE,1967,1397002000 +Zimbabwe,ZWE,1968,1479599900 +Zimbabwe,ZWE,1969,1747998800 +Zimbabwe,ZWE,1970,1884206300 +Zimbabwe,ZWE,1971,2178716300 +Zimbabwe,ZWE,1972,2677729400 +Zimbabwe,ZWE,1973,3309353600 +Zimbabwe,ZWE,1974,3982161400 +Zimbabwe,ZWE,1975,4371300700 +Zimbabwe,ZWE,1976,4318372000 +Zimbabwe,ZWE,1977,4364382100 +Zimbabwe,ZWE,1978,4351600500 +Zimbabwe,ZWE,1979,5177459400 +Zimbabwe,ZWE,1980,6678868200 +Zimbabwe,ZWE,1981,8011373800 +Zimbabwe,ZWE,1982,8539700700 +Zimbabwe,ZWE,1983,7764067000 +Zimbabwe,ZWE,1984,6352125900 +Zimbabwe,ZWE,1985,5637259300 +Zimbabwe,ZWE,1986,6217523700 +Zimbabwe,ZWE,1987,6741215100 +Zimbabwe,ZWE,1988,7814784100 +Zimbabwe,ZWE,1989,8286322700 +Zimbabwe,ZWE,1990,8783816700 +Zimbabwe,ZWE,1991,8641481700 +Zimbabwe,ZWE,1992,6751472200 +Zimbabwe,ZWE,1993,6563813300 +Zimbabwe,ZWE,1994,6890675000 +Zimbabwe,ZWE,1995,7111270700 +Zimbabwe,ZWE,1996,8553146600 +Zimbabwe,ZWE,1997,8529571600 +Zimbabwe,ZWE,1998,6401968200 +Zimbabwe,ZWE,1999,6858013100 +Zimbabwe,ZWE,2000,6689957600 +Zimbabwe,ZWE,2001,6777384700 +Zimbabwe,ZWE,2002,6342116400 +Zimbabwe,ZWE,2003,5727591800 +Zimbabwe,ZWE,2004,5805598400 +Zimbabwe,ZWE,2005,5755215200 +Zimbabwe,ZWE,2006,5443896500 +Zimbabwe,ZWE,2007,5291950100 +Zimbabwe,ZWE,2008,4415702800 +Zimbabwe,ZWE,2009,8366794000 +Zimbabwe,ZWE,2010,10052045200 +Zimbabwe,ZWE,2011,12071733500 +Zimbabwe,ZWE,2012,14058378300 +Zimbabwe,ZWE,2013,15223528900 +Zimbabwe,ZWE,2014,15834069900 +Zimbabwe,ZWE,2015,16072380200 +Zimbabwe,ZWE,2016,16289212000 diff --git a/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java b/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java index 4c3ee3e86..813f4e17d 100644 --- a/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java +++ b/main/tests/server/src/com/google/refine/tests/ProjectManagerStub.java @@ -35,13 +35,15 @@ package com.google.refine.tests; import java.io.IOException; import java.io.InputStream; +import java.util.Map; import org.apache.tools.tar.TarOutputStream; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.history.HistoryEntryManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.IMetadata; +import com.google.refine.model.medadata.MetadataFormat; /** * Stub used to make protected methods public for testing @@ -83,7 +85,7 @@ public class ProjectManagerStub extends ProjectManager { } @Override - public void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception { + public void saveMetadata(IMetadata metadata, long projectId) throws Exception { // empty } @@ -103,5 +105,4 @@ public class ProjectManagerStub extends ProjectManager { protected void saveWorkspace() { // empty } - } diff --git a/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java b/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java index 0f356f7e5..9b34f400a 100644 --- a/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java +++ b/main/tests/server/src/com/google/refine/tests/ProjectManagerTests.java @@ -51,8 +51,9 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import com.google.refine.ProjectMetadata; +import com.google.refine.ProjectManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.process.ProcessManager; import com.google.refine.tests.model.ProjectStub; @@ -73,11 +74,14 @@ public class ProjectManagerTests extends RefineTest { public void SetUp(){ pm = new ProjectManagerStub(); SUT = spy(pm); + project = mock(Project.class); metadata = mock(ProjectMetadata.class); + procmgr = mock(ProcessManager.class); when(project.getProcessManager()).thenReturn(procmgr); when(procmgr.hasPending()).thenReturn(false); // always false for now, but should test separately + when(project.getMetadata()).thenReturn(metadata); // cannot wire metadata directly with project, need mock object } @AfterMethod @@ -90,12 +94,9 @@ public class ProjectManagerTests extends RefineTest { @Test public void canRegisterProject(){ - SUT.registerProject(project, metadata); - AssertProjectRegistered(); - verify(metadata, times(1)).getTags(); - + verify(metadata).getTags(); verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); } @@ -110,16 +111,18 @@ public class ProjectManagerTests extends RefineTest { //run test SUT.ensureProjectSaved(project.id); - //assert and verify + //assert and verify it's registered under ProjectManager AssertProjectRegistered(); + try { - verify(SUT, times(1)).saveMetadata(metadata, project.id); + // make sure the ProjectManager does save the metadata + verify(SUT).saveMetadata(metadata, project.id); } catch (Exception e) { Assert.fail(); } this.verifySaveTimeCompared(1); - verify(SUT, times(1)).saveProject(project); - verify(metadata, times(1)).getTags(); + verify(SUT).saveProject(project); + verify(metadata).getTags(); //ensure end verifyNoMoreInteractions(project); @@ -130,25 +133,24 @@ public class ProjectManagerTests extends RefineTest { @Test public void canSaveAllModified(){ + // 1. register project 1 whenGetSaveTimes(project, metadata); //5 minute difference registerProject(project, metadata); - //add a second project to the cache + // 2. add a second project to the cache Project project2 = spy(new ProjectStub(2)); ProjectMetadata metadata2 = mock(ProjectMetadata.class); whenGetSaveTimes(project2, metadata2, 10); //not modified since the last save but within 30 seconds flush limit registerProject(project2, metadata2); - //check that the two projects are not the same + // 3. check that the two projects are not the same Assert.assertFalse(project.id == project2.id); + // 4. save all projects SUT.save(true); - verifySaved(project, metadata); - - verifySaved(project2, metadata2); - - verify(SUT, times(1)).saveWorkspace(); +// verifySaved(project2, metadata2); + verify(SUT).saveWorkspace(); } @Test @@ -160,17 +162,18 @@ public class ProjectManagerTests extends RefineTest { SUT.save(true); - verify(metadata, times(1)).getModified(); - verify(metadata, times(1)).getTags(); - verify(project, times(1)).getProcessManager(); - verify(project, times(2)).getLastSave(); - verify(project, times(1)).dispose(); + verify(metadata).getModified(); + verify(metadata).getTags(); + verify(project, never()).getMetadata(); + verify(project).getProcessManager(); + verify(project).getLastSave(); + verify(project).dispose(); verify(SUT, never()).saveProject(project); Assert.assertEquals(SUT.getProject(0), null); verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); - verify(SUT, times(1)).saveWorkspace(); + verify(SUT).saveWorkspace(); } @Test @@ -182,7 +185,7 @@ public class ProjectManagerTests extends RefineTest { verify(SUT, never()).saveProjects(Mockito.anyBoolean()); verify(SUT, never()).saveWorkspace(); - verify(metadata, times(1)).getTags(); + verify(metadata).getTags(); verifyNoMoreInteractions(project); verifyNoMoreInteractions(metadata); } @@ -197,7 +200,7 @@ public class ProjectManagerTests extends RefineTest { SUT.save(false); //not busy verifySaved(project, metadata); - verify(SUT, times(1)).saveWorkspace(); + verify(SUT).saveWorkspace(); } //TODO test canSaveAllModifiedWithRaceCondition @@ -205,10 +208,11 @@ public class ProjectManagerTests extends RefineTest { //-------------helpers------------- protected void registerProject(){ - this.registerProject(project, metadata); + SUT.registerProject(project, metadata); } - protected void registerProject(Project proj, ProjectMetadata meta){ - SUT.registerProject(proj, meta); + + protected void registerProject(Project proj, ProjectMetadata metadata) { + SUT.registerProject(proj, metadata); } protected void AssertProjectRegistered(){ @@ -244,12 +248,17 @@ public class ProjectManagerTests extends RefineTest { verify(metadata, times(times)).getModified(); verify(project, times(times)).getLastSave(); } - + + /** + * @see ProjectManager#save(boolean allModified) + * @param proj + * @param meta + */ protected void verifySaved(Project proj, ProjectMetadata meta){ - verify(meta, times(1)).getModified(); - verify(proj, times(2)).getLastSave(); - verify(SUT, times(1)).saveProject(proj); - verify(meta, times(1)).getTags(); + verify(meta).getModified(); + verify(proj).getLastSave(); + verify(SUT).saveProject(proj); + verify(meta).getTags(); verifyNoMoreInteractions(proj); verifyNoMoreInteractions(meta); diff --git a/main/tests/server/src/com/google/refine/tests/RefineTest.java b/main/tests/server/src/com/google/refine/tests/RefineTest.java index 2384d1dbb..7640ee55a 100644 --- a/main/tests/server/src/com/google/refine/tests/RefineTest.java +++ b/main/tests/server/src/com/google/refine/tests/RefineTest.java @@ -55,7 +55,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importers.SeparatorBasedImporter; import com.google.refine.importing.ImportingJob; @@ -66,6 +65,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.util.TestUtils; import com.google.refine.util.JSONUtilities; diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java index df220906d..97bf45951 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextSearchFacetTests.java @@ -45,6 +45,7 @@ import org.testng.annotations.Test; import com.google.refine.model.ModelException; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.facets.TextSearchFacet; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java b/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java index 0e8ae9a2c..a405f09c3 100644 --- a/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java +++ b/main/tests/server/src/com/google/refine/tests/commands/project/SetProjectMetadataCommandTests.java @@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.tests.commands.project; -import static org.mockito.Matchers.anyLong; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -57,9 +57,9 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.commands.project.SetProjectMetadataCommand; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineTest; public class SetProjectMetadataCommandTests extends RefineTest { @@ -102,6 +102,8 @@ public class SetProjectMetadataCommandTests extends RefineTest { // mock dependencies when(request.getParameter("project")).thenReturn(PROJECT_ID); when(projMan.getProject(anyLong())).thenReturn(proj); + + // below two should return the same object when(proj.getMetadata()).thenReturn(metadata); try { @@ -141,7 +143,7 @@ public class SetProjectMetadataCommandTests extends RefineTest { } // verify - verify(request, times(2)).getParameter("project"); + verify(request, times(1)).getParameter("name"); verify(projMan, times(1)).getProject(PROJECT_ID_LONG); verify(response, times(1)) @@ -154,6 +156,7 @@ public class SetProjectMetadataCommandTests extends RefineTest { } verify(pw, times(1)).write("{ \"code\" : \"ok\" }"); +// Assert.assertEquals(proj.getProjectMetadata().getName(), "subject"); Assert.assertEquals(proj.getMetadata().getSubject(), SUBJECT); } @@ -189,7 +192,7 @@ public class SetProjectMetadataCommandTests extends RefineTest { } verify(pw, times(1)).write("{ \"code\" : \"ok\" }"); - JSONObject obj = (JSONObject) proj.getMetadata().getUserMetadata().get(0); + JSONObject obj = (JSONObject) ((ProjectMetadata)proj.getMetadata()).getUserMetadata().get(0); Assert.assertEquals(obj.get("name"), "clientID"); Assert.assertEquals(obj.get("value"), "IBM"); } diff --git a/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java b/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java new file mode 100644 index 000000000..54af83701 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/commands/project/ValidateOperationTests.java @@ -0,0 +1,269 @@ +package com.google.refine.tests.commands.project; + +import static org.mockito.Mockito.mock; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.everit.json.schema.ValidationException; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.testng.Assert; + +import com.google.refine.ProjectManager; +import com.google.refine.importers.SeparatorBasedImporter; +import com.google.refine.model.Column; +import com.google.refine.model.medadata.DataPackageMetadata; +import com.google.refine.model.medadata.MetadataFactory; +import com.google.refine.model.medadata.MetadataFormat; +import com.google.refine.model.medadata.validator.ValidateOperation; +import com.google.refine.tests.importers.TsvCsvImporterTests; +import com.google.refine.util.ParsingUtilities; + +import io.frictionlessdata.tableschema.Field; +import io.frictionlessdata.tableschema.exceptions.ForeignKeyException; +import io.frictionlessdata.tableschema.exceptions.PrimaryKeyException; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(MetadataFactory.class) +public class ValidateOperationTests extends TsvCsvImporterTests { + private SeparatorBasedImporter parser = null; + + // variables + private static String input; + private DataPackageMetadata dataPackageMetadata; + + // mocks + private ProjectManager projMan = null; + + private String optionsString; + + @BeforeClass + public static void readData() throws IOException{ + //create input to test with + input = getFileContent("gdp.csv"); + // create an data type issue on the fly + input = input.replace("28434203615.4795", "XXXXXXXXXXXXX"); +// String input = "Country Name,Country Code,Year,Value\n" + +// "Arab World,ARB,1968,25760683041.0826\n" + +// "China, CHN,1968,16289212000\n" + +// "Arab World,ARB,1969,28434203615.4795XXX\n"; + } + + @Before + public void SetUp() throws JSONException, IOException, ValidationException, PrimaryKeyException, ForeignKeyException { + super.setUp(); + + optionsString = "{\"columnNames\": [\"Country Name\",\"Country Code\",\"Year\",\"Value\"]}"; + + // mockup + projMan = mock(ProjectManager.class); + ProjectManager.singleton = projMan; + + dataPackageMetadata = new DataPackageMetadata(); + String content = getJSONContent("datapackage-sample.json"); + dataPackageMetadata.loadFromStream(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8.name()))); + + // mock dependencies + //given + PowerMockito.mockStatic(MetadataFactory.class); + BDDMockito.given(MetadataFactory.buildMetadata(MetadataFormat.DATAPACKAGE_METADATA)).willReturn(dataPackageMetadata); + + parser = new SeparatorBasedImporter(); + parseOneFile(); + } + + @After + public void TearDown() { + projMan = null; + ProjectManager.singleton = null; + project = null; + } + + /** + * type or format error + */ + @Test + public void testTypeorFormatError() { + JSONObject optionObj = new JSONObject(optionsString); + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, + "should get records in report"); + } + + @Test + public void testMinimumConstraint() { + // options + optionsString = "{\"columnNames\": [\"Year\"]}"; + JSONObject optionObj = new JSONObject(optionsString); + + // add Constraint + String contraintKey = Field.CONSTRAINT_KEY_MINIMUM; + String contraintValue = "1962"; + Column column = project.columnModel.getColumnByName("Year"); + column.setType(Field.FIELD_TYPE_STRING); + addConstraint(column, contraintKey, contraintValue); + + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, + "should get records in report"); + } + + @Test + public void testMaximumConstraint() { + // options + optionsString = "{\"columnNames\": [\"Year\"]}"; + JSONObject optionObj = new JSONObject(optionsString); + + // add Constraint + String contraintKey = Field.CONSTRAINT_KEY_MAXIMUM; + String contraintValue = "2015"; + Column column = project.columnModel.getColumnByName("Year"); + column.setType(Field.FIELD_TYPE_STRING); + addConstraint(column, contraintKey, contraintValue); + + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, + "should get records in report"); + } + + @Test + public void testPatternConstraint() { + // options + optionsString = "{\"columnNames\": [\"Year\"]}"; + JSONObject optionObj = new JSONObject(optionsString); + + // add Constraint + String contraintKey = Field.CONSTRAINT_KEY_PATTERN; + String contraintValue = "[0-9]{4}"; + Column column = project.columnModel.getColumnByName("Year"); + column.setType(Field.FIELD_TYPE_STRING); + addConstraint(column, contraintKey, contraintValue); + + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertTrue(result.getJSONArray("validation-reports").length() == 0, + "should NOT get records in re" + + "port"); + } + + @Test + public void testEnumerableConstraint() { + // options + optionsString = "{\"columnNames\": [\"Year\"]}"; + JSONObject optionObj = new JSONObject(optionsString); + + // add Constraint + String contraintKey = Field.CONSTRAINT_KEY_ENUM; + String contraintValueStr = "[\"2010\",\"1990\",\"2015\"]"; + List contraintValue = ParsingUtilities.evaluateJsonStringToArray(contraintValueStr).toList(); + Column column = project.columnModel.getColumnByName("Year"); + column.setType(Field.FIELD_TYPE_STRING); + addConstraint(column, contraintKey, contraintValue); + + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertTrue(result.getJSONArray("validation-reports").length() > 0, + "should get records in report"); + } + + @Test + public void testEnumerableConstraint_ShouldReturnEmpty() { + // options + optionsString = "{\"columnNames\": [\"Year\"]}"; + JSONObject optionObj = new JSONObject(optionsString); + + // add Constraint + String contraintKey = Field.CONSTRAINT_KEY_ENUM; + String contraintValueStr = "["; + for (int i = 1950;i < 2018;i++) { + contraintValueStr += "\"" + i + "\","; + } + contraintValueStr += "]"; + + List contraintValue = ParsingUtilities.evaluateJsonStringToArray(contraintValueStr).toList(); + Column column = project.columnModel.getColumnByName("Year"); + column.setType(Field.FIELD_TYPE_STRING); + addConstraint(column, contraintKey, contraintValue); + + // run + JSONObject result = startValidateOperation(optionObj); + + Assert.assertEquals(result.getJSONArray("validation-reports").length(), 0); + } + + + private void addConstraint(Column column, String contraintKey, Object contraintValue) { + java.lang.reflect.Field f1; + try { + f1 = column.getClass().getDeclaredField("constraints"); + f1.setAccessible(true); + Map existingMap = (HashMap)f1.get(column); + if (existingMap == null) { + existingMap = new HashMap(); + } + existingMap.put(contraintKey, contraintValue); + f1.set(column, existingMap); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + + private JSONObject startValidateOperation(JSONObject options) { + // SUT + JSONObject report = new ValidateOperation(project, options).startProcess(); + + System.out.println("validation report:" + report.toString(2)); + + return report; + } + + private String getJSONContent(String fileName) throws IOException { + InputStream in = this.getClass().getClassLoader() + .getResourceAsStream(fileName); + String content = org.apache.commons.io.IOUtils.toString(in); + + return content; + } + + + private void parseOneFile() throws IOException{ + String sep = ","; + prepareOptions(sep, -1, 0, 0, 1, false, false); + parseOneFile(parser, new StringReader(input)); + + Assert.assertEquals(project.columnModel.columns.size(), 4); + } + + private static String getFileContent(String fileName) throws IOException { + InputStream in = ValidateOperationTests.class.getClassLoader() + .getResourceAsStream(fileName); + String content = org.apache.commons.io.IOUtils.toString(in); + + return content; + } +} diff --git a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java index d7e95e015..9fcf29fec 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/CsvExporterTests.java @@ -45,6 +45,7 @@ import java.time.ZoneId; import java.time.OffsetDateTime; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -214,8 +215,8 @@ public class CsvExporterTests extends RefineTest { Assert.fail(); } - String expectedOutput = ParsingUtilities.localDateToString(localDate) + "," + - ParsingUtilities.dateToString(date) + "\n"; + String expectedOutput = alignFractionalDigits(ParsingUtilities.localDateToString(localDate)) + "," + + alignFractionalDigits(ParsingUtilities.dateToString(date)) + "\n"; Assert.assertEquals(writer.toString(), expectedOutput); } @@ -243,4 +244,36 @@ public class CsvExporterTests extends RefineTest { project.rows.add(row); } } + + /** + * Given 2017-12-15T22:30:36.65(Z), convert to 2017-12-15T22:30:36.650(Z) + * @param dateTime + * @return + */ + protected String alignFractionalDigits(String dateTime) { + String[] parts = dateTime.split("\\."); + if (parts.length < 2) + return dateTime; + + String fraction = parts[1].replace("Z", ""); + + return parts[0] + "." + + StringUtils.rightPad(fraction, 3, "0") + + (dateTime.endsWith("Z") ? "Z" : ""); + } + + @Test + public void alignFractionalDigitsTest(){ + String input = "2017-12-15T22:30:36.65"; + String expected = "2017-12-15T22:30:36.650"; + Assert.assertEquals(alignFractionalDigits(input), expected); + } + + @Test + public void alignFractionalDigitsWithZTest(){ + String input = "2017-12-15T22:30:36.65Z"; + String expected = "2017-12-15T22:30:36.650Z"; + Assert.assertEquals(alignFractionalDigits(input), expected); + } + } diff --git a/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java index 47b38ca0e..46133ed3a 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/HtmlExporterTests.java @@ -50,7 +50,6 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.HtmlTableExporter; import com.google.refine.exporters.WriterExporter; @@ -59,6 +58,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java index d9830a067..49f23aa2f 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/TemplatingExporterTests.java @@ -48,7 +48,6 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.TemplatingExporter; import com.google.refine.exporters.WriterExporter; @@ -57,6 +56,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java b/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java index f5e18e7f6..93daf4348 100644 --- a/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/exporters/XlsExporterTests.java @@ -50,7 +50,6 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.browsing.Engine; import com.google.refine.exporters.StreamExporter; import com.google.refine.exporters.XlsExporter; @@ -59,6 +58,7 @@ import com.google.refine.model.Column; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.ProjectManagerStub; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/expr/functions/FunctionTests.java b/main/tests/server/src/com/google/refine/tests/expr/functions/FunctionTests.java index dd185f47d..cb050e8aa 100644 --- a/main/tests/server/src/com/google/refine/tests/expr/functions/FunctionTests.java +++ b/main/tests/server/src/com/google/refine/tests/expr/functions/FunctionTests.java @@ -52,6 +52,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/expr/functions/booleans/BooleanTests.java b/main/tests/server/src/com/google/refine/tests/expr/functions/booleans/BooleanTests.java index 7862688c7..0b57420bc 100644 --- a/main/tests/server/src/com/google/refine/tests/expr/functions/booleans/BooleanTests.java +++ b/main/tests/server/src/com/google/refine/tests/expr/functions/booleans/BooleanTests.java @@ -50,6 +50,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java index 08549a7bf..b29a7e56d 100644 --- a/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java +++ b/main/tests/server/src/com/google/refine/tests/history/HistoryTests.java @@ -47,10 +47,10 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.refine.ProjectManager; -import com.google.refine.ProjectMetadata; import com.google.refine.history.History; import com.google.refine.history.HistoryEntry; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java index d5d65e018..dfcf05bbf 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java +++ b/main/tests/server/src/com/google/refine/tests/importers/ImporterTest.java @@ -10,7 +10,6 @@ import java.util.List; import org.json.JSONObject; import org.mockito.Mockito; -import com.google.refine.ProjectMetadata; import com.google.refine.RefineServlet; import com.google.refine.importers.ImportingParserBase; import com.google.refine.importers.tree.ImportColumnGroup; @@ -19,10 +18,11 @@ import com.google.refine.importers.tree.XmlImportUtilities; import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingManager; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineServletStub; import com.google.refine.tests.RefineTest; -abstract class ImporterTest extends RefineTest { +abstract public class ImporterTest extends RefineTest { //mock dependencies protected Project project; protected ProjectMetadata metadata; diff --git a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java index 35b911a85..3f6ba1973 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/JsonImporterTests.java @@ -96,7 +96,6 @@ public class JsonImporterTests extends ImporterTest { public void canParseSample(){ RunTest(getSample()); - log(project); assertProjectCreated(project, 4, 6); Row row = project.rows.get(0); @@ -109,7 +108,6 @@ public class JsonImporterTests extends ImporterTest { public void canParseSampleWithDuplicateNestedElements(){ RunTest(getSampleWithDuplicateNestedElements()); - log(project); assertProjectCreated(project, 4, 12); Row row = project.rows.get(0); @@ -125,7 +123,6 @@ public class JsonImporterTests extends ImporterTest { RunTest(getSampleWithLineBreak()); - log(project); assertProjectCreated(project, 4, 6); Row row = project.rows.get(3); @@ -139,7 +136,6 @@ public class JsonImporterTests extends ImporterTest { public void testElementsWithVaryingStructure(){ RunTest(getSampleWithVaryingStructure()); - log(project); assertProjectCreated(project, 5, 6); Assert.assertEquals( project.columnModel.getColumnByCellIndex(4).getName(), JsonImporter.ANONYMOUS + " - genre"); @@ -156,7 +152,6 @@ public class JsonImporterTests extends ImporterTest { @Test public void testElementWithNestedTree(){ RunTest(getSampleWithTreeStructure()); - log(project); assertProjectCreated(project, 5, 6); Assert.assertEquals(project.columnModel.columnGroups.size(),1); @@ -180,7 +175,6 @@ public class JsonImporterTests extends ImporterTest { JSONUtilities.safePut(options, "recordPath", path); RunTest(mqlOutput, options); - log(project); assertProjectCreated(project,3,16); } @@ -214,7 +208,6 @@ public class JsonImporterTests extends ImporterTest { " }\n" + "]\n"; RunTest(ScraperwikiOutput); - log(project); assertProjectCreated(project,9,2); } @@ -299,7 +292,6 @@ public class JsonImporterTests extends ImporterTest { public void testJsonDatatypes(){ RunTest(getSampleWithDataTypes()); - log(project); assertProjectCreated(project, 2, 21,4); Assert.assertEquals( project.columnModel.getColumnByCellIndex(0).getName(), JsonImporter.ANONYMOUS + " - id"); @@ -370,7 +362,6 @@ public class JsonImporterTests extends ImporterTest { String fileName = "grid_small.json"; RunComplexJSONTest(getComplexJSON(fileName)); - log(project); logger.info("************************ columnu number:" + project.columnModel.columns.size() + ". \tcolumn groups number:" + project.columnModel.columnGroups.size() + ".\trow number:" + project.rows.size() + ".\trecord number:" + project.recordModel.getRecordCount()) ; diff --git a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java index 8a2ac99e2..ba9145541 100644 --- a/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java +++ b/main/tests/server/src/com/google/refine/tests/importers/TsvCsvImporterTests.java @@ -58,10 +58,10 @@ public class TsvCsvImporterTests extends ImporterTest { } //constants - String SAMPLE_ROW = "NDB_No,Shrt_Desc,Water"; + private String SAMPLE_ROW = "NDB_No,Shrt_Desc,Water"; //System Under Test - SeparatorBasedImporter SUT = null; + private SeparatorBasedImporter SUT = null; @Override @BeforeMethod @@ -543,7 +543,7 @@ public class TsvCsvImporterTests extends ImporterTest { }; } - private void prepareOptions( + protected void prepareOptions( String sep, int limit, int skip, int ignoreLines, int headerLines, boolean guessValueType, boolean ignoreQuotes) { diff --git a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java index 850c45df3..8a1e12710 100644 --- a/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java +++ b/main/tests/server/src/com/google/refine/tests/importing/ImportingUtilitiesTests.java @@ -4,8 +4,8 @@ import org.json.JSONObject; import org.testng.Assert; import org.testng.annotations.Test; -import com.google.refine.ProjectMetadata; import com.google.refine.importing.ImportingUtilities; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.tests.RefineTest; public class ImportingUtilitiesTests extends RefineTest { diff --git a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java index 146f323bc..8acb8f49b 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java @@ -52,6 +52,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.row.RowRemovalOperation; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/model/TextSearchFacetTests.java b/main/tests/server/src/com/google/refine/tests/model/TextSearchFacetTests.java new file mode 100644 index 000000000..38ed2f299 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/model/TextSearchFacetTests.java @@ -0,0 +1,265 @@ +/* + +Copyright 2010, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +package com.google.refine.tests.model; + +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.refine.ProjectManager; +import com.google.refine.RefineServlet; +import com.google.refine.browsing.RowFilter; +import com.google.refine.browsing.facets.TextSearchFacet; +import com.google.refine.importers.SeparatorBasedImporter; +import com.google.refine.importing.ImportingJob; +import com.google.refine.importing.ImportingManager; +import com.google.refine.io.FileProjectManager; +import com.google.refine.model.ModelException; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; +import com.google.refine.tests.RefineServletStub; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + + +public class TextSearchFacetTests extends RefineTest { + // dependencies + private RefineServlet servlet; + private Project project; + private ProjectMetadata pm; + private JSONObject options; + private ImportingJob job; + private SeparatorBasedImporter importer; + private TextSearchFacet textfilter; + private JSONObject textsearchfacet; + private RowFilter rowfilter; + + @Override + @BeforeTest + public void init() { + logger = LoggerFactory.getLogger(this.getClass()); + } + + @BeforeMethod + public void setUp() throws JSONException, IOException, ModelException { + servlet = new RefineServletStub(); + File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir"); + FileProjectManager.initialize(dir); + project = new Project(); + pm = new ProjectMetadata(); + pm.setName("TextSearchFacet test"); + ProjectManager.singleton.registerProject(project, pm); + options = mock(JSONObject.class); + + ImportingManager.initialize(servlet); + job = ImportingManager.createJob(); + importer = new SeparatorBasedImporter(); + + String csv = "Value\n" + + "a\n" + + "b\n" + + "ab\n" + + "Abc\n"; + prepareOptions(",", 10, 0, 0, 1, false, false); + List exceptions = new ArrayList(); + importer.parseOneFile(project, pm, job, "filesource", new StringReader(csv), -1, options, exceptions); + project.update(); + ProjectManager.singleton.registerProject(project, pm); + } + + @AfterMethod + public void tearDown() { + ImportingManager.disposeJob(job.id); + ProjectManager.singleton.deleteProject(project.id); + job = null; + project = null; + pm = null; + options = null; + } + + /** + * Test to demonstrate the intended behaviour of the function + */ + + @Test + public void testTextFilter() throws Exception { + //Apply text filter "a" + + //Column: "Value" + //Filter Query: "a" + //Mode: "text" + //Case sensitive: False + //Invert: False + String filter = "{\"type\":\"text\"," + + "\"name\":\"Value\"," + + "\"columnName\":\"Value\"," + + "\"mode\":\"text\"," + + "\"caseSensitive\":false," + + "\"invert\":false," + + "\"query\":\"a\"}"; + + //Add the facet to the project and create a row filter + textfilter = new TextSearchFacet(); + textsearchfacet = new JSONObject(filter); + textfilter.initializeFromJSON(project,textsearchfacet); + rowfilter = textfilter.getRowFilter(project); + + //Check each row in the project against the filter + Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),true); + Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); + Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),true); + Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true); + } + + @Test + public void testInvertedTextFilter() throws Exception { + //Apply inverted text filter "a" + + //Column: "Value" + //Filter Query: "a" + //Mode: "text" + //Case sensitive: False + //Invert: True + String filter = "{\"type\":\"text\"," + + "\"name\":\"Value\"," + + "\"columnName\":\"Value\"," + + "\"mode\":\"text\"," + + "\"caseSensitive\":false," + + "\"invert\":true," + + "\"query\":\"a\"}"; + + //Add the facet to the project and create a row filter + textfilter = new TextSearchFacet(); + textsearchfacet = new JSONObject(filter); + textfilter.initializeFromJSON(project,textsearchfacet); + rowfilter = textfilter.getRowFilter(project); + + //Check each row in the project against the filter + Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); + Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),true); + Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); + Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false); + } + + @Test + public void testRegExFilter() throws Exception { + //Apply regular expression filter "[bc]" + + //Column: "Value" + //Filter Query: "[bc]" + //Mode: "regex" + //Case sensitive: False + //Invert: False + String filter = "{\"type\":\"text\"," + + "\"name\":\"Value\"," + + "\"columnName\":\"Value\"," + + "\"mode\":\"regex\"," + + "\"caseSensitive\":false," + + "\"invert\":false," + + "\"query\":\"[bc]\"}"; + + //Add the facet to the project and create a row filter + textfilter = new TextSearchFacet(); + textsearchfacet = new JSONObject(filter); + textfilter.initializeFromJSON(project,textsearchfacet); + rowfilter = textfilter.getRowFilter(project); + + //Check each row in the project against the filter + Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); + Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),true); + Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),true); + Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true); + } + + @Test + public void testCaseSensitiveFilter() throws Exception { + //Apply case-sensitive filter "A" + + //Column: "Value" + //Filter Query: "A" + //Mode: "text" + //Case sensitive: True + //Invert: False + String filter = "{\"type\":\"text\"," + + "\"name\":\"Value\"," + + "\"columnName\":\"Value\"," + + "\"mode\":\"text\"," + + "\"caseSensitive\":true," + + "\"invert\":false," + + "\"query\":\"A\"}"; + + //Add the facet to the project and create a row filter + textfilter = new TextSearchFacet(); + textsearchfacet = new JSONObject(filter); + textfilter.initializeFromJSON(project,textsearchfacet); + rowfilter = textfilter.getRowFilter(project); + + //Check each row in the project against the filter + //Expect to retrieve one row containing "Abc" + Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); + Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); + Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); + Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true); + } + + private void prepareOptions( + String sep, int limit, int skip, int ignoreLines, + int headerLines, boolean guessValueType, boolean ignoreQuotes) { + + whenGetStringOption("separator", options, sep); + whenGetIntegerOption("limit", options, limit); + whenGetIntegerOption("skipDataLines", options, skip); + whenGetIntegerOption("ignoreLines", options, ignoreLines); + whenGetIntegerOption("headerLines", options, headerLines); + whenGetBooleanOption("guessCellValueTypes", options, guessValueType); + whenGetBooleanOption("processQuotes", options, !ignoreQuotes); + whenGetBooleanOption("storeBlankCellsAsNulls", options, true); + } + + +} + diff --git a/main/tests/server/src/com/google/refine/tests/model/UrlFetchingTests.java b/main/tests/server/src/com/google/refine/tests/model/UrlFetchingTests.java index 59073399c..44101862c 100644 --- a/main/tests/server/src/com/google/refine/tests/model/UrlFetchingTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/UrlFetchingTests.java @@ -51,6 +51,7 @@ import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; import com.google.refine.model.Row; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.operations.OnError; diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java index e28c29339..fbac646cf 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/JoinMultiValuedCellsTests.java @@ -42,8 +42,8 @@ import org.testng.annotations.Test; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; -import com.google.refine.process.Process; import com.google.refine.operations.cell.MultiValuedCellJoinOperation; +import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java new file mode 100644 index 000000000..d44cdeaf1 --- /dev/null +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/KeyValueColumnizeTests.java @@ -0,0 +1,173 @@ +/* + +Copyright 2010, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +package com.google.refine.tests.operations.cell; + +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.refine.ProjectManager; +import com.google.refine.RefineServlet; +import com.google.refine.importers.SeparatorBasedImporter; +import com.google.refine.importing.ImportingJob; +import com.google.refine.importing.ImportingManager; +import com.google.refine.io.FileProjectManager; +import com.google.refine.model.AbstractOperation; +import com.google.refine.model.ModelException; +import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; +import com.google.refine.operations.cell.KeyValueColumnizeOperation; +import com.google.refine.process.Process; +import com.google.refine.tests.RefineServletStub; +import com.google.refine.tests.RefineTest; +import com.google.refine.tests.util.TestUtils; + + +public class KeyValueColumnizeTests extends RefineTest { + // dependencies + private RefineServlet servlet; + private Project project; + private ProjectMetadata pm; + private JSONObject options; + private ImportingJob job; + private SeparatorBasedImporter importer; + + + @Override + @BeforeTest + public void init() { + logger = LoggerFactory.getLogger(this.getClass()); + } + + @BeforeMethod + public void SetUp() throws JSONException, IOException, ModelException { + servlet = new RefineServletStub(); + File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir"); + FileProjectManager.initialize(dir); + project = new Project(); + pm = new ProjectMetadata(); + pm.setName("KeyValueColumnize test"); + ProjectManager.singleton.registerProject(project, pm); + options = mock(JSONObject.class); + + ImportingManager.initialize(servlet); + job = ImportingManager.createJob(); + importer = new SeparatorBasedImporter(); + } + + @AfterMethod + public void TearDown() { + ImportingManager.disposeJob(job.id); + ProjectManager.singleton.deleteProject(project.id); + job = null; + project = null; + pm = null; + options = null; + } + + /** + * Test to demonstrate the intended behaviour of the function, for issue #1214 + * https://github.com/OpenRefine/OpenRefine/issues/1214 + */ + + @Test + public void testKeyValueColumnize() throws Exception { + String csv = "Key,Value\n" + + "merchant,Katie\n" + + "fruit,apple\n" + + "price,1.2\n" + + "fruit,pear\n" + + "price,1.5\n" + + "merchant,John\n" + + "fruit,banana\n" + + "price,3.1\n"; + prepareOptions(",", 20, 0, 0, 1, false, false); + List exceptions = new ArrayList(); + importer.parseOneFile(project, pm, job, "filesource", new StringReader(csv), -1, options, exceptions); + project.update(); + ProjectManager.singleton.registerProject(project, pm); + + AbstractOperation op = new KeyValueColumnizeOperation( + "Key", + "Value", + null); + Process process = op.createProcess(project, new Properties()); + process.performImmediate(); + + int merchantCol = project.columnModel.getColumnByName("merchant").getCellIndex(); + int fruitCol = project.columnModel.getColumnByName("fruit").getCellIndex(); + int priceCol = project.columnModel.getColumnByName("price").getCellIndex(); + + Assert.assertEquals(project.rows.get(0).getCellValue(merchantCol), "Katie"); + Assert.assertEquals(project.rows.get(1).getCellValue(merchantCol), null); + Assert.assertEquals(project.rows.get(2).getCellValue(merchantCol), "John"); + Assert.assertEquals(project.rows.get(0).getCellValue(fruitCol), "apple"); + Assert.assertEquals(project.rows.get(1).getCellValue(fruitCol), "pear"); + Assert.assertEquals(project.rows.get(2).getCellValue(fruitCol), "banana"); + Assert.assertEquals(project.rows.get(0).getCellValue(priceCol), "1.2"); + Assert.assertEquals(project.rows.get(1).getCellValue(priceCol), "1.5"); + Assert.assertEquals(project.rows.get(2).getCellValue(priceCol), "3.1"); + } + + private void prepareOptions( + String sep, int limit, int skip, int ignoreLines, + int headerLines, boolean guessValueType, boolean ignoreQuotes) { + + whenGetStringOption("separator", options, sep); + whenGetIntegerOption("limit", options, limit); + whenGetIntegerOption("skipDataLines", options, skip); + whenGetIntegerOption("ignoreLines", options, ignoreLines); + whenGetIntegerOption("headerLines", options, headerLines); + whenGetBooleanOption("guessCellValueTypes", options, guessValueType); + whenGetBooleanOption("processQuotes", options, !ignoreQuotes); + whenGetBooleanOption("storeBlankCellsAsNulls", options, true); + } + + +} + diff --git a/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java b/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java index e52fcebec..ad810eb08 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/cell/TransposeTests.java @@ -42,6 +42,7 @@ import org.testng.annotations.Test; import com.google.refine.model.AbstractOperation; import com.google.refine.model.Project; +import com.google.refine.model.medadata.ProjectMetadata; import com.google.refine.operations.cell.KeyValueColumnizeOperation; import com.google.refine.process.Process; import com.google.refine.tests.RefineTest; diff --git a/main/tests/server/src/com/google/refine/tests/recon/DataExtensionTests.java b/main/tests/server/src/com/google/refine/tests/recon/DataExtensionTests.java index 42c192a9c..33abd060e 100644 --- a/main/tests/server/src/com/google/refine/tests/recon/DataExtensionTests.java +++ b/main/tests/server/src/com/google/refine/tests/recon/DataExtensionTests.java @@ -36,9 +36,9 @@ package com.google.refine.tests.recon; import static org.mockito.Mockito.mock; import java.io.IOException; -import java.util.Properties; -import java.util.List; import java.util.ArrayList; +import java.util.List; +import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; @@ -53,9 +53,9 @@ import com.google.refine.browsing.Engine; import com.google.refine.model.Cell; import com.google.refine.model.ModelException; import com.google.refine.model.Project; -import com.google.refine.model.Row; import com.google.refine.model.Recon; import com.google.refine.model.ReconCandidate; +import com.google.refine.model.Row; import com.google.refine.process.Process; import com.google.refine.process.ProcessManager; import com.google.refine.operations.EngineDependentOperation; diff --git a/main/webapp/WEB-INF/lib-src/datapackage-java-1.0-SNAPSHOT-sources.jar b/main/webapp/WEB-INF/lib-src/datapackage-java-1.0-SNAPSHOT-sources.jar new file mode 100644 index 000000000..0e5959abf Binary files /dev/null and b/main/webapp/WEB-INF/lib-src/datapackage-java-1.0-SNAPSHOT-sources.jar differ diff --git a/main/webapp/WEB-INF/lib-src/tableschema-java-1.0-SNAPSHOT-sources.jar b/main/webapp/WEB-INF/lib-src/tableschema-java-1.0-SNAPSHOT-sources.jar new file mode 100644 index 000000000..d9ddf411e Binary files /dev/null and b/main/webapp/WEB-INF/lib-src/tableschema-java-1.0-SNAPSHOT-sources.jar differ diff --git a/main/webapp/WEB-INF/lib/bsh-2.0b4.jar b/main/webapp/WEB-INF/lib/bsh-2.0b4.jar new file mode 100644 index 000000000..36fe03d71 Binary files /dev/null and b/main/webapp/WEB-INF/lib/bsh-2.0b4.jar differ diff --git a/main/webapp/WEB-INF/lib/byte-buddy-1.6.14.jar b/main/webapp/WEB-INF/lib/byte-buddy-1.6.14.jar new file mode 100644 index 000000000..04c0f8478 Binary files /dev/null and b/main/webapp/WEB-INF/lib/byte-buddy-1.6.14.jar differ diff --git a/main/webapp/WEB-INF/lib/byte-buddy-agent-1.6.14.jar b/main/webapp/WEB-INF/lib/byte-buddy-agent-1.6.14.jar new file mode 100644 index 000000000..350e6cc98 Binary files /dev/null and b/main/webapp/WEB-INF/lib/byte-buddy-agent-1.6.14.jar differ diff --git a/main/webapp/WEB-INF/lib/cglib-nodep-2.2.2.jar b/main/webapp/WEB-INF/lib/cglib-nodep-2.2.2.jar new file mode 100644 index 000000000..02d81e880 Binary files /dev/null and b/main/webapp/WEB-INF/lib/cglib-nodep-2.2.2.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-beanutils-1.9.3.jar b/main/webapp/WEB-INF/lib/commons-beanutils-1.9.3.jar new file mode 100644 index 000000000..6728154e5 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-beanutils-1.9.3.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-codec-1.6.jar b/main/webapp/WEB-INF/lib/commons-codec-1.6.jar deleted file mode 100644 index ee1bc49ac..000000000 Binary files a/main/webapp/WEB-INF/lib/commons-codec-1.6.jar and /dev/null differ diff --git a/main/webapp/WEB-INF/lib/commons-collections-3.2.1.jar b/main/webapp/WEB-INF/lib/commons-collections-3.2.1.jar deleted file mode 100644 index c35fa1fee..000000000 Binary files a/main/webapp/WEB-INF/lib/commons-collections-3.2.1.jar and /dev/null differ diff --git a/main/webapp/WEB-INF/lib/commons-collections-3.2.2.jar b/main/webapp/WEB-INF/lib/commons-collections-3.2.2.jar new file mode 100644 index 000000000..fa5df82a6 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-collections-3.2.2.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-csv-1.5.jar b/main/webapp/WEB-INF/lib/commons-csv-1.5.jar new file mode 100644 index 000000000..eb4775e30 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-csv-1.5.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-digester-1.8.1.jar b/main/webapp/WEB-INF/lib/commons-digester-1.8.1.jar new file mode 100644 index 000000000..7abda9696 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-digester-1.8.1.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-io-1.4.jar b/main/webapp/WEB-INF/lib/commons-io-1.4.jar deleted file mode 100644 index 133dc6cb3..000000000 Binary files a/main/webapp/WEB-INF/lib/commons-io-1.4.jar and /dev/null differ diff --git a/main/webapp/WEB-INF/lib/commons-lang3-3.6.jar b/main/webapp/WEB-INF/lib/commons-lang3-3.6.jar new file mode 100644 index 000000000..c25fd4d32 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-lang3-3.6.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-logging-1.1.1.jar b/main/webapp/WEB-INF/lib/commons-logging-1.1.1.jar deleted file mode 100644 index 1deef144c..000000000 Binary files a/main/webapp/WEB-INF/lib/commons-logging-1.1.1.jar and /dev/null differ diff --git a/main/webapp/WEB-INF/lib/commons-logging-1.2.jar b/main/webapp/WEB-INF/lib/commons-logging-1.2.jar new file mode 100644 index 000000000..93a3b9f6d Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-logging-1.2.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-text-1.1.jar b/main/webapp/WEB-INF/lib/commons-text-1.1.jar new file mode 100644 index 000000000..73fb4ae72 Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-text-1.1.jar differ diff --git a/main/webapp/WEB-INF/lib/commons-validator-1.5.1.jar b/main/webapp/WEB-INF/lib/commons-validator-1.5.1.jar new file mode 100644 index 000000000..f90c6958c Binary files /dev/null and b/main/webapp/WEB-INF/lib/commons-validator-1.5.1.jar differ diff --git a/main/webapp/WEB-INF/lib/datapackage-java-1.0-SNAPSHOT.jar b/main/webapp/WEB-INF/lib/datapackage-java-1.0-SNAPSHOT.jar new file mode 100644 index 000000000..a5486d34f Binary files /dev/null and b/main/webapp/WEB-INF/lib/datapackage-java-1.0-SNAPSHOT.jar differ diff --git a/main/webapp/WEB-INF/lib/hamcrest-all-1.3.jar b/main/webapp/WEB-INF/lib/hamcrest-all-1.3.jar new file mode 100644 index 000000000..6f62ba00c Binary files /dev/null and b/main/webapp/WEB-INF/lib/hamcrest-all-1.3.jar differ diff --git a/main/webapp/WEB-INF/lib/hamcrest-core-1.3.jar b/main/webapp/WEB-INF/lib/hamcrest-core-1.3.jar new file mode 100644 index 000000000..9d5fe16e3 Binary files /dev/null and b/main/webapp/WEB-INF/lib/hamcrest-core-1.3.jar differ diff --git a/main/webapp/WEB-INF/lib/javassist-3.21.0-GA.jar b/main/webapp/WEB-INF/lib/javassist-3.21.0-GA.jar new file mode 100644 index 000000000..64549c4ad Binary files /dev/null and b/main/webapp/WEB-INF/lib/javassist-3.21.0-GA.jar differ diff --git a/main/webapp/WEB-INF/lib/jcommander-1.48.jar b/main/webapp/WEB-INF/lib/jcommander-1.48.jar new file mode 100644 index 000000000..ad0a12c95 Binary files /dev/null and b/main/webapp/WEB-INF/lib/jcommander-1.48.jar differ diff --git a/main/webapp/WEB-INF/lib/joda-time-2.9.9.jar b/main/webapp/WEB-INF/lib/joda-time-2.9.9.jar new file mode 100644 index 000000000..b3080c435 Binary files /dev/null and b/main/webapp/WEB-INF/lib/joda-time-2.9.9.jar differ diff --git a/main/webapp/WEB-INF/lib/json-20100208.jar b/main/webapp/WEB-INF/lib/json-20100208.jar deleted file mode 100644 index fa95275c6..000000000 Binary files a/main/webapp/WEB-INF/lib/json-20100208.jar and /dev/null differ diff --git a/main/webapp/WEB-INF/lib/json-20160810.jar b/main/webapp/WEB-INF/lib/json-20160810.jar new file mode 100644 index 000000000..a90e44852 Binary files /dev/null and b/main/webapp/WEB-INF/lib/json-20160810.jar differ diff --git a/main/webapp/WEB-INF/lib/junit-4.12.jar b/main/webapp/WEB-INF/lib/junit-4.12.jar new file mode 100644 index 000000000..3a7fc266c Binary files /dev/null and b/main/webapp/WEB-INF/lib/junit-4.12.jar differ diff --git a/main/webapp/WEB-INF/lib/mockito-core-2.8.9.jar b/main/webapp/WEB-INF/lib/mockito-core-2.8.9.jar new file mode 100644 index 000000000..a6a361223 Binary files /dev/null and b/main/webapp/WEB-INF/lib/mockito-core-2.8.9.jar differ diff --git a/main/webapp/WEB-INF/lib/objenesis-2.5.jar b/main/webapp/WEB-INF/lib/objenesis-2.5.jar new file mode 100644 index 000000000..7b60a8b43 Binary files /dev/null and b/main/webapp/WEB-INF/lib/objenesis-2.5.jar differ diff --git a/main/webapp/WEB-INF/lib/opencsv-4.0.jar b/main/webapp/WEB-INF/lib/opencsv-4.0.jar new file mode 100644 index 000000000..13ce91af2 Binary files /dev/null and b/main/webapp/WEB-INF/lib/opencsv-4.0.jar differ diff --git a/main/webapp/WEB-INF/lib/org.everit.json.schema-1.5.1.jar b/main/webapp/WEB-INF/lib/org.everit.json.schema-1.5.1.jar new file mode 100644 index 000000000..89d7f7f5f Binary files /dev/null and b/main/webapp/WEB-INF/lib/org.everit.json.schema-1.5.1.jar differ diff --git a/main/webapp/WEB-INF/lib/powermock-mockito2-1.7.1-full.jar b/main/webapp/WEB-INF/lib/powermock-mockito2-1.7.1-full.jar new file mode 100644 index 000000000..bfed6fada Binary files /dev/null and b/main/webapp/WEB-INF/lib/powermock-mockito2-1.7.1-full.jar differ diff --git a/main/webapp/WEB-INF/lib/tableschema-java-1.0-SNAPSHOT.jar b/main/webapp/WEB-INF/lib/tableschema-java-1.0-SNAPSHOT.jar new file mode 100644 index 000000000..4cc32a03f Binary files /dev/null and b/main/webapp/WEB-INF/lib/tableschema-java-1.0-SNAPSHOT.jar differ diff --git a/main/webapp/WEB-INF/lib/testng-6.9.10.jar b/main/webapp/WEB-INF/lib/testng-6.9.10.jar new file mode 100644 index 000000000..a9e0f76d4 Binary files /dev/null and b/main/webapp/WEB-INF/lib/testng-6.9.10.jar differ diff --git a/main/webapp/modules/core/MOD-INF/controller.js b/main/webapp/modules/core/MOD-INF/controller.js index 7ecdff3e4..23e5304eb 100644 --- a/main/webapp/modules/core/MOD-INF/controller.js +++ b/main/webapp/modules/core/MOD-INF/controller.js @@ -65,10 +65,12 @@ function registerCommands() { RS.registerCommand(module, "import-project", new Packages.com.google.refine.commands.project.ImportProjectCommand()); RS.registerCommand(module, "export-project", new Packages.com.google.refine.commands.project.ExportProjectCommand()); RS.registerCommand(module, "export-rows", new Packages.com.google.refine.commands.project.ExportRowsCommand()); + RS.registerCommand(module, "project-data-package", new Packages.com.google.refine.commands.project.PackageProjectCommand()); RS.registerCommand(module, "get-project-metadata", new Packages.com.google.refine.commands.project.GetProjectMetadataCommand()); RS.registerCommand(module, "get-all-project-metadata", new Packages.com.google.refine.commands.workspace.GetAllProjectMetadataCommand()); RS.registerCommand(module, "set-metaData", new Packages.com.google.refine.commands.project.SetProjectMetadataCommand()); + RS.registerCommand(module, "get-imetaData", new Packages.com.google.refine.commands.project.GetMetadataCommand()); RS.registerCommand(module, "get-all-project-tags", new Packages.com.google.refine.commands.workspace.GetAllProjectTagsCommand()); RS.registerCommand(module, "set-project-tags", new Packages.com.google.refine.commands.project.SetProjectTagsCommand()); @@ -276,6 +278,8 @@ function registerImporting() { IM.registerMimeType("application/rdf+xml", "text/xml/rdf"); IM.registerMimeType("application/marc", "text/marc"); + + IM.registerUrlRewriter(new Packages.com.google.refine.model.medadata.DataPackageUrlRewriter()); /* * Format guessers: these take a format derived from extensions or mime-types, @@ -323,6 +327,7 @@ function init() { "externals/jquery.i18n.js", "externals/tablesorter/jquery.tablesorter.min.js", "externals/moment-with-locales.min.js", + "externals/jsoneditor/jsoneditor.js", "externals/select2/select2.min.js", "externals/jquery.lavalamp.min.js", @@ -360,7 +365,8 @@ function init() { "scripts/index/parser-interfaces/wikitext-parser-ui.js", "scripts/reconciliation/recon-manager.js", // so that reconciliation functions are available to importers - "scripts/index/edit-metadata-dialog.js" + "scripts/index/edit-metadata-dialog.js", + "scripts/project/edit-general-metadata-dialog.js" ] ); @@ -376,6 +382,7 @@ function init() { "styles/pure.css", "styles/util/dialog.less", "styles/util/encoding.less", + "externals/jsoneditor/jsoneditor.css", "styles/index.less", "styles/index/create-project-ui.less", @@ -391,7 +398,7 @@ function init() { "styles/index/fixed-width-parser-ui.less", "styles/index/xml-parser-ui.less", "styles/index/json-parser-ui.less", - "styles/index/wikitext-parser-ui.less", + "styles/index/wikitext-parser-ui.less" ] ); @@ -408,6 +415,7 @@ function init() { "externals/date.js", "externals/jquery.i18n.js", "externals/underscore-min.js", + "externals/jsoneditor/jsoneditor.js", "scripts/project.js", @@ -460,6 +468,7 @@ function init() { "scripts/dialogs/column-reordering-dialog.js", "scripts/dialogs/custom-tabular-exporter-dialog.js", "scripts/dialogs/expression-column-dialog.js", + "scripts/project/edit-general-metadata-dialog.js", "scripts/dialogs/http-headers-dialog.js", ] ); @@ -471,6 +480,7 @@ function init() { "externals/suggest/css/suggest-4_3.min.css", "externals/jquery-ui/css/ui-lightness/jquery-ui-1.10.3.custom.css", "externals/imgareaselect/css/imgareaselect-default.css", + "externals/jsoneditor/jsoneditor.css", "styles/jquery-ui-overrides.less", "styles/common.less", diff --git a/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png new file mode 100644 index 000000000..c9ae20b46 Binary files /dev/null and b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.png differ diff --git a/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg new file mode 100644 index 000000000..9e48bdcb0 --- /dev/null +++ b/main/webapp/modules/core/externals/jsoneditor/img/jsoneditor-icons.svg @@ -0,0 +1,899 @@ + + + JSON Editor Icons + + + + image/svg+xml + + JSON Editor Icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css new file mode 100644 index 000000000..a490eb3db --- /dev/null +++ b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.css @@ -0,0 +1,1065 @@ +/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ + +div.jsoneditor .jsoneditor-search input { + height: auto; + border: inherit; +} + +div.jsoneditor .jsoneditor-search input:focus { + border: none !important; + box-shadow: none !important; +} + +div.jsoneditor table { + border-collapse: collapse; + width: auto; +} + +div.jsoneditor td, +div.jsoneditor th { + padding: 0; + display: table-cell; + text-align: left; + vertical-align: inherit; + border-radius: inherit; +} + + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor-readonly { + border: 1px solid transparent; + min-height: 16px; + min-width: 32px; + padding: 2px; + margin: 1px; + word-wrap: break-word; + float: left; +} + +/* adjust margin of p elements inside editable divs, needed for Opera, IE */ + +div.jsoneditor-field p, +div.jsoneditor-value p { + margin: 0; +} + +div.jsoneditor-value { + word-break: break-word; +} + +div.jsoneditor-readonly { + min-width: 16px; + color: gray; +} + +div.jsoneditor-empty { + border-color: lightgray; + border-style: dashed; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-empty::after, +div.jsoneditor-value.jsoneditor-empty::after { + pointer-events: none; + color: lightgray; + font-size: 8pt; +} + +div.jsoneditor-field.jsoneditor-empty::after { + content: "field"; +} + +div.jsoneditor-value.jsoneditor-empty::after { + content: "value"; +} + +div.jsoneditor-value.jsoneditor-url, +a.jsoneditor-value.jsoneditor-url { + color: green; + text-decoration: underline; +} + +a.jsoneditor-value.jsoneditor-url { + display: inline-block; + padding: 2px; + margin: 2px; +} + +a.jsoneditor-value.jsoneditor-url:hover, +a.jsoneditor-value.jsoneditor-url:focus { + color: #ee422e; +} + +div.jsoneditor td.jsoneditor-separator { + padding: 3px 0; + vertical-align: top; + color: gray; +} + +div.jsoneditor-field[contenteditable=true]:focus, +div.jsoneditor-field[contenteditable=true]:hover, +div.jsoneditor-value[contenteditable=true]:focus, +div.jsoneditor-value[contenteditable=true]:hover, +div.jsoneditor-field.jsoneditor-highlight, +div.jsoneditor-value.jsoneditor-highlight { + background-color: #FFFFAB; + border: 1px solid yellow; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-highlight-active, +div.jsoneditor-field.jsoneditor-highlight-active:focus, +div.jsoneditor-field.jsoneditor-highlight-active:hover, +div.jsoneditor-value.jsoneditor-highlight-active, +div.jsoneditor-value.jsoneditor-highlight-active:focus, +div.jsoneditor-value.jsoneditor-highlight-active:hover { + background-color: #ffee00; + border: 1px solid #ffc700; + border-radius: 2px; +} + +div.jsoneditor-value.jsoneditor-string { + color: #008000; +} + +div.jsoneditor-value.jsoneditor-object, +div.jsoneditor-value.jsoneditor-array { + min-width: 16px; + color: #808080; +} + +div.jsoneditor-value.jsoneditor-number { + color: #ee422e; +} + +div.jsoneditor-value.jsoneditor-boolean { + color: #ff8c00; +} + +div.jsoneditor-value.jsoneditor-null { + color: #004ED0; +} + +div.jsoneditor-value.jsoneditor-invalid { + color: #000000; +} + +div.jsoneditor-tree button { + width: 24px; + height: 24px; + padding: 0; + margin: 0; + border: none; + cursor: pointer; + background: transparent url("img/jsoneditor-icons.png"); +} + +div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, +div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { + cursor: pointer; +} + +div.jsoneditor-tree button.jsoneditor-collapsed { + background-position: 0 -48px; +} + +div.jsoneditor-tree button.jsoneditor-expanded { + background-position: 0 -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu { + background-position: -48px -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu:hover, +div.jsoneditor-tree button.jsoneditor-contextmenu:focus, +div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + background-position: -48px -48px; +} + +div.jsoneditor-tree *:focus { + outline: none; +} + +div.jsoneditor-tree button:focus { + /* TODO: nice outline for buttons with focus + outline: #97B0F8 solid 2px; + box-shadow: 0 0 8px #97B0F8; + */ + background-color: #f5f5f5; + outline: #e5e5e5 solid 1px; +} + +div.jsoneditor-tree button.jsoneditor-invisible { + visibility: hidden; + background: none; +} + +div.jsoneditor { + color: #1A1A1A; + border: 1px solid #3883fa; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 100%; + position: relative; + padding: 0; + line-height: 100%; +} + +div.jsoneditor-tree table.jsoneditor-tree { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin: 0; +} + +div.jsoneditor-outer { + position: static; + width: 100%; + height: 100%; + margin: -35px 0 0 0; + padding: 35px 0 0 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +div.jsoneditor-outer.has-nav-bar { + margin: -61px 0 0 0; + padding: 61px 0 0 0; +} + +div.jsoneditor-outer.has-status-bar { + margin: -35px 0 -26px 0; + padding: 35px 0 26px 0; +} + +textarea.jsoneditor-text, +.ace-jsoneditor { + min-height: 150px; +} + +div.jsoneditor-tree { + width: 100%; + height: 100%; + position: relative; + overflow: auto; +} + +textarea.jsoneditor-text { + width: 100%; + height: 100%; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + outline-width: 0; + border: none; + background-color: white; + resize: none; +} + +tr.jsoneditor-highlight, +tr.jsoneditor-selected { + background-color: #d3d3d3; +} + +tr.jsoneditor-selected button.jsoneditor-dragarea, +tr.jsoneditor-selected button.jsoneditor-contextmenu { + visibility: hidden; +} + +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + visibility: visible; +} + +div.jsoneditor-tree button.jsoneditor-dragarea { + background: url("img/jsoneditor-icons.png") -72px -72px; + cursor: move; +} + +div.jsoneditor-tree button.jsoneditor-dragarea:hover, +div.jsoneditor-tree button.jsoneditor-dragarea:focus, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { + background-position: -72px -48px; +} + +div.jsoneditor tr, +div.jsoneditor th, +div.jsoneditor td { + padding: 0; + margin: 0; +} + +div.jsoneditor td { + vertical-align: top; +} + +div.jsoneditor td.jsoneditor-tree { + vertical-align: top; +} + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor td, +div.jsoneditor th, +div.jsoneditor textarea, +.jsoneditor-schema-error { + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; + font-size: 10pt; + color: #1A1A1A; +} + +/* popover */ + +.jsoneditor-schema-error { + cursor: default; + display: inline-block; + /*font-family: arial, sans-serif;*/ + height: 24px; + line-height: 24px; + position: relative; + text-align: center; + width: 24px; +} + +div.jsoneditor-tree .jsoneditor-schema-error { + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.png") -168px -48px; +} + +.jsoneditor-schema-error .jsoneditor-popover { + background-color: #4c4c4c; + border-radius: 3px; + box-shadow: 0 0 5px rgba(0,0,0,0.4); + color: #fff; + display: none; + padding: 7px 10px; + position: absolute; + width: 200px; + z-index: 4; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { + bottom: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { + top: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { + top: -7px; + right: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { + top: -7px; + left: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover:before { + border-right: 7px solid transparent; + border-left: 7px solid transparent; + content: ''; + display: block; + left: 50%; + margin-left: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { + border-top: 7px solid #4c4c4c; + bottom: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { + border-bottom: 7px solid #4c4c4c; + top: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { + border-left: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + right: -14px; + left: inherit; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { + border-right: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + left: -14px; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error:hover .jsoneditor-popover, +.jsoneditor-schema-error:focus .jsoneditor-popover { + display: block; + -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; + -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; + -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; +} + +@-webkit-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-moz-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-ms-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +/*@-webkit-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-moz-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-ms-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/* JSON schema errors displayed at the bottom of the editor in mode text and code */ + +.jsoneditor .jsoneditor-text-errors { + width: 100%; + border-collapse: collapse; + background-color: #ffef8b; + border-top: 1px solid #ffd700; +} + +.jsoneditor .jsoneditor-text-errors td { + padding: 3px 6px; + vertical-align: middle; +} + +.jsoneditor-text-errors .jsoneditor-schema-error { + border: none; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.png") -168px -48px; +} +/* ContextMenu - main menu */ + +div.jsoneditor-contextmenu-root { + position: relative; + width: 0; + height: 0; +} + +div.jsoneditor-contextmenu { + position: absolute; + box-sizing: content-box; + z-index: 99999; +} + +div.jsoneditor-contextmenu ul, +div.jsoneditor-contextmenu li { + box-sizing: content-box; + position: relative; +} + +div.jsoneditor-contextmenu ul { + position: relative; + left: 0; + top: 0; + width: 128px; + background: white; + border: 1px solid #d3d3d3; + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + list-style: none; + margin: 0; + padding: 0; +} + +div.jsoneditor-contextmenu ul li button { + position: relative; + padding: 0 4px 0 0; + margin: 0; + width: 128px; + height: auto; + border: none; + cursor: pointer; + color: #4d4d4d; + background: transparent; + font-size: 10pt; + font-family: arial, sans-serif; + box-sizing: border-box; + text-align: left; +} + +/* Fix button padding in firefox */ + +div.jsoneditor-contextmenu ul li button::-moz-focus-inner { + padding: 0; + border: 0; +} + +div.jsoneditor-contextmenu ul li button:hover, +div.jsoneditor-contextmenu ul li button:focus { + color: #1a1a1a; + background-color: #f5f5f5; + outline: none; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-default { + width: 96px; + /* 128px - 32px */ +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-expand { + float: right; + width: 32px; + height: 24px; + border-left: 1px solid #e5e5e5; +} + +div.jsoneditor-contextmenu div.jsoneditor-icon { + position: absolute; + top: 0; + left: 0; + width: 24px; + height: 24px; + border: none; + padding: 0; + margin: 0; + background: url url("img/jsoneditor-icons.png"); +} + +div.jsoneditor-contextmenu ul li ul div.jsoneditor-icon { + margin-left: 24px; +} + +div.jsoneditor-contextmenu div.jsoneditor-text { + padding: 4px 0 4px 24px; + word-wrap: break-word; +} + +div.jsoneditor-contextmenu div.jsoneditor-text.jsoneditor-right-margin { + padding-right: 24px; +} + +div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { + position: absolute; + top: 0; + right: 0; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.png") 0 -72px; + opacity: 0.4; +} + +div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { + opacity: 1; +} + +div.jsoneditor-contextmenu div.jsoneditor-separator { + height: 0; + border-top: 1px solid #e5e5e5; + padding-top: 5px; + margin-top: 5px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { + background-position: -24px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { + background-position: -24px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { + background-position: -48px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { + background-position: -48px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { + background-position: -168px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { + background-position: -168px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { + background-position: -192px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { + background-position: -192px 0; +} + +/* ContextMenu - sub menu */ + +div.jsoneditor-contextmenu ul li button.jsoneditor-selected, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { + color: white; + background-color: #ee422e; +} + +div.jsoneditor-contextmenu ul li { + overflow: hidden; +} + +div.jsoneditor-contextmenu ul li ul { + display: none; + position: relative; + left: -10px; + top: 0; + border: none; + box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); + padding: 0 10px; + /* TODO: transition is not supported on IE8-9 */ + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + + + +div.jsoneditor-contextmenu ul li ul li button { + padding-left: 24px; + animation: all ease-in-out 1s; +} + +div.jsoneditor-contextmenu ul li ul li button:hover, +div.jsoneditor-contextmenu ul li ul li button:focus { + background-color: #f5f5f5; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { + background-position: -144px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon { + background-position: -144px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { + background-position: -120px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { + background-position: -120px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { + background-position: -72px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon { + background-position: -72px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { + background-position: -96px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon { + background-position: -96px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { + background: url none; + width: 6px; +} +div.jsoneditor-menu { + width: 100%; + height: 35px; + padding: 2px; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: white; + background-color: #3883fa; + border-bottom: 1px solid #3883fa; +} + +div.jsoneditor-menu > button, +div.jsoneditor-menu > div.jsoneditor-modes > button { + width: 26px; + height: 26px; + margin: 2px; + padding: 0; + border-radius: 2px; + border: 1px solid transparent; + background: transparent url("img/jsoneditor-icons.png"); + color: white; + opacity: 0.8; + font-family: arial, sans-serif; + font-size: 10pt; + float: left; +} + +div.jsoneditor-menu > button:hover, +div.jsoneditor-menu > div.jsoneditor-modes > button:hover { + background-color: rgba(255,255,255,0.2); + border: 1px solid rgba(255,255,255,0.4); +} + +div.jsoneditor-menu > button:focus, +div.jsoneditor-menu > button:active, +div.jsoneditor-menu > div.jsoneditor-modes > button:focus, +div.jsoneditor-menu > div.jsoneditor-modes > button:active { + background-color: rgba(255,255,255,0.3); +} + +div.jsoneditor-menu > button:disabled, +div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { + opacity: 0.5; +} + +div.jsoneditor-menu > button.jsoneditor-collapse-all { + background-position: 0 -96px; +} + +div.jsoneditor-menu > button.jsoneditor-expand-all { + background-position: 0 -120px; +} + +div.jsoneditor-menu > button.jsoneditor-undo { + background-position: -24px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-undo:disabled { + background-position: -24px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-redo { + background-position: -48px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-redo:disabled { + background-position: -48px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-compact { + background-position: -72px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-format { + background-position: -72px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-repair { + background-position: -96px -96px; +} + +div.jsoneditor-menu > div.jsoneditor-modes { + display: inline-block; + float: left; +} + +div.jsoneditor-menu > div.jsoneditor-modes > button { + background: url none; + width: auto; + padding-left: 6px; + padding-right: 6px; +} + +div.jsoneditor-menu > button.jsoneditor-separator, +div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { + margin-left: 10px; +} + +div.jsoneditor-menu a { + font-family: arial, sans-serif; + font-size: 10pt; + color: white; + opacity: 0.8; + vertical-align: middle; +} + +div.jsoneditor-menu a:hover { + opacity: 1; +} + +div.jsoneditor-menu a.jsoneditor-poweredBy { + font-size: 8pt; + position: absolute; + right: 0; + top: 0; + padding: 10px; +} +table.jsoneditor-search input, +table.jsoneditor-search div.jsoneditor-results { + font-family: arial, sans-serif; + font-size: 10pt; + color: #1A1A1A; + background: transparent; + /* For Firefox */ +} + +table.jsoneditor-search div.jsoneditor-results { + color: white; + padding-right: 5px; + line-height: 24px; +} + +table.jsoneditor-search { + position: absolute; + right: 4px; + top: 4px; + border-collapse: collapse; + border-spacing: 0; +} + +table.jsoneditor-search div.jsoneditor-frame { + border: 1px solid transparent; + background-color: white; + padding: 0 2px; + margin: 0; +} + +table.jsoneditor-search div.jsoneditor-frame table { + border-collapse: collapse; +} + +table.jsoneditor-search input { + width: 120px; + border: none; + outline: none; + margin: 1px; + line-height: 20px; +} + +table.jsoneditor-search button { + width: 16px; + height: 24px; + padding: 0; + margin: 0; + border: none; + background: url("img/jsoneditor-icons.png"); + vertical-align: top; +} + +table.jsoneditor-search button:hover { + background-color: transparent; +} + +table.jsoneditor-search button.jsoneditor-refresh { + width: 18px; + background-position: -99px -73px; +} + +table.jsoneditor-search button.jsoneditor-next { + cursor: pointer; + background-position: -124px -73px; +} + +table.jsoneditor-search button.jsoneditor-next:hover { + background-position: -124px -49px; +} + +table.jsoneditor-search button.jsoneditor-previous { + cursor: pointer; + background-position: -148px -73px; + margin-right: 2px; +} + +table.jsoneditor-search button.jsoneditor-previous:hover { + background-position: -148px -49px; +} +div.jsoneditor div.autocomplete.dropdown { + position: absolute; + background: white; + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + border: 1px solid #d3d3d3; + z-index: 100; + overflow-x: hidden; + overflow-y: auto; + cursor: default; + margin: 0; + padding-left: 2pt; + padding-right: 5pt; + text-align: left; + outline: 0; + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; + font-size: 10pt; +} + +div.jsoneditor div.autocomplete.dropdown .item { + color: #333; +} + +div.jsoneditor div.autocomplete.dropdown .item.hover { + background-color: #ddd; +} + +div.jsoneditor div.autocomplete.hint { + color: #aaa; + top: 4px; + left: 4px; +} +div.jsoneditor-treepath { + padding: 0 5px; + overflow: hidden; +} + +div.jsoneditor-treepath div.jsoneditor-contextmenu-root { + position: absolute; + left: 0; +} + +div.jsoneditor-treepath span.jsoneditor-treepath-element { + margin: 1px; + font-family: arial, sans-serif; + font-size: 10pt; +} + +div.jsoneditor-treepath span.jsoneditor-treepath-seperator { + margin: 2px; + font-size: 9pt; + font-family: arial, sans-serif; +} + +div.jsoneditor-treepath span.jsoneditor-treepath-element:hover, +div.jsoneditor-treepath span.jsoneditor-treepath-seperator:hover { + cursor: pointer; + text-decoration: underline; +} +div.jsoneditor-statusbar { + line-height: 26px; + height: 26px; + margin-top: -26px; + color: #808080; + background-color: #ebebeb; + border-top: 1px solid #d3d3d3; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-size: 10pt; +} + +div.jsoneditor-statusbar > .jsoneditor-curserinfo-label { + margin: 0 2px 0 4px; +} + +div.jsoneditor-statusbar > .jsoneditor-curserinfo-val { + margin-right: 12px; +} + +div.jsoneditor-statusbar > .jsoneditor-curserinfo-count { + margin-left: 4px; +} +div.jsoneditor-navigation-bar { + width: 100%; + height: 26px; + line-height: 26px; + padding: 0; + margin: 0; + border-bottom: 1px solid #d3d3d3; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: #808080; + background-color: #ebebeb; + font-size: 10pt; +} + +div.jsoneditor-navigation-bar.nav-bar-empty:after { + content: 'Select a node ...'; + color: rgba(104, 104, 91, 0.56); + position: absolute; + margin-left: 5px; +} \ No newline at end of file diff --git a/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js new file mode 100644 index 000000000..c48653054 --- /dev/null +++ b/main/webapp/modules/core/externals/jsoneditor/jsoneditor.js @@ -0,0 +1,38359 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2017 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version 5.11.0 + * @date 2017-11-22 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["JSONEditor"] = factory(); + else + root["JSONEditor"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var Ajv; + try { + Ajv = __webpack_require__(1); + } + catch (err) { + // no problem... when we need Ajv we will throw a neat exception + } + + var treemode = __webpack_require__(51); + var textmode = __webpack_require__(64); + var util = __webpack_require__(54); + + /** + * @constructor JSONEditor + * @param {Element} container Container element + * @param {Object} [options] Object with options. available options: + * {String} mode Editor mode. Available values: + * 'tree' (default), 'view', + * 'form', 'text', and 'code'. + * {function} onChange Callback method, triggered + * on change of contents + * {function} onError Callback method, triggered + * when an error occurs + * {Boolean} search Enable search box. + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Boolean} history Enable history (undo/redo). + * True by default + * Only applicable for modes + * 'tree', 'view', and 'form' + * {String} name Field name for the root node. + * Only applicable for modes + * 'tree', 'view', and 'form' + * {Number} indentation Number of indentation + * spaces. 4 by default. + * Only applicable for + * modes 'text' and 'code' + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * {boolean} sortObjectKeys If true, object keys are + * sorted before display. + * false by default. + * @param {Object | undefined} json JSON object + */ + function JSONEditor (container, options, json) { + if (!(this instanceof JSONEditor)) { + throw new Error('JSONEditor constructor called without "new".'); + } + + // check for unsupported browser (IE8 and older) + var ieVersion = util.getInternetExplorerVersion(); + if (ieVersion != -1 && ieVersion < 9) { + throw new Error('Unsupported browser, IE9 or newer required. ' + + 'Please install the newest version of your browser.'); + } + + if (options) { + // check for deprecated options + if (options.error) { + console.warn('Option "error" has been renamed to "onError"'); + options.onError = options.error; + delete options.error; + } + if (options.change) { + console.warn('Option "change" has been renamed to "onChange"'); + options.onChange = options.change; + delete options.change; + } + if (options.editable) { + console.warn('Option "editable" has been renamed to "onEditable"'); + options.onEditable = options.editable; + delete options.editable; + } + + // validate options + if (options) { + var VALID_OPTIONS = [ + 'ajv', 'schema', 'schemaRefs','templates', + 'ace', 'theme','autocomplete', + 'onChange', 'onEditable', 'onError', 'onModeChange', + 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', + 'sortObjectKeys', 'navigationBar', 'statusBar' + ]; + + Object.keys(options).forEach(function (option) { + if (VALID_OPTIONS.indexOf(option) === -1) { + console.warn('Unknown option "' + option + '". This option will be ignored'); + } + }); + } + } + + if (arguments.length) { + this._create(container, options, json); + } + } + + /** + * Configuration for all registered modes. Example: + * { + * tree: { + * mixin: TreeEditor, + * data: 'json' + * }, + * text: { + * mixin: TextEditor, + * data: 'text' + * } + * } + * + * @type { Object. } + */ + JSONEditor.modes = {}; + + // debounce interval for JSON schema vaidation in milliseconds + JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Create the JSONEditor + * @param {Element} container Container element + * @param {Object} [options] See description in constructor + * @param {Object | undefined} json JSON object + * @private + */ + JSONEditor.prototype._create = function (container, options, json) { + this.container = container; + this.options = options || {}; + this.json = json || {}; + + var mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree'; + this.setMode(mode); + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + JSONEditor.prototype.destroy = function () {}; + + /** + * Set JSON object in editor + * @param {Object | undefined} json JSON data + */ + JSONEditor.prototype.set = function (json) { + this.json = json; + }; + + /** + * Get JSON from the editor + * @returns {Object} json + */ + JSONEditor.prototype.get = function () { + return this.json; + }; + + /** + * Set string containing JSON for the editor + * @param {String | undefined} jsonText + */ + JSONEditor.prototype.setText = function (jsonText) { + this.json = util.parse(jsonText); + }; + + /** + * Get stringified JSON contents from the editor + * @returns {String} jsonText + */ + JSONEditor.prototype.getText = function () { + return JSON.stringify(this.json); + }; + + /** + * Set a field name for the root node. + * @param {String | undefined} name + */ + JSONEditor.prototype.setName = function (name) { + if (!this.options) { + this.options = {}; + } + this.options.name = name; + }; + + /** + * Get the field name for the root node. + * @return {String | undefined} name + */ + JSONEditor.prototype.getName = function () { + return this.options && this.options.name; + }; + + /** + * Change the mode of the editor. + * JSONEditor will be extended with all methods needed for the chosen mode. + * @param {String} mode Available modes: 'tree' (default), 'view', 'form', + * 'text', and 'code'. + */ + JSONEditor.prototype.setMode = function (mode) { + var container = this.container; + var options = util.extend({}, this.options); + var oldMode = options.mode; + var data; + var name; + + options.mode = mode; + var config = JSONEditor.modes[mode]; + if (config) { + try { + var asText = (config.data == 'text'); + name = this.getName(); + data = this[asText ? 'getText' : 'get'](); // get text or json + + this.destroy(); + util.clear(this); + util.extend(this, config.mixin); + this.create(container, options); + + this.setName(name); + this[asText ? 'setText' : 'set'](data); // set text or json + + if (typeof config.load === 'function') { + try { + config.load.call(this); + } + catch (err) { + console.error(err); + } + } + + if (typeof options.onModeChange === 'function' && mode !== oldMode) { + try { + options.onModeChange(mode, oldMode); + } + catch (err) { + console.error(err); + } + } + } + catch (err) { + this._onError(err); + } + } + else { + throw new Error('Unknown mode "' + options.mode + '"'); + } + }; + + /** + * Get the current mode + * @return {string} + */ + JSONEditor.prototype.getMode = function () { + return this.options.mode; + }; + + /** + * Throw an error. If an error callback is configured in options.error, this + * callback will be invoked. Else, a regular error is thrown. + * @param {Error} err + * @private + */ + JSONEditor.prototype._onError = function(err) { + if (this.options && typeof this.options.onError === 'function') { + this.options.onError(err); + } + else { + throw err; + } + }; + + /** + * Set a JSON schema for validation of the JSON object. + * To remove the schema, call JSONEditor.setSchema(null) + * @param {Object | null} schema + * @param {Object.=} schemaRefs Schemas that are referenced using the `$ref` property from the JSON schema that are set in the `schema` option, + + the object structure in the form of `{reference_key: schemaObject}` + */ + JSONEditor.prototype.setSchema = function (schema, schemaRefs) { + // compile a JSON schema validator if a JSON schema is provided + if (schema) { + var ajv; + try { + // grab ajv from options if provided, else create a new instance + ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); + + } + catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } + + if (ajv) { + if(schemaRefs) { + for (var ref in schemaRefs) { + ajv.removeSchema(ref); // When updating a schema - old refs has to be removed first + if(schemaRefs[ref]) { + ajv.addSchema(schemaRefs[ref], ref); + } + } + this.options.schemaRefs = schemaRefs; + } + this.validateSchema = ajv.compile(schema); + + // add schema to the options, so that when switching to an other mode, + // the set schema is not lost + this.options.schema = schema; + + // validate now + this.validate(); + } + + this.refresh(); // update DOM + } + else { + // remove current schema + this.validateSchema = null; + this.options.schema = null; + this.options.schemaRefs = null; + this.validate(); // to clear current error messages + this.refresh(); // update DOM + } + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + JSONEditor.prototype.validate = function () { + // must be implemented by treemode and textmode + }; + + /** + * Refresh the rendered contents + */ + JSONEditor.prototype.refresh = function () { + // can be implemented by treemode and textmode + }; + + /** + * Register a plugin with one ore multiple modes for the JSON Editor. + * + * A mode is described as an object with properties: + * + * - `mode: String` The name of the mode. + * - `mixin: Object` An object containing the mixin functions which + * will be added to the JSONEditor. Must contain functions + * create, get, getText, set, and setText. May have + * additional functions. + * When the JSONEditor switches to a mixin, all mixin + * functions are added to the JSONEditor, and then + * the function `create(container, options)` is executed. + * - `data: 'text' | 'json'` The type of data that will be used to load the mixin. + * - `[load: function]` An optional function called after the mixin + * has been loaded. + * + * @param {Object | Array} mode A mode object or an array with multiple mode objects. + */ + JSONEditor.registerMode = function (mode) { + var i, prop; + + if (util.isArray(mode)) { + // multiple modes + for (i = 0; i < mode.length; i++) { + JSONEditor.registerMode(mode[i]); + } + } + else { + // validate the new mode + if (!('mode' in mode)) throw new Error('Property "mode" missing'); + if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); + if (!('data' in mode)) throw new Error('Property "data" missing'); + var name = mode.mode; + if (name in JSONEditor.modes) { + throw new Error('Mode "' + name + '" already registered'); + } + + // validate the mixin + if (typeof mode.mixin.create !== 'function') { + throw new Error('Required function "create" missing on mixin'); + } + var reserved = ['setMode', 'registerMode', 'modes']; + for (i = 0; i < reserved.length; i++) { + prop = reserved[i]; + if (prop in mode.mixin) { + throw new Error('Reserved property "' + prop + '" not allowed in mixin'); + } + } + + JSONEditor.modes[name] = mode; + } + }; + + // register tree and text modes + JSONEditor.registerMode(treemode); + JSONEditor.registerMode(textmode); + + module.exports = JSONEditor; + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var compileSchema = __webpack_require__(2) + , resolve = __webpack_require__(3) + , Cache = __webpack_require__(19) + , SchemaObject = __webpack_require__(13) + , stableStringify = __webpack_require__(16) + , formats = __webpack_require__(20) + , rules = __webpack_require__(21) + , $dataMetaSchema = __webpack_require__(44) + , patternGroups = __webpack_require__(45) + , util = __webpack_require__(11) + , co = __webpack_require__(18); + + module.exports = Ajv; + + Ajv.prototype.validate = validate; + Ajv.prototype.compile = compile; + Ajv.prototype.addSchema = addSchema; + Ajv.prototype.addMetaSchema = addMetaSchema; + Ajv.prototype.validateSchema = validateSchema; + Ajv.prototype.getSchema = getSchema; + Ajv.prototype.removeSchema = removeSchema; + Ajv.prototype.addFormat = addFormat; + Ajv.prototype.errorsText = errorsText; + + Ajv.prototype._addSchema = _addSchema; + Ajv.prototype._compile = _compile; + + Ajv.prototype.compileAsync = __webpack_require__(46); + var customKeyword = __webpack_require__(47); + Ajv.prototype.addKeyword = customKeyword.add; + Ajv.prototype.getKeyword = customKeyword.get; + Ajv.prototype.removeKeyword = customKeyword.remove; + + var errorClasses = __webpack_require__(15); + Ajv.ValidationError = errorClasses.Validation; + Ajv.MissingRefError = errorClasses.MissingRef; + Ajv.$dataMetaSchema = $dataMetaSchema; + + var META_SCHEMA_ID = 'http://json-schema.org/draft-06/schema'; + + var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ]; + var META_SUPPORT_DATA = ['/properties']; + + /** + * Creates validator instance. + * Usage: `Ajv(opts)` + * @param {Object} opts optional options + * @return {Object} ajv instance + */ + function Ajv(opts) { + if (!(this instanceof Ajv)) return new Ajv(opts); + opts = this._opts = util.copy(opts) || {}; + setLogger(this); + this._schemas = {}; + this._refs = {}; + this._fragments = {}; + this._formats = formats(opts.format); + var schemaUriFormat = this._schemaUriFormat = this._formats['uri-reference']; + this._schemaUriFormatFunc = function (str) { return schemaUriFormat.test(str); }; + + this._cache = opts.cache || new Cache; + this._loadingSchemas = {}; + this._compilations = []; + this.RULES = rules(); + this._getId = chooseGetId(opts); + + opts.loopRequired = opts.loopRequired || Infinity; + if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true; + if (opts.serialize === undefined) opts.serialize = stableStringify; + this._metaOpts = getMetaSchemaOptions(this); + + if (opts.formats) addInitialFormats(this); + addDraft6MetaSchema(this); + if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); + addInitialSchemas(this); + if (opts.patternGroups) patternGroups(this); + } + + + + /** + * Validate data using schema + * Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize. + * @this Ajv + * @param {String|Object} schemaKeyRef key, ref or schema object + * @param {Any} data to be validated + * @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`). + */ + function validate(schemaKeyRef, data) { + var v; + if (typeof schemaKeyRef == 'string') { + v = this.getSchema(schemaKeyRef); + if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"'); + } else { + var schemaObj = this._addSchema(schemaKeyRef); + v = schemaObj.validate || this._compile(schemaObj); + } + + var valid = v(data); + if (v.$async === true) + return this._opts.async == '*' ? co(valid) : valid; + this.errors = v.errors; + return valid; + } + + + /** + * Create validating function for passed schema. + * @this Ajv + * @param {Object} schema schema object + * @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords. + * @return {Function} validating function + */ + function compile(schema, _meta) { + var schemaObj = this._addSchema(schema, undefined, _meta); + return schemaObj.validate || this._compile(schemaObj); + } + + + /** + * Adds schema to the instance. + * @this Ajv + * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored. + * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`. + * @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead. + * @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead. + */ + function addSchema(schema, key, _skipValidation, _meta) { + if (Array.isArray(schema)){ + for (var i=0; i} errors optional array of validation errors, if not passed errors from the instance are used. + * @param {Object} options optional options with properties `separator` and `dataVar`. + * @return {String} human readable string with all errors descriptions + */ + function errorsText(errors, options) { + errors = errors || this.errors; + if (!errors) return 'No errors'; + options = options || {}; + var separator = options.separator === undefined ? ', ' : options.separator; + var dataVar = options.dataVar === undefined ? 'data' : options.dataVar; + + var text = ''; + for (var i=0; i= 0) return { index: index, compiling: true }; + index = this._compilations.length; + this._compilations[index] = { + schema: schema, + root: root, + baseId: baseId + }; + return { index: index, compiling: false }; + } + + + /** + * Removes the schema from the currently compiled list + * @this Ajv + * @param {Object} schema schema to compile + * @param {Object} root root object + * @param {String} baseId base schema ID + */ + function endCompiling(schema, root, baseId) { + /* jshint validthis: true */ + var i = compIndex.call(this, schema, root, baseId); + if (i >= 0) this._compilations.splice(i, 1); + } + + + /** + * Index of schema compilation in the currently compiled list + * @this Ajv + * @param {Object} schema schema to compile + * @param {Object} root root object + * @param {String} baseId base schema ID + * @return {Integer} compilation index + */ + function compIndex(schema, root, baseId) { + /* jshint validthis: true */ + for (var i=0; i', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = __webpack_require__(7); + + function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; + } + + Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; + }; + + // format a parsed object into a url string + function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); + } + + Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; + }; + + function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); + } + + Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); + }; + + function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); + } + + Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + }; + + Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; + }; + + function isString(arg) { + return typeof arg === "string"; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + function isNull(arg) { + return arg === null; + } + function isNullOrUndefined(arg) { + return arg == null; + } + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6)(module), (function() { return this; }()))) + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + exports.decode = exports.parse = __webpack_require__(8); + exports.encode = exports.stringify = __webpack_require__(9); + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (Array.isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + }; + + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + 'use strict'; + + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + }; + + module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return Object.keys(obj).map(function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (Array.isArray(obj[k])) { + return obj[k].map(function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; + + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + 'use strict'; + + module.exports = function equal(a, b) { + if (a === b) return true; + + var arrA = Array.isArray(a) + , arrB = Array.isArray(b) + , i; + + if (arrA && arrB) { + if (a.length != b.length) return false; + for (i = 0; i < a.length; i++) + if (!equal(a[i], b[i])) return false; + return true; + } + + if (arrA != arrB) return false; + + if (a && b && typeof a === 'object' && typeof b === 'object') { + var keys = Object.keys(a); + if (keys.length !== Object.keys(b).length) return false; + + var dateA = a instanceof Date + , dateB = b instanceof Date; + if (dateA && dateB) return a.getTime() == b.getTime(); + if (dateA != dateB) return false; + + var regexpA = a instanceof RegExp + , regexpB = b instanceof RegExp; + if (regexpA && regexpB) return a.toString() == b.toString(); + if (regexpA != regexpB) return false; + + for (i = 0; i < keys.length; i++) + if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; + + for (i = 0; i < keys.length; i++) + if(!equal(a[keys[i]], b[keys[i]])) return false; + + return true; + } + + return false; + }; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + + module.exports = { + copy: copy, + checkDataType: checkDataType, + checkDataTypes: checkDataTypes, + coerceToTypes: coerceToTypes, + toHash: toHash, + getProperty: getProperty, + escapeQuotes: escapeQuotes, + equal: __webpack_require__(10), + ucs2length: __webpack_require__(12), + varOccurences: varOccurences, + varReplace: varReplace, + cleanUpCode: cleanUpCode, + finalCleanUpCode: finalCleanUpCode, + schemaHasRules: schemaHasRules, + schemaHasRulesExcept: schemaHasRulesExcept, + toQuotedString: toQuotedString, + getPathExpr: getPathExpr, + getPath: getPath, + getData: getData, + unescapeFragment: unescapeFragment, + unescapeJsonPointer: unescapeJsonPointer, + escapeFragment: escapeFragment, + escapeJsonPointer: escapeJsonPointer + }; + + + function copy(o, to) { + to = to || {}; + for (var key in o) to[key] = o[key]; + return to; + } + + + function checkDataType(dataType, data, negate) { + var EQUAL = negate ? ' !== ' : ' === ' + , AND = negate ? ' || ' : ' && ' + , OK = negate ? '!' : '' + , NOT = negate ? '' : '!'; + switch (dataType) { + case 'null': return data + EQUAL + 'null'; + case 'array': return OK + 'Array.isArray(' + data + ')'; + case 'object': return '(' + OK + data + AND + + 'typeof ' + data + EQUAL + '"object"' + AND + + NOT + 'Array.isArray(' + data + '))'; + case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + + NOT + '(' + data + ' % 1)' + + AND + data + EQUAL + data + ')'; + default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; + } + } + + + function checkDataTypes(dataTypes, data) { + switch (dataTypes.length) { + case 1: return checkDataType(dataTypes[0], data, true); + default: + var code = ''; + var types = toHash(dataTypes); + if (types.array && types.object) { + code = types.null ? '(': '(!' + data + ' || '; + code += 'typeof ' + data + ' !== "object")'; + delete types.null; + delete types.array; + delete types.object; + } + if (types.number) delete types.integer; + for (var t in types) + code += (code ? ' && ' : '' ) + checkDataType(t, data, true); + + return code; + } + } + + + var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); + function coerceToTypes(optionCoerceTypes, dataTypes) { + if (Array.isArray(dataTypes)) { + var types = []; + for (var i=0; i= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); + return paths[lvl - up]; + } + + if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); + data = 'data' + ((lvl - up) || ''); + if (!jsonPointer) return data; + } + + var expr = data; + var segments = jsonPointer.split('/'); + for (var i=0; i= 0xD800 && value <= 0xDBFF && pos < len) { + // high surrogate, and there is a next character + value = str.charCodeAt(pos); + if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate + } + } + return length; + }; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(11); + + module.exports = SchemaObject; + + function SchemaObject(obj) { + util.copy(obj, this); + } + + +/***/ }, +/* 14 */ +/***/ function(module, exports) { + + 'use strict'; + + var traverse = module.exports = function (schema, opts, cb) { + if (typeof opts == 'function') { + cb = opts; + opts = {}; + } + _traverse(opts, cb, schema, '', schema); + }; + + + traverse.keywords = { + additionalItems: true, + items: true, + contains: true, + additionalProperties: true, + propertyNames: true, + not: true + }; + + traverse.arrayKeywords = { + items: true, + allOf: true, + anyOf: true, + oneOf: true + }; + + traverse.propsKeywords = { + definitions: true, + properties: true, + patternProperties: true, + dependencies: true + }; + + traverse.skipKeywords = { + enum: true, + const: true, + required: true, + maximum: true, + minimum: true, + exclusiveMaximum: true, + exclusiveMinimum: true, + multipleOf: true, + maxLength: true, + minLength: true, + pattern: true, + format: true, + maxItems: true, + minItems: true, + uniqueItems: true, + maxProperties: true, + minProperties: true + }; + + + function _traverse(opts, cb, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) { + if (schema && typeof schema == 'object' && !Array.isArray(schema)) { + cb(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex); + for (var key in schema) { + var sch = schema[key]; + if (Array.isArray(sch)) { + if (key in traverse.arrayKeywords) { + for (var i=0; i 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + + /** + * Convert an array of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Array} obj + * @return {Promise} + * @api private + */ + + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + + /** + * Convert an object of "yieldables" to a promise. + * Uses `Promise.all()` internally. + * + * @param {Object} obj + * @return {Promise} + * @api private + */ + + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + + /** + * Check if `obj` is a promise. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + + function isPromise(obj) { + return 'function' == typeof obj.then; + } + + /** + * Check if `obj` is a generator. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + + /** + * Check if `obj` is a generator function. + * + * @param {Mixed} obj + * @return {Boolean} + * @api private + */ + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + if (!constructor) return false; + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + + /** + * Check for plain object. + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + + function isObject(val) { + return Object == val.constructor; + } + + +/***/ }, +/* 19 */ +/***/ function(module, exports) { + + 'use strict'; + + + var Cache = module.exports = function Cache() { + this._cache = {}; + }; + + + Cache.prototype.put = function Cache_put(key, value) { + this._cache[key] = value; + }; + + + Cache.prototype.get = function Cache_get(key) { + return this._cache[key]; + }; + + + Cache.prototype.del = function Cache_del(key) { + delete this._cache[key]; + }; + + + Cache.prototype.clear = function Cache_clear() { + this._cache = {}; + }; + + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(11); + + var DATE = /^\d\d\d\d-(\d\d)-(\d\d)$/; + var DAYS = [0,31,29,31,30,31,30,31,31,30,31,30,31]; + var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; + var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i; + var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; + var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; + // uri-template: https://tools.ietf.org/html/rfc6570 + var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i; + // For the source: https://gist.github.com/dperini/729294 + // For test cases: https://mathiasbynens.be/demo/url-regex + // @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983. + // var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu; + var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i; + var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i; + var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$|^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i; + var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/; + + + module.exports = formats; + + function formats(mode) { + mode = mode == 'full' ? 'full' : 'fast'; + return util.copy(formats[mode]); + } + + + formats.fast = { + // date: http://tools.ietf.org/html/rfc3339#section-5.6 + date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/, + // date-time: http://tools.ietf.org/html/rfc3339#section-5.6 + time: /^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i, + 'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i, + // uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js + uri: /^(?:[a-z][a-z0-9+-.]*)(?::|\/)\/?[^\s]*$/i, + 'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/\/)?[^\s]*$/i, + 'uri-template': URITEMPLATE, + url: URL, + // email (sources from jsen validator): + // http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363 + // http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation') + email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i, + hostname: HOSTNAME, + // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + // optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + // uuid: http://tools.ietf.org/html/rfc4122 + uuid: UUID, + // JSON-pointer: https://tools.ietf.org/html/rfc6901 + // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A + 'json-pointer': JSON_POINTER, + // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 + 'relative-json-pointer': RELATIVE_JSON_POINTER + }; + + + formats.full = { + date: date, + time: time, + 'date-time': date_time, + uri: uri, + 'uri-reference': URIREF, + 'uri-template': URITEMPLATE, + url: URL, + email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, + hostname: hostname, + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + uuid: UUID, + 'json-pointer': JSON_POINTER, + 'relative-json-pointer': RELATIVE_JSON_POINTER + }; + + + function date(str) { + // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 + var matches = str.match(DATE); + if (!matches) return false; + + var month = +matches[1]; + var day = +matches[2]; + return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month]; + } + + + function time(str, full) { + var matches = str.match(TIME); + if (!matches) return false; + + var hour = matches[1]; + var minute = matches[2]; + var second = matches[3]; + var timeZone = matches[5]; + return hour <= 23 && minute <= 59 && second <= 59 && (!full || timeZone); + } + + + var DATE_TIME_SEPARATOR = /t|\s/i; + function date_time(str) { + // http://tools.ietf.org/html/rfc3339#section-5.6 + var dateTime = str.split(DATE_TIME_SEPARATOR); + return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true); + } + + + function hostname(str) { + // https://tools.ietf.org/html/rfc1034#section-3.5 + // https://tools.ietf.org/html/rfc1123#section-2 + return str.length <= 255 && HOSTNAME.test(str); + } + + + var NOT_URI_FRAGMENT = /\/|:/; + function uri(str) { + // http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "." + return NOT_URI_FRAGMENT.test(str) && URI.test(str); + } + + + var Z_ANCHOR = /[^\\]\\Z/; + function regex(str) { + if (Z_ANCHOR.test(str)) return false; + try { + new RegExp(str); + return true; + } catch(e) { + return false; + } + } + + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ruleModules = __webpack_require__(22) + , toHash = __webpack_require__(11).toHash; + + module.exports = function rules() { + var RULES = [ + { type: 'number', + rules: [ { 'maximum': ['exclusiveMaximum'] }, + { 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] }, + { type: 'string', + rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] }, + { type: 'array', + rules: [ 'maxItems', 'minItems', 'uniqueItems', 'contains', 'items' ] }, + { type: 'object', + rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames', + { 'properties': ['additionalProperties', 'patternProperties'] } ] }, + { rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf' ] } + ]; + + var ALL = [ 'type' ]; + var KEYWORDS = [ + 'additionalItems', '$schema', '$id', 'id', 'title', + 'description', 'default', 'definitions' + ]; + var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ]; + RULES.all = toHash(ALL); + RULES.types = toHash(TYPES); + + RULES.forEach(function (group) { + group.rules = group.rules.map(function (keyword) { + var implKeywords; + if (typeof keyword == 'object') { + var key = Object.keys(keyword)[0]; + implKeywords = keyword[key]; + keyword = key; + implKeywords.forEach(function (k) { + ALL.push(k); + RULES.all[k] = true; + }); + } + ALL.push(keyword); + var rule = RULES.all[keyword] = { + keyword: keyword, + code: ruleModules[keyword], + implements: implKeywords + }; + return rule; + }); + + if (group.type) RULES.types[group.type] = group; + }); + + RULES.keywords = toHash(ALL.concat(KEYWORDS)); + RULES.custom = {}; + + return RULES; + }; + + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + //all requires must be explicit because browserify won't work with dynamic requires + module.exports = { + '$ref': __webpack_require__(23), + allOf: __webpack_require__(24), + anyOf: __webpack_require__(25), + const: __webpack_require__(26), + contains: __webpack_require__(27), + dependencies: __webpack_require__(28), + 'enum': __webpack_require__(29), + format: __webpack_require__(30), + items: __webpack_require__(31), + maximum: __webpack_require__(32), + minimum: __webpack_require__(32), + maxItems: __webpack_require__(33), + minItems: __webpack_require__(33), + maxLength: __webpack_require__(34), + minLength: __webpack_require__(34), + maxProperties: __webpack_require__(35), + minProperties: __webpack_require__(35), + multipleOf: __webpack_require__(36), + not: __webpack_require__(37), + oneOf: __webpack_require__(38), + pattern: __webpack_require__(39), + properties: __webpack_require__(40), + propertyNames: __webpack_require__(41), + required: __webpack_require__(42), + uniqueItems: __webpack_require__(43), + validate: __webpack_require__(17) + }; + + +/***/ }, +/* 23 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_ref(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $async, $refCode; + if ($schema == '#' || $schema == '#/') { + if (it.isRoot) { + $async = it.async; + $refCode = 'validate'; + } else { + $async = it.root.schema.$async === true; + $refCode = 'root.refVal[0]'; + } + } else { + var $refVal = it.resolveRef(it.baseId, $schema, it.isRoot); + if ($refVal === undefined) { + var $message = it.MissingRefError.message(it.baseId, $schema); + if (it.opts.missingRefs == 'fail') { + it.logger.error($message); + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'can\\\'t resolve reference ' + (it.util.escapeQuotes($schema)) + '\' '; + } + if (it.opts.verbose) { + out += ' , schema: ' + (it.util.toQuotedString($schema)) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + if ($breakOnError) { + out += ' if (false) { '; + } + } else if (it.opts.missingRefs == 'ignore') { + it.logger.warn($message); + if ($breakOnError) { + out += ' if (true) { '; + } + } else { + throw new it.MissingRefError(it.baseId, $schema, $message); + } + } else if ($refVal.inline) { + var $it = it.util.copy(it); + $it.level++; + var $nextValid = 'valid' + $it.level; + $it.schema = $refVal.schema; + $it.schemaPath = ''; + $it.errSchemaPath = $schema; + var $code = it.validate($it).replace(/validate\.schema/g, $refVal.code); + out += ' ' + ($code) + ' '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + } + } else { + $async = $refVal.$async === true; + $refCode = $refVal.code; + } + } + if ($refCode) { + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; + if (it.opts.passContext) { + out += ' ' + ($refCode) + '.call(this, '; + } else { + out += ' ' + ($refCode) + '( '; + } + out += ' ' + ($data) + ', (dataPath || \'\')'; + if (it.errorPath != '""') { + out += ' + ' + (it.errorPath); + } + var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', + $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; + out += ' , ' + ($parentData) + ' , ' + ($parentDataProperty) + ', rootData) '; + var __callValidate = out; + out = $$outStack.pop(); + if ($async) { + if (!it.async) throw new Error('async schema referenced by sync schema'); + if ($breakOnError) { + out += ' var ' + ($valid) + '; '; + } + out += ' try { ' + (it.yieldAwait) + ' ' + (__callValidate) + '; '; + if ($breakOnError) { + out += ' ' + ($valid) + ' = true; '; + } + out += ' } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; '; + if ($breakOnError) { + out += ' ' + ($valid) + ' = false; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($valid) + ') { '; + } + } else { + out += ' if (!' + (__callValidate) + ') { if (vErrors === null) vErrors = ' + ($refCode) + '.errors; else vErrors = vErrors.concat(' + ($refCode) + '.errors); errors = vErrors.length; } '; + if ($breakOnError) { + out += ' else { '; + } + } + } + return out; + } + + +/***/ }, +/* 24 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_allOf(it, $keyword, $ruleType) { + var out = ' '; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $currentBaseId = $it.baseId, + $allSchemasEmpty = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $allSchemasEmpty = false; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + if ($breakOnError) { + if ($allSchemasEmpty) { + out += ' if (true) { '; + } else { + out += ' ' + ($closingBraces.slice(0, -1)) + ' '; + } + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 25 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_anyOf(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $noEmptySchema = $schema.every(function($sch) { + return it.util.schemaHasRules($sch, it.RULES.all); + }); + if ($noEmptySchema) { + var $currentBaseId = $it.baseId; + out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = false; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + out += ' ' + ($valid) + ' = ' + ($valid) + ' || ' + ($nextValid) + '; if (!' + ($valid) + ') { '; + $closingBraces += '}'; + } + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' ' + ($closingBraces) + ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should match some schema in anyOf\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError(vErrors); '; + } else { + out += ' validate.errors = vErrors; return false; '; + } + } + out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + if (it.opts.allErrors) { + out += ' } '; + } + out = it.util.cleanUpCode(out); + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; + } + + +/***/ }, +/* 26 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_const(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + if (!$isData) { + out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + ';'; + } + out += 'var ' + ($valid) + ' = equal(' + ($data) + ', schema' + ($lvl) + '); if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('const') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should be equal to constant\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' }'; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 27 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_contains(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $idx = 'i' + $lvl, + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $currentBaseId = it.baseId, + $nonEmptySchema = it.util.schemaHasRules($schema, it.RULES.all); + out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; + if ($nonEmptySchema) { + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' var ' + ($nextValid) + ' = false; for (var ' + ($idx) + ' = 0; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); + var $passData = $data + '[' + $idx + ']'; + $it.dataPathArr[$dataNxt] = $idx; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' if (' + ($nextValid) + ') break; } '; + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' ' + ($closingBraces) + ' if (!' + ($nextValid) + ') {'; + } else { + out += ' if (' + ($data) + '.length == 0) {'; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('contains') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should contain a valid item\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + if ($nonEmptySchema) { + out += ' errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + } + if (it.opts.allErrors) { + out += ' } '; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 28 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_dependencies(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $schemaDeps = {}, + $propertyDeps = {}, + $ownProperties = it.opts.ownProperties; + for ($property in $schema) { + var $sch = $schema[$property]; + var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps; + $deps[$property] = $sch; + } + out += 'var ' + ($errs) + ' = errors;'; + var $currentErrorPath = it.errorPath; + out += 'var missing' + ($lvl) + ';'; + for (var $property in $propertyDeps) { + $deps = $propertyDeps[$property]; + if ($deps.length) { + out += ' if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; + } + if ($breakOnError) { + out += ' && ( '; + var arr1 = $deps; + if (arr1) { + var $propertyKey, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $propertyKey = arr1[$i += 1]; + if ($i) { + out += ' || '; + } + var $prop = it.util.getProperty($propertyKey), + $useData = $data + $prop; + out += ' ( ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; + } + } + out += ')) { '; + var $propertyPath = 'missing' + $lvl, + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should have '; + if ($deps.length == 1) { + out += 'property ' + (it.util.escapeQuotes($deps[0])); + } else { + out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); + } + out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + } else { + out += ' ) { '; + var arr2 = $deps; + if (arr2) { + var $propertyKey, i2 = -1, + l2 = arr2.length - 1; + while (i2 < l2) { + $propertyKey = arr2[i2 += 1]; + var $prop = it.util.getProperty($propertyKey), + $missingProperty = it.util.escapeQuotes($propertyKey), + $useData = $data + $prop; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should have '; + if ($deps.length == 1) { + out += 'property ' + (it.util.escapeQuotes($deps[0])); + } else { + out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); + } + out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; + } + } + } + out += ' } '; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + } + } + it.errorPath = $currentErrorPath; + var $currentBaseId = $it.baseId; + for (var $property in $schemaDeps) { + var $sch = $schemaDeps[$property]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + out += ' ' + ($nextValid) + ' = true; if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; + } + out += ') { '; + $it.schema = $sch; + $it.schemaPath = $schemaPath + it.util.getProperty($property); + $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property); + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 29 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_enum(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $i = 'i' + $lvl, + $vSchema = 'schema' + $lvl; + if (!$isData) { + out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + ';'; + } + out += 'var ' + ($valid) + ';'; + if ($isData) { + out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; + } + out += '' + ($valid) + ' = false;for (var ' + ($i) + '=0; ' + ($i) + '<' + ($vSchema) + '.length; ' + ($i) + '++) if (equal(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + '])) { ' + ($valid) + ' = true; break; }'; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('enum') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValues: schema' + ($lvl) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be equal to one of the allowed values\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' }'; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 30 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_format(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + if (it.opts.format === false) { + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $unknownFormats = it.opts.unknownFormats, + $allowUnknown = Array.isArray($unknownFormats); + if ($isData) { + var $format = 'format' + $lvl, + $isObject = 'isObject' + $lvl, + $formatType = 'formatType' + $lvl; + out += ' var ' + ($format) + ' = formats[' + ($schemaValue) + ']; var ' + ($isObject) + ' = typeof ' + ($format) + ' == \'object\' && !(' + ($format) + ' instanceof RegExp) && ' + ($format) + '.validate; var ' + ($formatType) + ' = ' + ($isObject) + ' && ' + ($format) + '.type || \'string\'; if (' + ($isObject) + ') { '; + if (it.async) { + out += ' var async' + ($lvl) + ' = ' + ($format) + '.async; '; + } + out += ' ' + ($format) + ' = ' + ($format) + '.validate; } if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; + } + out += ' ('; + if ($unknownFormats != 'ignore') { + out += ' (' + ($schemaValue) + ' && !' + ($format) + ' '; + if ($allowUnknown) { + out += ' && self._opts.unknownFormats.indexOf(' + ($schemaValue) + ') == -1 '; + } + out += ') || '; + } + out += ' (' + ($format) + ' && ' + ($formatType) + ' == \'' + ($ruleType) + '\' && !(typeof ' + ($format) + ' == \'function\' ? '; + if (it.async) { + out += ' (async' + ($lvl) + ' ? ' + (it.yieldAwait) + ' ' + ($format) + '(' + ($data) + ') : ' + ($format) + '(' + ($data) + ')) '; + } else { + out += ' ' + ($format) + '(' + ($data) + ') '; + } + out += ' : ' + ($format) + '.test(' + ($data) + '))))) {'; + } else { + var $format = it.formats[$schema]; + if (!$format) { + if ($unknownFormats == 'ignore') { + it.logger.warn('unknown format "' + $schema + '" ignored in schema at path "' + it.errSchemaPath + '"'); + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } else if ($allowUnknown && $unknownFormats.indexOf($schema) >= 0) { + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } else { + throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); + } + } + var $isObject = typeof $format == 'object' && !($format instanceof RegExp) && $format.validate; + var $formatType = $isObject && $format.type || 'string'; + if ($isObject) { + var $async = $format.async === true; + $format = $format.validate; + } + if ($formatType != $ruleType) { + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } + if ($async) { + if (!it.async) throw new Error('async format in sync schema'); + var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate'; + out += ' if (!(' + (it.yieldAwait) + ' ' + ($formatRef) + '(' + ($data) + '))) { '; + } else { + out += ' if (! '; + var $formatRef = 'formats' + it.util.getProperty($schema); + if ($isObject) $formatRef += '.validate'; + if (typeof $format == 'function') { + out += ' ' + ($formatRef) + '(' + ($data) + ') '; + } else { + out += ' ' + ($formatRef) + '.test(' + ($data) + ') '; + } + out += ') { '; + } + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match format "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 31 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_items(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $idx = 'i' + $lvl, + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $currentBaseId = it.baseId; + out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; + if (Array.isArray($schema)) { + var $additionalItems = it.schema.additionalItems; + if ($additionalItems === false) { + out += ' ' + ($valid) + ' = ' + ($data) + '.length <= ' + ($schema.length) + '; '; + var $currErrSchemaPath = $errSchemaPath; + $errSchemaPath = it.errSchemaPath + '/additionalItems'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have more than ' + ($schema.length) + ' items\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + } + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($i) + ') { '; + var $passData = $data + '[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + $it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true); + $it.dataPathArr[$dataNxt] = $i; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + if (typeof $additionalItems == 'object' && it.util.schemaHasRules($additionalItems, it.RULES.all)) { + $it.schema = $additionalItems; + $it.schemaPath = it.schemaPath + '.additionalItems'; + $it.errSchemaPath = it.errSchemaPath + '/additionalItems'; + out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($schema.length) + ') { for (var ' + ($idx) + ' = ' + ($schema.length) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); + var $passData = $data + '[' + $idx + ']'; + $it.dataPathArr[$dataNxt] = $idx; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' } } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } else if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' for (var ' + ($idx) + ' = ' + (0) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); + var $passData = $data + '[' + $idx + ']'; + $it.dataPathArr[$dataNxt] = $idx; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' }'; + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 32 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limit(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $isMax = $keyword == 'maximum', + $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum', + $schemaExcl = it.schema[$exclusiveKeyword], + $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data, + $op = $isMax ? '<' : '>', + $notOp = $isMax ? '>' : '<', + $errorKeyword = undefined; + if ($isDataExcl) { + var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), + $exclusive = 'exclusive' + $lvl, + $exclType = 'exclType' + $lvl, + $exclIsNumber = 'exclIsNumber' + $lvl, + $opExpr = 'op' + $lvl, + $opStr = '\' + ' + $opExpr + ' + \''; + out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; + $schemaValueExcl = 'schemaExcl' + $lvl; + out += ' var ' + ($exclusive) + '; var ' + ($exclType) + ' = typeof ' + ($schemaValueExcl) + '; if (' + ($exclType) + ' != \'boolean\' && ' + ($exclType) + ' != \'undefined\' && ' + ($exclType) + ' != \'number\') { '; + var $errorKeyword = $exclusiveKeyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($exclType) + ' == \'number\' ? ( (' + ($exclusive) + ' = ' + ($schemaValue) + ' === undefined || ' + ($schemaValueExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ') ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValueExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) : ( (' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';'; + } else { + var $exclIsNumber = typeof $schemaExcl == 'number', + $opStr = $op; + if ($exclIsNumber && $isData) { + var $opExpr = '\'' + $opStr + '\''; + out += ' if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ( ' + ($schemaValue) + ' === undefined || ' + ($schemaExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ' ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { '; + } else { + if ($exclIsNumber && $schema === undefined) { + $exclusive = true; + $errorKeyword = $exclusiveKeyword; + $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; + $schemaValue = $schemaExcl; + $notOp += '='; + } else { + if ($exclIsNumber) $schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema); + if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) { + $exclusive = true; + $errorKeyword = $exclusiveKeyword; + $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; + $notOp += '='; + } else { + $exclusive = false; + $opStr += '='; + } + } + var $opExpr = '\'' + $opStr + '\''; + out += ' if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' || ' + ($data) + ' !== ' + ($data) + ') { '; + } + } + $errorKeyword = $errorKeyword || $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be ' + ($opStr) + ' '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schemaValue) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 33 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitItems(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxItems' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxItems') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' items\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 34 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitLength(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxLength' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + if (it.opts.unicode === false) { + out += ' ' + ($data) + '.length '; + } else { + out += ' ucs2length(' + ($data) + ') '; + } + out += ' ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitLength') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be '; + if ($keyword == 'maxLength') { + out += 'longer'; + } else { + out += 'shorter'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' characters\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 35 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate__limitProperties(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxProperties' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' Object.keys(' + ($data) + ').length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxProperties') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' properties\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 36 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_multipleOf(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + out += 'var division' + ($lvl) + ';if ('; + if ($isData) { + out += ' ' + ($schemaValue) + ' !== undefined && ( typeof ' + ($schemaValue) + ' != \'number\' || '; + } + out += ' (division' + ($lvl) + ' = ' + ($data) + ' / ' + ($schemaValue) + ', '; + if (it.opts.multipleOfPrecision) { + out += ' Math.abs(Math.round(division' + ($lvl) + ') - division' + ($lvl) + ') > 1e-' + (it.opts.multipleOfPrecision) + ' '; + } else { + out += ' division' + ($lvl) + ' !== parseInt(division' + ($lvl) + ') '; + } + out += ' ) '; + if ($isData) { + out += ' ) '; + } + out += ' ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be multiple of '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schemaValue) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 37 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_not(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + $it.level++; + var $nextValid = 'valid' + $it.level; + if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.createErrors = false; + var $allErrorsOption; + if ($it.opts.allErrors) { + $allErrorsOption = $it.opts.allErrors; + $it.opts.allErrors = false; + } + out += ' ' + (it.validate($it)) + ' '; + $it.createErrors = true; + if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption; + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' if (' + ($nextValid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + if (it.opts.allErrors) { + out += ' } '; + } + } else { + out += ' var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if ($breakOnError) { + out += ' if (false) { '; + } + } + return out; + } + + +/***/ }, +/* 38 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_oneOf(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + out += 'var ' + ($errs) + ' = errors;var prevValid' + ($lvl) + ' = false;var ' + ($valid) + ' = false;'; + var $currentBaseId = $it.baseId; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + } else { + out += ' var ' + ($nextValid) + ' = true; '; + } + if ($i) { + out += ' if (' + ($nextValid) + ' && prevValid' + ($lvl) + ') ' + ($valid) + ' = false; else { '; + $closingBraces += '}'; + } + out += ' if (' + ($nextValid) + ') ' + ($valid) + ' = prevValid' + ($lvl) + ' = true;'; + } + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should match exactly one schema in oneOf\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError(vErrors); '; + } else { + out += ' validate.errors = vErrors; return false; '; + } + } + out += '} else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; }'; + if (it.opts.allErrors) { + out += ' } '; + } + return out; + } + + +/***/ }, +/* 39 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_pattern(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema); + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; + } + out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match pattern "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; + } + + +/***/ }, +/* 40 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_properties(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $key = 'key' + $lvl, + $idx = 'idx' + $lvl, + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $dataProperties = 'dataProperties' + $lvl; + var $schemaKeys = Object.keys($schema || {}), + $pProperties = it.schema.patternProperties || {}, + $pPropertyKeys = Object.keys($pProperties), + $aProperties = it.schema.additionalProperties, + $someProperties = $schemaKeys.length || $pPropertyKeys.length, + $noAdditional = $aProperties === false, + $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length, + $removeAdditional = it.opts.removeAdditional, + $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional, + $ownProperties = it.opts.ownProperties, + $currentBaseId = it.baseId; + var $required = it.schema.required; + if ($required && !(it.opts.v5 && $required.$data) && $required.length < it.opts.loopRequired) var $requiredHash = it.util.toHash($required); + if (it.opts.patternGroups) { + var $pgProperties = it.schema.patternGroups || {}, + $pgPropertyKeys = Object.keys($pgProperties); + } + out += 'var ' + ($errs) + ' = errors;var ' + ($nextValid) + ' = true;'; + if ($ownProperties) { + out += ' var ' + ($dataProperties) + ' = undefined;'; + } + if ($checkAdditional) { + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + if ($someProperties) { + out += ' var isAdditional' + ($lvl) + ' = !(false '; + if ($schemaKeys.length) { + if ($schemaKeys.length > 5) { + out += ' || validate.schema' + ($schemaPath) + '[' + ($key) + '] '; + } else { + var arr1 = $schemaKeys; + if (arr1) { + var $propertyKey, i1 = -1, + l1 = arr1.length - 1; + while (i1 < l1) { + $propertyKey = arr1[i1 += 1]; + out += ' || ' + ($key) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' '; + } + } + } + } + if ($pPropertyKeys.length) { + var arr2 = $pPropertyKeys; + if (arr2) { + var $pProperty, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + $pProperty = arr2[$i += 1]; + out += ' || ' + (it.usePattern($pProperty)) + '.test(' + ($key) + ') '; + } + } + } + if (it.opts.patternGroups && $pgPropertyKeys.length) { + var arr3 = $pgPropertyKeys; + if (arr3) { + var $pgProperty, $i = -1, + l3 = arr3.length - 1; + while ($i < l3) { + $pgProperty = arr3[$i += 1]; + out += ' || ' + (it.usePattern($pgProperty)) + '.test(' + ($key) + ') '; + } + } + } + out += ' ); if (isAdditional' + ($lvl) + ') { '; + } + if ($removeAdditional == 'all') { + out += ' delete ' + ($data) + '[' + ($key) + ']; '; + } else { + var $currentErrorPath = it.errorPath; + var $additionalProperty = '\' + ' + $key + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + } + if ($noAdditional) { + if ($removeAdditional) { + out += ' delete ' + ($data) + '[' + ($key) + ']; '; + } else { + out += ' ' + ($nextValid) + ' = false; '; + var $currErrSchemaPath = $errSchemaPath; + $errSchemaPath = it.errSchemaPath + '/additionalProperties'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have additional properties\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + out += ' break; '; + } + } + } else if ($additionalIsSchema) { + if ($removeAdditional == 'failing') { + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' if (!' + ($nextValid) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[' + ($key) + ']; } '; + it.compositeRule = $it.compositeRule = $wasComposite; + } else { + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + } + } + it.errorPath = $currentErrorPath; + } + if ($someProperties) { + out += ' } '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + var $useDefaults = it.opts.useDefaults && !it.compositeRule; + if ($schemaKeys.length) { + var arr4 = $schemaKeys; + if (arr4) { + var $propertyKey, i4 = -1, + l4 = arr4.length - 1; + while (i4 < l4) { + $propertyKey = arr4[i4 += 1]; + var $sch = $schema[$propertyKey]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + var $prop = it.util.getProperty($propertyKey), + $passData = $data + $prop, + $hasDefault = $useDefaults && $sch.default !== undefined; + $it.schema = $sch; + $it.schemaPath = $schemaPath + $prop; + $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey); + $it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers); + $it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey); + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + $code = it.util.varReplace($code, $nextData, $passData); + var $useData = $passData; + } else { + var $useData = $nextData; + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; '; + } + if ($hasDefault) { + out += ' ' + ($code) + ' '; + } else { + if ($requiredHash && $requiredHash[$propertyKey]) { + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { ' + ($nextValid) + ' = false; '; + var $currentErrorPath = it.errorPath, + $currErrSchemaPath = $errSchemaPath, + $missingProperty = it.util.escapeQuotes($propertyKey); + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + $errSchemaPath = it.errSchemaPath + '/required'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + it.errorPath = $currentErrorPath; + out += ' } else { '; + } else { + if ($breakOnError) { + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { ' + ($nextValid) + ' = true; } else { '; + } else { + out += ' if (' + ($useData) + ' !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ' ) { '; + } + } + out += ' ' + ($code) + ' } '; + } + } + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + if ($pPropertyKeys.length) { + var arr5 = $pPropertyKeys; + if (arr5) { + var $pProperty, i5 = -1, + l5 = arr5.length - 1; + while (i5 < l5) { + $pProperty = arr5[i5 += 1]; + var $sch = $pProperties[$pProperty]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty); + $it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty); + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + out += ' if (' + (it.usePattern($pProperty)) + '.test(' + ($key) + ')) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else ' + ($nextValid) + ' = true; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + } + if (it.opts.patternGroups && $pgPropertyKeys.length) { + var arr6 = $pgPropertyKeys; + if (arr6) { + var $pgProperty, i6 = -1, + l6 = arr6.length - 1; + while (i6 < l6) { + $pgProperty = arr6[i6 += 1]; + var $pgSchema = $pgProperties[$pgProperty], + $sch = $pgSchema.schema; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = it.schemaPath + '.patternGroups' + it.util.getProperty($pgProperty) + '.schema'; + $it.errSchemaPath = it.errSchemaPath + '/patternGroups/' + it.util.escapeFragment($pgProperty) + '/schema'; + out += ' var pgPropCount' + ($lvl) + ' = 0; '; + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + out += ' if (' + (it.usePattern($pgProperty)) + '.test(' + ($key) + ')) { pgPropCount' + ($lvl) + '++; '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else ' + ($nextValid) + ' = true; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + var $pgMin = $pgSchema.minimum, + $pgMax = $pgSchema.maximum; + if ($pgMin !== undefined || $pgMax !== undefined) { + out += ' var ' + ($valid) + ' = true; '; + var $currErrSchemaPath = $errSchemaPath; + if ($pgMin !== undefined) { + var $limit = $pgMin, + $reason = 'minimum', + $moreOrLess = 'less'; + out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' >= ' + ($pgMin) + '; '; + $errSchemaPath = it.errSchemaPath + '/patternGroups/minimum'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($pgMax !== undefined) { + out += ' else '; + } + } + if ($pgMax !== undefined) { + var $limit = $pgMax, + $reason = 'maximum', + $moreOrLess = 'more'; + out += ' ' + ($valid) + ' = pgPropCount' + ($lvl) + ' <= ' + ($pgMax) + '; '; + $errSchemaPath = it.errSchemaPath + '/patternGroups/maximum'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + } + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + out += ' if (' + ($valid) + ') { '; + $closingBraces += '}'; + } + } + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; + } + + +/***/ }, +/* 41 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_propertyNames(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + var $key = 'key' + $lvl, + $idx = 'idx' + $lvl, + $i = 'i' + $lvl, + $invalidName = '\' + ' + $key + ' + \'', + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $dataProperties = 'dataProperties' + $lvl, + $ownProperties = it.opts.ownProperties, + $currentBaseId = it.baseId; + out += ' var ' + ($errs) + ' = errors; '; + if ($ownProperties) { + out += ' var ' + ($dataProperties) + ' = undefined; '; + } + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + out += ' var startErrs' + ($lvl) + ' = errors; '; + var $passData = $key; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' if (!' + ($nextValid) + ') { for (var ' + ($i) + '=startErrs' + ($lvl) + '; ' + ($i) + '= it.opts.loopRequired, + $ownProperties = it.opts.ownProperties; + if ($breakOnError) { + out += ' var missing' + ($lvl) + '; '; + if ($loopRequired) { + if (!$isData) { + out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + out += ' var ' + ($valid) + ' = true; '; + if ($isData) { + out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { ' + ($valid) + ' = ' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; + } + out += '; if (!' + ($valid) + ') break; } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } else { + out += ' if ( '; + var arr2 = $required; + if (arr2) { + var $propertyKey, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + $propertyKey = arr2[$i += 1]; + if ($i) { + out += ' || '; + } + var $prop = it.util.getProperty($propertyKey), + $useData = $data + $prop; + out += ' ( ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; + } + } + out += ') { '; + var $propertyPath = 'missing' + $lvl, + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } + } else { + if ($loopRequired) { + if (!$isData) { + out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + if ($isData) { + out += ' if (' + ($vSchema) + ' && !Array.isArray(' + ($vSchema) + ')) { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (' + ($vSchema) + ' !== undefined) { '; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { if (' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; + } + out += ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } '; + if ($isData) { + out += ' } '; + } + } else { + var arr3 = $required; + if (arr3) { + var $propertyKey, i3 = -1, + l3 = arr3.length - 1; + while (i3 < l3) { + $propertyKey = arr3[i3 += 1]; + var $prop = it.util.getProperty($propertyKey), + $missingProperty = it.util.escapeQuotes($propertyKey), + $useData = $data + $prop; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; + } + } + } + } + it.errorPath = $currentErrorPath; + } else if ($breakOnError) { + out += ' if (true) {'; + } + return out; + } + + +/***/ }, +/* 43 */ +/***/ function(module, exports) { + + 'use strict'; + module.exports = function generate_uniqueItems(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + if (($schema || $isData) && it.opts.uniqueItems !== false) { + if ($isData) { + out += ' var ' + ($valid) + '; if (' + ($schemaValue) + ' === false || ' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'boolean\') ' + ($valid) + ' = false; else { '; + } + out += ' var ' + ($valid) + ' = true; if (' + ($data) + '.length > 1) { var i = ' + ($data) + '.length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal(' + ($data) + '[i], ' + ($data) + '[j])) { ' + ($valid) + ' = false; break outer; } } } } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; + } + + +/***/ }, +/* 44 */ +/***/ function(module, exports) { + + 'use strict'; + + var KEYWORDS = [ + 'multipleOf', + 'maximum', + 'exclusiveMaximum', + 'minimum', + 'exclusiveMinimum', + 'maxLength', + 'minLength', + 'pattern', + 'additionalItems', + 'maxItems', + 'minItems', + 'uniqueItems', + 'maxProperties', + 'minProperties', + 'required', + 'additionalProperties', + 'enum', + 'format', + 'const' + ]; + + module.exports = function (metaSchema, keywordsJsonPointers) { + for (var i=0; i 0) { + this.autoScrollStep = ((top + margin) - mouseY) / 3; + } + else if (mouseY > bottom - margin && + height + content.scrollTop < content.scrollHeight) { + this.autoScrollStep = ((bottom - margin) - mouseY) / 3; + } + else { + this.autoScrollStep = undefined; + } + + if (this.autoScrollStep) { + if (!this.autoScrollTimer) { + this.autoScrollTimer = setInterval(function () { + if (me.autoScrollStep) { + content.scrollTop -= me.autoScrollStep; + } + else { + me.stopAutoScroll(); + } + }, interval); + } + } + else { + this.stopAutoScroll(); + } + }; + + /** + * Stop auto scrolling. Only applicable when scrolling + */ + treemode.stopAutoScroll = function () { + if (this.autoScrollTimer) { + clearTimeout(this.autoScrollTimer); + delete this.autoScrollTimer; + } + if (this.autoScrollStep) { + delete this.autoScrollStep; + } + }; + + + /** + * Set the focus to an element in the editor, set text selection, and + * set scroll position. + * @param {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.setSelection = function (selection) { + if (!selection) { + return; + } + + if ('scrollTop' in selection && this.content) { + // TODO: animated scroll + this.content.scrollTop = selection.scrollTop; + } + if (selection.nodes) { + // multi-select + this.select(selection.nodes); + } + if (selection.range) { + util.setSelectionOffset(selection.range); + } + if (selection.dom) { + selection.dom.focus(); + } + }; + + /** + * Get the current focus + * @return {Object} selection An object containing fields: + * {Element | undefined} dom The dom element + * which has focus + * {Range | TextRange} range A text selection + * {Node[]} nodes Nodes in case of multi selection + * {Number} scrollTop Scroll position + */ + treemode.getSelection = function () { + var range = util.getSelectionOffset(); + if (range && range.container.nodeName !== 'DIV') { // filter on (editable) divs) + range = null; + } + + return { + dom: this.focusTarget, + range: range, + nodes: this.multiselection.nodes.slice(0), + scrollTop: this.content ? this.content.scrollTop : 0 + }; + }; + + /** + * Adjust the scroll position such that given top position is shown at 1/4 + * of the window height. + * @param {Number} top + * @param {function(boolean)} [callback] Callback, executed when animation is + * finished. The callback returns true + * when animation is finished, or false + * when not. + */ + treemode.scrollTo = function (top, callback) { + var content = this.content; + if (content) { + var editor = this; + // cancel any running animation + if (editor.animateTimeout) { + clearTimeout(editor.animateTimeout); + delete editor.animateTimeout; + } + if (editor.animateCallback) { + editor.animateCallback(false); + delete editor.animateCallback; + } + + // calculate final scroll position + var height = content.clientHeight; + var bottom = content.scrollHeight - height; + var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); + + // animate towards the new scroll position + var animate = function () { + var scrollTop = content.scrollTop; + var diff = (finalScrollTop - scrollTop); + if (Math.abs(diff) > 3) { + content.scrollTop += diff / 3; + editor.animateCallback = callback; + editor.animateTimeout = setTimeout(animate, 50); + } + else { + // finished + if (callback) { + callback(true); + } + content.scrollTop = finalScrollTop; + delete editor.animateTimeout; + delete editor.animateCallback; + } + }; + animate(); + } + else { + if (callback) { + callback(false); + } + } + }; + + /** + * Create main frame + * @private + */ + treemode._createFrame = function () { + // create the frame + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.container.appendChild(this.frame); + + // create one global event listener to handle all events from all nodes + var editor = this; + function onEvent(event) { + // when switching to mode "code" or "text" via the menu, some events + // are still fired whilst the _onEvent methods is already removed. + if (editor._onEvent) { + editor._onEvent(event); + } + } + this.frame.onclick = function (event) { + var target = event.target;// || event.srcElement; + + onEvent(event); + + // prevent default submit action of buttons when editor is located + // inside a form + if (target.nodeName == 'BUTTON') { + event.preventDefault(); + } + }; + this.frame.oninput = onEvent; + this.frame.onchange = onEvent; + this.frame.onkeydown = onEvent; + this.frame.onkeyup = onEvent; + this.frame.oncut = onEvent; + this.frame.onpaste = onEvent; + this.frame.onmousedown = onEvent; + this.frame.onmouseup = onEvent; + this.frame.onmouseover = onEvent; + this.frame.onmouseout = onEvent; + // Note: focus and blur events do not propagate, therefore they defined + // using an eventListener with useCapture=true + // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + util.addEventListener(this.frame, 'focus', onEvent, true); + util.addEventListener(this.frame, 'blur', onEvent, true); + this.frame.onfocusin = onEvent; // for IE + this.frame.onfocusout = onEvent; // for IE + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create expand all button + var expandAll = document.createElement('button'); + expandAll.type = 'button'; + expandAll.className = 'jsoneditor-expand-all'; + expandAll.title = 'Expand all fields'; + expandAll.onclick = function () { + editor.expandAll(); + }; + this.menu.appendChild(expandAll); + + // create collapse all button + var collapseAll = document.createElement('button'); + collapseAll.type = 'button'; + collapseAll.title = 'Collapse all fields'; + collapseAll.className = 'jsoneditor-collapse-all'; + collapseAll.onclick = function () { + editor.collapseAll(); + }; + this.menu.appendChild(collapseAll); + + // create undo/redo buttons + if (this.history) { + // create undo button + var undo = document.createElement('button'); + undo.type = 'button'; + undo.className = 'jsoneditor-undo jsoneditor-separator'; + undo.title = 'Undo last action (Ctrl+Z)'; + undo.onclick = function () { + editor._onUndo(); + }; + this.menu.appendChild(undo); + this.dom.undo = undo; + + // create redo button + var redo = document.createElement('button'); + redo.type = 'button'; + redo.className = 'jsoneditor-redo'; + redo.title = 'Redo (Ctrl+Shift+Z)'; + redo.onclick = function () { + editor._onRedo(); + }; + this.menu.appendChild(redo); + this.dom.redo = redo; + + // register handler for onchange of history + this.history.onChange = function () { + undo.disabled = !editor.history.canUndo(); + redo.disabled = !editor.history.canRedo(); + }; + this.history.onChange(); + } + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + var me = this; + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + me.modeSwitcher.destroy(); + + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + // create search box + if (this.options.search) { + this.searchBox = new SearchBox(this, this.menu); + } + + if(this.options.navigationBar) { + // create second menu row for treepath + this.navBar = document.createElement('div'); + this.navBar.className = 'jsoneditor-navigation-bar nav-bar-empty'; + this.frame.appendChild(this.navBar); + + this.treePath = new TreePath(this.navBar); + this.treePath.onSectionSelected(this._onTreePathSectionSelected.bind(this)); + this.treePath.onContextMenuItemSelected(this._onTreePathMenuItemSelected.bind(this)); + } + }; + + /** + * Perform an undo action + * @private + */ + treemode._onUndo = function () { + if (this.history) { + // undo last action + this.history.undo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Perform a redo action + * @private + */ + treemode._onRedo = function () { + if (this.history) { + // redo last action + this.history.redo(); + + // fire change event + this._onChange(); + } + }; + + /** + * Event handler + * @param event + * @private + */ + treemode._onEvent = function (event) { + if (event.type == 'keydown') { + this._onKeyDown(event); + } + + if (event.type == 'focus') { + this.focusTarget = event.target; + } + + if (event.type == 'mousedown') { + this._startDragDistance(event); + } + if (event.type == 'mousemove' || event.type == 'mouseup' || event.type == 'click') { + this._updateDragDistance(event); + } + + var node = Node.getNodeFromTarget(event.target); + + if (this.options && this.options.navigationBar && node && (event.type == 'keydown' || event.type == 'mousedown')) { + this._updateTreePath(node.getNodePath()); + } + + if (node && node.selected) { + if (event.type == 'click') { + if (event.target == node.dom.menu) { + this.showContextMenu(event.target); + + // stop propagation (else we will open the context menu of a single node) + return; + } + + // deselect a multi selection + if (!event.hasMoved) { + this.deselect(); + } + } + + if (event.type == 'mousedown') { + // drag multiple nodes + Node.onDragStart(this.multiselection.nodes, event); + } + } + else { + if (event.type == 'mousedown') { + this.deselect(); + + if (node && event.target == node.dom.drag) { + // drag a singe node + Node.onDragStart(node, event); + } + else if (!node || (event.target != node.dom.field && event.target != node.dom.value && event.target != node.dom.select)) { + // select multiple nodes + this._onMultiSelectStart(event); + } + } + } + + if (node) { + node.onEvent(event); + } + }; + + /** + * Update TreePath components + * @param {Array} pathNodes list of nodes in path from root to selection + * @private + */ + treemode._updateTreePath = function (pathNodes) { + if (pathNodes && pathNodes.length) { + util.removeClassName(this.navBar, 'nav-bar-empty'); + + var pathObjs = []; + pathNodes.forEach(function (node) { + var pathObj = { + name: getName(node), + node: node, + children: [] + } + if (node.childs && node.childs.length) { + node.childs.forEach(function (childNode) { + pathObj.children.push({ + name: getName(childNode), + node: childNode + }); + }); + } + pathObjs.push(pathObj); + }); + this.treePath.setPath(pathObjs); + } else { + util.addClassName(this.navBar, 'nav-bar-empty'); + } + + function getName(node) { + return node.field || (isNaN(node.index) ? node.type : node.index); + } + }; + + /** + * Callback for tree path section selection - focus the selected node in the tree + * @param {Object} pathObj path object that was represents the selected section node + * @private + */ + treemode._onTreePathSectionSelected = function (pathObj) { + if(pathObj && pathObj.node) { + pathObj.node.expandTo(); + pathObj.node.focus(); + } + }; + + /** + * Callback for tree path menu item selection - rebuild the path accrding to the new selection and focus the selected node in the tree + * @param {Object} pathObj path object that was represents the parent section node + * @param {String} selection selected section child + * @private + */ + treemode._onTreePathMenuItemSelected = function (pathObj, selection) { + if(pathObj && pathObj.children.length) { + var selectionObj = pathObj.children.find(function (obj) { + return obj.name === selection; + }); + if(selectionObj && selectionObj.node) { + this._updateTreePath(selectionObj.node.getNodePath()); + selectionObj.node.expandTo(); + selectionObj.node.focus(); + } + } + }; + + treemode._startDragDistance = function (event) { + this.dragDistanceEvent = { + initialTarget: event.target, + initialPageX: event.pageX, + initialPageY: event.pageY, + dragDistance: 0, + hasMoved: false + }; + }; + + treemode._updateDragDistance = function (event) { + if (!this.dragDistanceEvent) { + this._startDragDistance(event); + } + + var diffX = event.pageX - this.dragDistanceEvent.initialPageX; + var diffY = event.pageY - this.dragDistanceEvent.initialPageY; + + this.dragDistanceEvent.dragDistance = Math.sqrt(diffX * diffX + diffY * diffY); + this.dragDistanceEvent.hasMoved = + this.dragDistanceEvent.hasMoved || this.dragDistanceEvent.dragDistance > 10; + + event.dragDistance = this.dragDistanceEvent.dragDistance; + event.hasMoved = this.dragDistanceEvent.hasMoved; + + return event.dragDistance; + }; + + /** + * Start multi selection of nodes by dragging the mouse + * @param event + * @private + */ + treemode._onMultiSelectStart = function (event) { + var node = Node.getNodeFromTarget(event.target); + + if (this.options.mode !== 'tree' || this.options.onEditable !== undefined) { + // dragging not allowed in modes 'view' and 'form' + // TODO: allow multiselection of items when option onEditable is specified + return; + } + + this.multiselection = { + start: node || null, + end: null, + nodes: [] + }; + + this._startDragDistance(event); + + var editor = this; + if (!this.mousemove) { + this.mousemove = util.addEventListener(window, 'mousemove', function (event) { + editor._onMultiSelect(event); + }); + } + if (!this.mouseup) { + this.mouseup = util.addEventListener(window, 'mouseup', function (event ) { + editor._onMultiSelectEnd(event); + }); + } + + }; + + /** + * Multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelect = function (event) { + event.preventDefault(); + + this._updateDragDistance(event); + if (!event.hasMoved) { + return; + } + + var node = Node.getNodeFromTarget(event.target); + + if (node) { + if (this.multiselection.start == null) { + this.multiselection.start = node; + } + this.multiselection.end = node; + } + + // deselect previous selection + this.deselect(); + + // find the selected nodes in the range from first to last + var start = this.multiselection.start; + var end = this.multiselection.end || this.multiselection.start; + if (start && end) { + // find the top level childs, all having the same parent + this.multiselection.nodes = this._findTopLevelNodes(start, end); + this.select(this.multiselection.nodes); + } + }; + + /** + * End of multiselect nodes by dragging + * @param event + * @private + */ + treemode._onMultiSelectEnd = function (event) { + // set focus to the context menu button of the first node + if (this.multiselection.nodes[0]) { + this.multiselection.nodes[0].dom.menu.focus(); + } + + this.multiselection.start = null; + this.multiselection.end = null; + + // cleanup global event listeners + if (this.mousemove) { + util.removeEventListener(window, 'mousemove', this.mousemove); + delete this.mousemove; + } + if (this.mouseup) { + util.removeEventListener(window, 'mouseup', this.mouseup); + delete this.mouseup; + } + }; + + /** + * deselect currently selected nodes + * @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end` + * state is cleared too. + */ + treemode.deselect = function (clearStartAndEnd) { + this.multiselection.nodes.forEach(function (node) { + node.setSelected(false); + }); + this.multiselection.nodes = []; + + if (clearStartAndEnd) { + this.multiselection.start = null; + this.multiselection.end = null; + } + }; + + /** + * select nodes + * @param {Node[] | Node} nodes + */ + treemode.select = function (nodes) { + if (!Array.isArray(nodes)) { + return this.select([nodes]); + } + + if (nodes) { + this.deselect(); + + this.multiselection.nodes = nodes.slice(0); + + var first = nodes[0]; + nodes.forEach(function (node) { + node.setSelected(true, node === first); + }); + } + }; + + /** + * From two arbitrary selected nodes, find their shared parent node. + * From that parent node, select the two child nodes in the brances going to + * nodes `start` and `end`, and select all childs in between. + * @param {Node} start + * @param {Node} end + * @return {Array.} Returns an ordered list with child nodes + * @private + */ + treemode._findTopLevelNodes = function (start, end) { + var startPath = start.getNodePath(); + var endPath = end.getNodePath(); + var i = 0; + while (i < startPath.length && startPath[i] === endPath[i]) { + i++; + } + var root = startPath[i - 1]; + var startChild = startPath[i]; + var endChild = endPath[i]; + + if (!startChild || !endChild) { + if (root.parent) { + // startChild is a parent of endChild or vice versa + startChild = root; + endChild = root; + root = root.parent + } + else { + // we have selected the root node (which doesn't have a parent) + startChild = root.childs[0]; + endChild = root.childs[root.childs.length - 1]; + } + } + + if (root && startChild && endChild) { + var startIndex = root.childs.indexOf(startChild); + var endIndex = root.childs.indexOf(endChild); + var firstIndex = Math.min(startIndex, endIndex); + var lastIndex = Math.max(startIndex, endIndex); + + return root.childs.slice(firstIndex, lastIndex + 1); + } + else { + return []; + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + treemode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var altKey = event.altKey; + var ctrlKey = event.ctrlKey; + var metaKey = event.metaKey; + var shiftKey = event.shiftKey; + var handled = false; + + if (keynum == 9) { // Tab or Shift+Tab + var me = this; + setTimeout(function () { + // select all text when moving focus to an editable div + util.selectContentEditable(me.focusTarget); + }, 0); + } + + if (this.searchBox) { + if (ctrlKey && keynum == 70) { // Ctrl+F + this.searchBox.dom.search.focus(); + this.searchBox.dom.search.select(); + handled = true; + } + else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G + var focus = true; + if (!shiftKey) { + // select next search result (F3 or Ctrl+G) + this.searchBox.next(focus); + } + else { + // select previous search result (Shift+F3 or Ctrl+Shift+G) + this.searchBox.previous(focus); + } + + handled = true; + } + } + + if (this.history) { + if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z + // undo + this._onUndo(); + handled = true; + } + else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z + // redo + this._onRedo(); + handled = true; + } + } + + if ((this.options.autocomplete) && (!handled)) { + if (!ctrlKey && !altKey && !metaKey && (event.key.length == 1 || keynum == 8 || keynum == 46)) { + handled = false; + var jsonElementType = ""; + if (event.target.className.indexOf("jsoneditor-value") >= 0) jsonElementType = "value"; + if (event.target.className.indexOf("jsoneditor-field") >= 0) jsonElementType = "field"; + + var node = Node.getNodeFromTarget(event.target); + // Activate autocomplete + setTimeout(function (hnode, element) { + if (element.innerText.length > 0) { + var result = this.options.autocomplete.getOptions(element.innerText, hnode.getPath(), jsonElementType, hnode.editor); + if (typeof result.then === 'function') { + // probably a promise + if (result.then(function (obj) { + if (obj.options) + this.autocomplete.show(element, obj.startFrom, obj.options); + else + this.autocomplete.show(element, 0, obj); + }.bind(this))); + } else { + // definitely not a promise + if (result.options) + this.autocomplete.show(element, result.startFrom, result.options); + else + this.autocomplete.show(element, 0, result); + } + } + else + this.autocomplete.hideDropDown(); + + }.bind(this, node, event.target), 50); + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Create main table + * @private + */ + treemode._createTable = function () { + var contentOuter = document.createElement('div'); + contentOuter.className = 'jsoneditor-outer'; + if(this.options.navigationBar) { + util.addClassName(contentOuter, 'has-nav-bar'); + } + this.contentOuter = contentOuter; + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-tree'; + contentOuter.appendChild(this.content); + + this.table = document.createElement('table'); + this.table.className = 'jsoneditor-tree'; + this.content.appendChild(this.table); + + // create colgroup where the first two columns don't have a fixed + // width, and the edit columns do have a fixed width + var col; + this.colgroupContent = document.createElement('colgroup'); + if (this.options.mode === 'tree') { + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + } + col = document.createElement('col'); + col.width = "24px"; + this.colgroupContent.appendChild(col); + col = document.createElement('col'); + this.colgroupContent.appendChild(col); + this.table.appendChild(this.colgroupContent); + + this.tbody = document.createElement('tbody'); + this.table.appendChild(this.tbody); + + this.frame.appendChild(contentOuter); + }; + + /** + * Show a contextmenu for this node. + * Used for multiselection + * @param {HTMLElement} anchor Anchor element to attach the context menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + treemode.showContextMenu = function (anchor, onClose) { + var items = []; + var editor = this; + + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate selected fields (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(editor.multiselection.nodes); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove selected fields (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(editor.multiselection.nodes); + } + }); + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.content); + }; + + + // define modes + module.exports = [ + { + mode: 'tree', + mixin: treemode, + data: 'json' + }, + { + mode: 'view', + mixin: treemode, + data: 'json' + }, + { + mode: 'form', + mixin: treemode, + data: 'json' + } + ]; + + +/***/ }, +/* 52 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * The highlighter can highlight/unhighlight a node, and + * animate the visibility of a context menu. + * @constructor Highlighter + */ + function Highlighter () { + this.locked = false; + } + + /** + * Hightlight given node and its childs + * @param {Node} node + */ + Highlighter.prototype.highlight = function (node) { + if (this.locked) { + return; + } + + if (this.node != node) { + // unhighlight current node + if (this.node) { + this.node.setHighlight(false); + } + + // highlight new node + this.node = node; + this.node.setHighlight(true); + } + + // cancel any current timeout + this._cancelUnhighlight(); + }; + + /** + * Unhighlight currently highlighted node. + * Will be done after a delay + */ + Highlighter.prototype.unhighlight = function () { + if (this.locked) { + return; + } + + var me = this; + if (this.node) { + this._cancelUnhighlight(); + + // do the unhighlighting after a small delay, to prevent re-highlighting + // the same node when moving from the drag-icon to the contextmenu-icon + // or vice versa. + this.unhighlightTimer = setTimeout(function () { + me.node.setHighlight(false); + me.node = undefined; + me.unhighlightTimer = undefined; + }, 0); + } + }; + + /** + * Cancel an unhighlight action (if before the timeout of the unhighlight action) + * @private + */ + Highlighter.prototype._cancelUnhighlight = function () { + if (this.unhighlightTimer) { + clearTimeout(this.unhighlightTimer); + this.unhighlightTimer = undefined; + } + }; + + /** + * Lock highlighting or unhighlighting nodes. + * methods highlight and unhighlight do not work while locked. + */ + Highlighter.prototype.lock = function () { + this.locked = true; + }; + + /** + * Unlock highlighting or unhighlighting nodes + */ + Highlighter.prototype.unlock = function () { + this.locked = false; + }; + + module.exports = Highlighter; + + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + + /** + * @constructor History + * Store action history, enables undo and redo + * @param {JSONEditor} editor + */ + function History (editor) { + this.editor = editor; + this.history = []; + this.index = -1; + + this.clear(); + + // map with all supported actions + this.actions = { + 'editField': { + 'undo': function (params) { + params.node.updateField(params.oldValue); + }, + 'redo': function (params) { + params.node.updateField(params.newValue); + } + }, + 'editValue': { + 'undo': function (params) { + params.node.updateValue(params.oldValue); + }, + 'redo': function (params) { + params.node.updateValue(params.newValue); + } + }, + 'changeType': { + 'undo': function (params) { + params.node.changeType(params.oldType); + }, + 'redo': function (params) { + params.node.changeType(params.newType); + } + }, + + 'appendNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.appendChild(node); + }); + } + }, + 'insertBeforeNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.insertBefore(node, params.beforeNode); + }); + } + }, + 'insertAfterNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(params.node, afterNode); + afterNode = node; + }); + } + }, + 'removeNodes': { + 'undo': function (params) { + var parent = params.parent; + var beforeNode = parent.childs[params.index] || parent.append; + params.nodes.forEach(function (node) { + parent.insertBefore(node, beforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + } + }, + 'duplicateNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.parent.removeChild(node); + }); + }, + 'redo': function (params) { + var afterNode = params.afterNode; + params.nodes.forEach(function (node) { + params.parent.insertAfter(node, afterNode); + afterNode = node; + }); + } + }, + 'moveNodes': { + 'undo': function (params) { + params.nodes.forEach(function (node) { + params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); + }); + }, + 'redo': function (params) { + params.nodes.forEach(function (node) { + params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); + }); + } + }, + + 'sort': { + 'undo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.oldSort; + node.childs = params.oldChilds; + node.showChilds(); + }, + 'redo': function (params) { + var node = params.node; + node.hideChilds(); + node.sort = params.newSort; + node.childs = params.newChilds; + node.showChilds(); + } + } + + // TODO: restore the original caret position and selection with each undo + // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" + }; + } + + /** + * The method onChange is executed when the History is changed, and can + * be overloaded. + */ + History.prototype.onChange = function () {}; + + /** + * Add a new action to the history + * @param {String} action The executed action. Available actions: "editField", + * "editValue", "changeType", "appendNode", + * "removeNode", "duplicateNode", "moveNode" + * @param {Object} params Object containing parameters describing the change. + * The parameters in params depend on the action (for + * example for "editValue" the Node, old value, and new + * value are provided). params contains all information + * needed to undo or redo the action. + */ + History.prototype.add = function (action, params) { + this.index++; + this.history[this.index] = { + 'action': action, + 'params': params, + 'timestamp': new Date() + }; + + // remove redo actions which are invalid now + if (this.index < this.history.length - 1) { + this.history.splice(this.index + 1, this.history.length - this.index - 1); + } + + // fire onchange event + this.onChange(); + }; + + /** + * Clear history + */ + History.prototype.clear = function () { + this.history = []; + this.index = -1; + + // fire onchange event + this.onChange(); + }; + + /** + * Check if there is an action available for undo + * @return {Boolean} canUndo + */ + History.prototype.canUndo = function () { + return (this.index >= 0); + }; + + /** + * Check if there is an action available for redo + * @return {Boolean} canRedo + */ + History.prototype.canRedo = function () { + return (this.index < this.history.length - 1); + }; + + /** + * Undo the last action + */ + History.prototype.undo = function () { + if (this.canUndo()) { + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.undo) { + action.undo(obj.params); + if (obj.params.oldSelection) { + this.editor.setSelection(obj.params.oldSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + this.index--; + + // fire onchange event + this.onChange(); + } + }; + + /** + * Redo the last action + */ + History.prototype.redo = function () { + if (this.canRedo()) { + this.index++; + + var obj = this.history[this.index]; + if (obj) { + var action = this.actions[obj.action]; + if (action && action.redo) { + action.redo(obj.params); + if (obj.params.newSelection) { + this.editor.setSelection(obj.params.newSelection); + } + } + else { + console.error(new Error('unknown action "' + obj.action + '"')); + } + } + + // fire onchange event + this.onChange(); + } + }; + + /** + * Destroy history + */ + History.prototype.destroy = function () { + this.editor = null; + + this.history = []; + this.index = -1; + }; + + module.exports = History; + + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var jsonlint = __webpack_require__(55); + + /** + * Parse JSON using the parser built-in in the browser. + * On exception, the jsonString is validated and a detailed error is thrown. + * @param {String} jsonString + * @return {JSON} json + */ + exports.parse = function parse(jsonString) { + try { + return JSON.parse(jsonString); + } + catch (err) { + // try to throw a more detailed error message using validate + exports.validate(jsonString); + + // rethrow the original error + throw err; + } + }; + + /** + * Sanitize a JSON-like string containing. For example changes JavaScript + * notation into JSON notation. + * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" + * into '{"a": 2, "b": {"c": "d"}' + * @param {string} jsString + * @returns {string} json + */ + exports.sanitize = function (jsString) { + // escape all single and double quotes inside strings + var chars = []; + var i = 0; + + //If JSON starts with a function (characters/digits/"_-"), remove this function. + //This is useful for "stripping" JSONP objects to become JSON + //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] + var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); + if (match) { + jsString = match[3]; + } + + var controlChars = { + '\b': '\\b', + '\f': '\\f', + '\n': '\\n', + '\r': '\\r', + '\t': '\\t' + }; + + var quote = '\''; + var quoteDbl = '"'; + var quoteLeft = '\u2018'; + var quoteRight = '\u2019'; + var quoteDblLeft = '\u201C'; + var quoteDblRight = '\u201D'; + var graveAccent = '\u0060'; + var acuteAccent = '\u00B4'; + + // helper functions to get the current/prev/next character + function curr () { return jsString.charAt(i); } + function next() { return jsString.charAt(i + 1); } + function prev() { return jsString.charAt(i - 1); } + + // get the last parsed non-whitespace character + function lastNonWhitespace () { + var p = chars.length - 1; + + while (p >= 0) { + var pp = chars[p]; + if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace + return pp; + } + p--; + } + + return ''; + } + + // skip a block comment '/* ... */' + function skipBlockComment () { + i += 2; + while (i < jsString.length && (curr() !== '*' || next() !== '/')) { + i++; + } + i += 2; + } + + // skip a comment '// ...' + function skipComment () { + i += 2; + while (i < jsString.length && (curr() !== '\n')) { + i++; + } + } + + // parse single or double quoted string + function parseString(endQuote) { + chars.push('"'); + i++; + var c = curr(); + while (i < jsString.length && c !== endQuote) { + if (c === '"' && prev() !== '\\') { + // unescaped double quote, escape it + chars.push('\\"'); + } + else if (controlChars.hasOwnProperty(c)) { + // replace unescaped control characters with escaped ones + chars.push(controlChars[c]) + } + else if (c === '\\') { + // remove the escape character when followed by a single quote ', not needed + i++; + c = curr(); + if (c !== '\'') { + chars.push('\\'); + } + chars.push(c); + } + else { + // regular character + chars.push(c); + } + + i++; + c = curr(); + } + if (c === endQuote) { + chars.push('"'); + i++; + } + } + + // parse an unquoted key + function parseKey() { + var specialValues = ['null', 'true', 'false']; + var key = ''; + var c = curr(); + + var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character + while (regexp.test(c)) { + key += c; + i++; + c = curr(); + } + + if (specialValues.indexOf(key) === -1) { + chars.push('"' + key + '"'); + } + else { + chars.push(key); + } + } + + while(i < jsString.length) { + var c = curr(); + + if (c === '/' && next() === '*') { + skipBlockComment(); + } + else if (c === '/' && next() === '/') { + skipComment(); + } + else if (c === '\u00A0' || (c >= '\u2000' && c <= '\u200A') || c === '\u202F' || c === '\u205F' || c === '\u3000') { + // special white spaces (like non breaking space) + chars.push(' ') + i++ + } + else if (c === quote) { + parseString(quote); + } + else if (c === quoteDbl) { + parseString(quoteDbl); + } + else if (c === graveAccent) { + parseString(acuteAccent); + } + else if (c === quoteLeft) { + parseString(quoteRight); + } + else if (c === quoteDblLeft) { + parseString(quoteDblRight); + } + else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { + // an unquoted object key (like a in '{a:2}') + parseKey(); + } + else { + chars.push(c); + i++; + } + } + + return chars.join(''); + }; + + /** + * Escape unicode characters. + * For example input '\u2661' (length 1) will output '\\u2661' (length 5). + * @param {string} text + * @return {string} + */ + exports.escapeUnicodeChars = function (text) { + // see https://www.wikiwand.com/en/UTF-16 + // note: we leave surrogate pairs as two individual chars, + // as JSON doesn't interpret them as a single unicode char. + return text.replace(/[\u007F-\uFFFF]/g, function(c) { + return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }) + }; + + /** + * Validate a string containing a JSON object + * This method uses JSONLint to validate the String. If JSONLint is not + * available, the built-in JSON parser of the browser is used. + * @param {String} jsonString String with an (invalid) JSON object + * @throws Error + */ + exports.validate = function validate(jsonString) { + if (typeof(jsonlint) != 'undefined') { + jsonlint.parse(jsonString); + } + else { + JSON.parse(jsonString); + } + }; + + /** + * Extend object a with the properties of object b + * @param {Object} a + * @param {Object} b + * @return {Object} a + */ + exports.extend = function extend(a, b) { + for (var prop in b) { + if (b.hasOwnProperty(prop)) { + a[prop] = b[prop]; + } + } + return a; + }; + + /** + * Remove all properties from object a + * @param {Object} a + * @return {Object} a + */ + exports.clear = function clear (a) { + for (var prop in a) { + if (a.hasOwnProperty(prop)) { + delete a[prop]; + } + } + return a; + }; + + /** + * Get the type of an object + * @param {*} object + * @return {String} type + */ + exports.type = function type (object) { + if (object === null) { + return 'null'; + } + if (object === undefined) { + return 'undefined'; + } + if ((object instanceof Number) || (typeof object === 'number')) { + return 'number'; + } + if ((object instanceof String) || (typeof object === 'string')) { + return 'string'; + } + if ((object instanceof Boolean) || (typeof object === 'boolean')) { + return 'boolean'; + } + if ((object instanceof RegExp) || (typeof object === 'regexp')) { + return 'regexp'; + } + if (exports.isArray(object)) { + return 'array'; + } + + return 'object'; + }; + + /** + * Test whether a text contains a url (matches when a string starts + * with 'http://*' or 'https://*' and has no whitespace characters) + * @param {String} text + */ + var isUrlRegex = /^https?:\/\/\S+$/; + exports.isUrl = function isUrl (text) { + return (typeof text == 'string' || text instanceof String) && + isUrlRegex.test(text); + }; + + /** + * Tes whether given object is an Array + * @param {*} obj + * @returns {boolean} returns true when obj is an array + */ + exports.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + /** + * Retrieve the absolute left value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} left The absolute left position of this element + * in the browser page. + */ + exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { + var rect = elem.getBoundingClientRect(); + return rect.left + window.pageXOffset || document.scrollLeft || 0; + }; + + /** + * Retrieve the absolute top value of a DOM element + * @param {Element} elem A dom element, for example a div + * @return {Number} top The absolute top position of this element + * in the browser page. + */ + exports.getAbsoluteTop = function getAbsoluteTop(elem) { + var rect = elem.getBoundingClientRect(); + return rect.top + window.pageYOffset || document.scrollTop || 0; + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.addClassName = function addClassName(elem, className) { + var classes = elem.className.split(' '); + if (classes.indexOf(className) == -1) { + classes.push(className); // add the class to the array + elem.className = classes.join(' '); + } + }; + + /** + * add a className to the given elements style + * @param {Element} elem + * @param {String} className + */ + exports.removeClassName = function removeClassName(elem, className) { + var classes = elem.className.split(' '); + var index = classes.indexOf(className); + if (index != -1) { + classes.splice(index, 1); // remove the class from the array + elem.className = classes.join(' '); + } + }; + + /** + * Strip the formatting from the contents of a div + * the formatting from the div itself is not stripped, only from its childs. + * @param {Element} divElement + */ + exports.stripFormatting = function stripFormatting(divElement) { + var childs = divElement.childNodes; + for (var i = 0, iMax = childs.length; i < iMax; i++) { + var child = childs[i]; + + // remove the style + if (child.style) { + // TODO: test if child.attributes does contain style + child.removeAttribute('style'); + } + + // remove all attributes + var attributes = child.attributes; + if (attributes) { + for (var j = attributes.length - 1; j >= 0; j--) { + var attribute = attributes[j]; + if (attribute.specified === true) { + child.removeAttribute(attribute.name); + } + } + } + + // recursively strip childs + exports.stripFormatting(child); + } + }; + + /** + * Set focus to the end of an editable div + * code from Nico Burns + * http://stackoverflow.com/users/140293/nico-burns + * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity + * @param {Element} contentEditableElement A content editable div + */ + exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { + var range, selection; + if(document.createRange) { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + }; + + /** + * Select all text of a content editable div. + * http://stackoverflow.com/a/3806004/1262753 + * @param {Element} contentEditableElement A content editable div + */ + exports.selectContentEditable = function selectContentEditable(contentEditableElement) { + if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { + return; + } + + var sel, range; + if (window.getSelection && document.createRange) { + range = document.createRange(); + range.selectNodeContents(contentEditableElement); + sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + }; + + /** + * Get text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @return {Range | TextRange | null} range + */ + exports.getSelection = function getSelection() { + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + return sel.getRangeAt(0); + } + } + return null; + }; + + /** + * Set text selection + * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore + * @param {Range | TextRange | null} range + */ + exports.setSelection = function setSelection(range) { + if (range) { + if (window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + } + }; + + /** + * Get selected text range + * @return {Object} params object containing parameters: + * {Number} startOffset + * {Number} endOffset + * {Element} container HTML element holding the + * selected text element + * Returns null if no text selection is found + */ + exports.getSelectionOffset = function getSelectionOffset() { + var range = exports.getSelection(); + + if (range && 'startOffset' in range && 'endOffset' in range && + range.startContainer && (range.startContainer == range.endContainer)) { + return { + startOffset: range.startOffset, + endOffset: range.endOffset, + container: range.startContainer.parentNode + }; + } + + return null; + }; + + /** + * Set selected text range in given element + * @param {Object} params An object containing: + * {Element} container + * {Number} startOffset + * {Number} endOffset + */ + exports.setSelectionOffset = function setSelectionOffset(params) { + if (document.createRange && window.getSelection) { + var selection = window.getSelection(); + if(selection) { + var range = document.createRange(); + + if (!params.container.firstChild) { + params.container.appendChild(document.createTextNode('')); + } + + // TODO: do not suppose that the first child of the container is a textnode, + // but recursively find the textnodes + range.setStart(params.container.firstChild, params.startOffset); + range.setEnd(params.container.firstChild, params.endOffset); + + exports.setSelection(range); + } + } + }; + + /** + * Get the inner text of an HTML element (for example a div element) + * @param {Element} element + * @param {Object} [buffer] + * @return {String} innerText + */ + exports.getInnerText = function getInnerText(element, buffer) { + var first = (buffer == undefined); + if (first) { + buffer = { + 'text': '', + 'flush': function () { + var text = this.text; + this.text = ''; + return text; + }, + 'set': function (text) { + this.text = text; + } + }; + } + + // text node + if (element.nodeValue) { + return buffer.flush() + element.nodeValue; + } + + // divs or other HTML elements + if (element.hasChildNodes()) { + var childNodes = element.childNodes; + var innerText = ''; + + for (var i = 0, iMax = childNodes.length; i < iMax; i++) { + var child = childNodes[i]; + + if (child.nodeName == 'DIV' || child.nodeName == 'P') { + var prevChild = childNodes[i - 1]; + var prevName = prevChild ? prevChild.nodeName : undefined; + if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { + innerText += '\n'; + buffer.flush(); + } + innerText += exports.getInnerText(child, buffer); + buffer.set('\n'); + } + else if (child.nodeName == 'BR') { + innerText += buffer.flush(); + buffer.set('\n'); + } + else { + innerText += exports.getInnerText(child, buffer); + } + } + + return innerText; + } + else { + if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { + // On Internet Explorer, a

with hasChildNodes()==false is + // rendered with a new line. Note that a

with + // hasChildNodes()==true is rendered without a new line + // Other browsers always ensure there is a
inside the

, + // and if not, the

does not render a new line + return buffer.flush(); + } + } + + // br or unknown + return ''; + }; + + /** + * Returns the version of Internet Explorer or a -1 + * (indicating the use of another browser). + * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx + * @return {Number} Internet Explorer version, or -1 in case of an other browser + */ + exports.getInternetExplorerVersion = function getInternetExplorerVersion() { + if (_ieVersion == -1) { + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') + { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat( RegExp.$1 ); + } + } + + _ieVersion = rv; + } + + return _ieVersion; + }; + + /** + * Test whether the current browser is Firefox + * @returns {boolean} isFirefox + */ + exports.isFirefox = function isFirefox () { + return (navigator.userAgent.indexOf("Firefox") != -1); + }; + + /** + * cached internet explorer version + * @type {Number} + * @private + */ + var _ieVersion = -1; + + /** + * Add and event listener. Works for all browsers + * @param {Element} element An html element + * @param {string} action The action, for example "click", + * without the prefix "on" + * @param {function} listener The callback function to be executed + * @param {boolean} [useCapture] false by default + * @return {function} the created event listener + */ + exports.addEventListener = function addEventListener(element, action, listener, useCapture) { + if (element.addEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.addEventListener(action, listener, useCapture); + return listener; + } else if (element.attachEvent) { + // Old IE browsers + var f = function () { + return listener.call(element, window.event); + }; + element.attachEvent("on" + action, f); + return f; + } + }; + + /** + * Remove an event listener from an element + * @param {Element} element An html dom element + * @param {string} action The name of the event, for example "mousedown" + * @param {function} listener The listener function + * @param {boolean} [useCapture] false by default + */ + exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { + if (element.removeEventListener) { + if (useCapture === undefined) + useCapture = false; + + if (action === "mousewheel" && exports.isFirefox()) { + action = "DOMMouseScroll"; // For Firefox + } + + element.removeEventListener(action, listener, useCapture); + } else if (element.detachEvent) { + // Old IE browsers + element.detachEvent("on" + action, listener); + } + }; + + /** + * Parse a JSON path like '.items[3].name' into an array + * @param {string} jsonPath + * @return {Array} + */ + exports.parsePath = function parsePath(jsonPath) { + var prop, remainder; + + if (jsonPath.length === 0) { + return []; + } + + // find a match like '.prop' + var match = jsonPath.match(/^\.(\w+)/); + if (match) { + prop = match[1]; + remainder = jsonPath.substr(prop.length + 1); + } + else if (jsonPath[0] === '[') { + // find a match like + var end = jsonPath.indexOf(']'); + if (end === -1) { + throw new SyntaxError('Character ] expected in path'); + } + if (end === 1) { + throw new SyntaxError('Index expected after ['); + } + + var value = jsonPath.substring(1, end); + if (value[0] === '\'') { + // ajv produces string prop names with single quotes, so we need + // to reformat them into valid double-quoted JSON strings + value = '\"' + value.substring(1, value.length - 1) + '\"'; + } + + prop = value === '*' ? value : JSON.parse(value); // parse string and number + remainder = jsonPath.substr(end + 1); + } + else { + throw new SyntaxError('Failed to parse path'); + } + + return [prop].concat(parsePath(remainder)) + }; + + /** + * Improve the error message of a JSON schema error + * @param {Object} error + * @return {Object} The error + */ + exports.improveSchemaError = function (error) { + if (error.keyword === 'enum' && Array.isArray(error.schema)) { + var enums = error.schema; + if (enums) { + enums = enums.map(function (value) { + return JSON.stringify(value); + }); + + if (enums.length > 5) { + var more = ['(' + (enums.length - 5) + ' more...)']; + enums = enums.slice(0, 5); + enums.push(more); + } + error.message = 'should be equal to one of: ' + enums.join(', '); + } + } + + if (error.keyword === 'additionalProperties') { + error.message = 'should NOT have additional property: ' + error.params.additionalProperty; + } + + return error; + }; + + /** + * Test whether the child rect fits completely inside the parent rect. + * @param {ClientRect} parent + * @param {ClientRect} child + * @param {number} margin + */ + exports.insideRect = function (parent, child, margin) { + var _margin = margin !== undefined ? margin : 0; + return child.left - _margin >= parent.left + && child.right + _margin <= parent.right + && child.top - _margin >= parent.top + && child.bottom + _margin <= parent.bottom; + }; + + /** + * Returns a function, that, as long as it continues to be invoked, will not + * be triggered. The function will be called after it stops being called for + * N milliseconds. + * + * Source: https://davidwalsh.name/javascript-debounce-function + * + * @param {function} func + * @param {number} wait Number in milliseconds + * @param {boolean} [immediate=false] If `immediate` is passed, trigger the + * function on the leading edge, instead + * of the trailing. + * @return {function} Return the debounced function + */ + exports.debounce = function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + }; + + /** + * Determines the difference between two texts. + * Can only detect one removed or inserted block of characters. + * @param {string} oldText + * @param {string} newText + * @return {{start: number, end: number}} Returns the start and end + * of the changed part in newText. + */ + exports.textDiff = function textDiff(oldText, newText) { + var len = newText.length; + var start = 0; + var oldEnd = oldText.length; + var newEnd = newText.length; + + while (newText.charAt(start) === oldText.charAt(start) + && start < len) { + start++; + } + + while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) + && newEnd > start && oldEnd > 0) { + newEnd--; + oldEnd--; + } + + return {start: start, end: newEnd}; + }; + + + /** + * Return an object with the selection range or cursor position (if both have the same value) + * Support also old browsers (IE8-) + * Source: http://ourcodeworld.com/articles/read/282/how-to-get-the-current-cursor-position-and-selection-within-a-text-input-or-textarea-in-javascript + * @param {DOMElement} el A dom element of a textarea or input text. + * @return {Object} reference Object with 2 properties (start and end) with the identifier of the location of the cursor and selected text. + **/ + exports.getInputSelection = function(el) { + var start = 0, end = 0, normalizedValue, range, textInputRange, len, endRange; + + if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { + start = el.selectionStart; + end = el.selectionEnd; + } else { + range = document.selection.createRange(); + + if (range && range.parentElement() == el) { + len = el.value.length; + normalizedValue = el.value.replace(/\r\n/g, "\n"); + + // Create a working TextRange that lives only in the input + textInputRange = el.createTextRange(); + textInputRange.moveToBookmark(range.getBookmark()); + + // Check if the start and end of the selection are at the very end + // of the input, since moveStart/moveEnd doesn't return what we want + // in those cases + endRange = el.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + start = end = len; + } else { + start = -textInputRange.moveStart("character", -len); + start += normalizedValue.slice(0, start).split("\n").length - 1; + + if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { + end = len; + } else { + end = -textInputRange.moveEnd("character", -len); + end += normalizedValue.slice(0, end).split("\n").length - 1; + } + } + } + } + + return { + start: start, + end: end + }; + } + + + if (typeof Element !== 'undefined') { + // Polyfill for array remove + (function () { + function polyfill (item) { + if (item.hasOwnProperty('remove')) { + return; + } + Object.defineProperty(item, 'remove', { + configurable: true, + enumerable: true, + writable: true, + value: function remove() { + if (this.parentNode != null) + this.parentNode.removeChild(this); + } + }); + } + + if (typeof Element !== 'undefined') { polyfill(Element.prototype); } + if (typeof CharacterData !== 'undefined') { polyfill(CharacterData.prototype); } + if (typeof DocumentType !== 'undefined') { polyfill(DocumentType.prototype); } + })(); + } + + + // Polyfill for startsWith + if (!String.prototype.startsWith) { + String.prototype.startsWith = function (searchString, position) { + position = position || 0; + return this.substr(position, searchString.length) === searchString; + }; + } + + // Polyfill for Array.find + if (!Array.prototype.find) { + Array.prototype.find = function(callback) { + for (var i = 0; i < this.length; i++) { + var element = this[i]; + if ( callback.call(this, element, i, this) ) { + return element; + } + } + } + } + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + /* Jison generated parser */ + var jsonlint = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, + terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, + productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: // replace escaped characters with actual character + this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") + .replace(/\\n/g,'\n') + .replace(/\\r/g,'\r') + .replace(/\\t/g,'\t') + .replace(/\\v/g,'\v') + .replace(/\\f/g,'\f') + .replace(/\\b/g,'\b'); + + break; + case 2:this.$ = Number(yytext); + break; + case 3:this.$ = null; + break; + case 4:this.$ = true; + break; + case 5:this.$ = false; + break; + case 6:return this.$ = $$[$0-1]; + break; + case 13:this.$ = {}; + break; + case 14:this.$ = $$[$0-1]; + break; + case 15:this.$ = [$$[$0-2], $$[$0]]; + break; + case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; + break; + case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; + break; + case 18:this.$ = []; + break; + case 19:this.$ = $$[$0-1]; + break; + case 20:this.$ = [$$[$0]]; + break; + case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); + break; + } + }, + table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], + defaultActions: {16:[2,6]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; + }}; + /* Jison generated lexer */ + var lexer = (function(){ + var lexer = ({EOF:1, + parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, + input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, + unput:function (ch) { + this._input = ch + this._input; + return this; + }, + more:function () { + this._more = true; + return this; + }, + less:function (n) { + this._input = this.match.slice(n) + this._input; + }, + pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, + showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, + next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, + lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin:function begin(condition) { + this.conditionStack.push(condition); + }, + popState:function popState() { + return this.conditionStack.pop(); + }, + _currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, + topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, + pushState:function begin(condition) { + this.begin(condition); + }}); + lexer.options = {}; + lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0:/* skip whitespace */ + break; + case 1:return 6 + break; + case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 + break; + case 3:return 17 + break; + case 4:return 18 + break; + case 5:return 23 + break; + case 6:return 24 + break; + case 7:return 22 + break; + case 8:return 21 + break; + case 9:return 10 + break; + case 10:return 11 + break; + case 11:return 8 + break; + case 12:return 14 + break; + case 13:return 'INVALID' + break; + } + }; + lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; + lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; + + + ; + return lexer;})() + parser.lexer = lexer; + return parser; + })(); + if (true) { + exports.parser = jsonlint; + exports.parse = jsonlint.parse.bind(jsonlint); + } + +/***/ }, +/* 56 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * @constructor SearchBox + * Create a search box in given HTML container + * @param {JSONEditor} editor The JSON Editor to attach to + * @param {Element} container HTML container element of where to + * create the search box + */ + function SearchBox (editor, container) { + var searchBox = this; + + this.editor = editor; + this.timeout = undefined; + this.delay = 200; // ms + this.lastText = undefined; + + this.dom = {}; + this.dom.container = container; + + var table = document.createElement('table'); + this.dom.table = table; + table.className = 'jsoneditor-search'; + container.appendChild(table); + var tbody = document.createElement('tbody'); + this.dom.tbody = tbody; + table.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + var td = document.createElement('td'); + tr.appendChild(td); + var results = document.createElement('div'); + this.dom.results = results; + results.className = 'jsoneditor-results'; + td.appendChild(results); + + td = document.createElement('td'); + tr.appendChild(td); + var divInput = document.createElement('div'); + this.dom.input = divInput; + divInput.className = 'jsoneditor-frame'; + divInput.title = 'Search fields and values'; + td.appendChild(divInput); + + // table to contain the text input and search button + var tableInput = document.createElement('table'); + divInput.appendChild(tableInput); + var tbodySearch = document.createElement('tbody'); + tableInput.appendChild(tbodySearch); + tr = document.createElement('tr'); + tbodySearch.appendChild(tr); + + var refreshSearch = document.createElement('button'); + refreshSearch.type = 'button'; + refreshSearch.className = 'jsoneditor-refresh'; + td = document.createElement('td'); + td.appendChild(refreshSearch); + tr.appendChild(td); + + var search = document.createElement('input'); + // search.type = 'button'; + this.dom.search = search; + search.oninput = function (event) { + searchBox._onDelayedSearch(event); + }; + search.onchange = function (event) { // For IE 9 + searchBox._onSearch(); + }; + search.onkeydown = function (event) { + searchBox._onKeyDown(event); + }; + search.onkeyup = function (event) { + searchBox._onKeyUp(event); + }; + refreshSearch.onclick = function (event) { + search.select(); + }; + + // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 + td = document.createElement('td'); + td.appendChild(search); + tr.appendChild(td); + + var searchNext = document.createElement('button'); + searchNext.type = 'button'; + searchNext.title = 'Next result (Enter)'; + searchNext.className = 'jsoneditor-next'; + searchNext.onclick = function () { + searchBox.next(); + }; + td = document.createElement('td'); + td.appendChild(searchNext); + tr.appendChild(td); + + var searchPrevious = document.createElement('button'); + searchPrevious.type = 'button'; + searchPrevious.title = 'Previous result (Shift+Enter)'; + searchPrevious.className = 'jsoneditor-previous'; + searchPrevious.onclick = function () { + searchBox.previous(); + }; + td = document.createElement('td'); + td.appendChild(searchPrevious); + tr.appendChild(td); + } + + /** + * Go to the next search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.next = function(focus) { + if (this.results != undefined) { + var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; + if (index > this.results.length - 1) { + index = 0; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Go to the prevous search result + * @param {boolean} [focus] If true, focus will be set to the next result + * focus is false by default. + */ + SearchBox.prototype.previous = function(focus) { + if (this.results != undefined) { + var max = this.results.length - 1; + var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; + if (index < 0) { + index = max; + } + this._setActiveResult(index, focus); + } + }; + + /** + * Set new value for the current active result + * @param {Number} index + * @param {boolean} [focus] If true, focus will be set to the next result. + * focus is false by default. + * @private + */ + SearchBox.prototype._setActiveResult = function(index, focus) { + // de-activate current active result + if (this.activeResult) { + var prevNode = this.activeResult.node; + var prevElem = this.activeResult.elem; + if (prevElem == 'field') { + delete prevNode.searchFieldActive; + } + else { + delete prevNode.searchValueActive; + } + prevNode.updateDom(); + } + + if (!this.results || !this.results[index]) { + // out of range, set to undefined + this.resultIndex = undefined; + this.activeResult = undefined; + return; + } + + this.resultIndex = index; + + // set new node active + var node = this.results[this.resultIndex].node; + var elem = this.results[this.resultIndex].elem; + if (elem == 'field') { + node.searchFieldActive = true; + } + else { + node.searchValueActive = true; + } + this.activeResult = this.results[this.resultIndex]; + node.updateDom(); + + // TODO: not so nice that the focus is only set after the animation is finished + node.scrollTo(function () { + if (focus) { + node.focus(elem); + } + }); + }; + + /** + * Cancel any running onDelayedSearch. + * @private + */ + SearchBox.prototype._clearDelay = function() { + if (this.timeout != undefined) { + clearTimeout(this.timeout); + delete this.timeout; + } + }; + + /** + * Start a timer to execute a search after a short delay. + * Used for reducing the number of searches while typing. + * @param {Event} event + * @private + */ + SearchBox.prototype._onDelayedSearch = function (event) { + // execute the search after a short delay (reduces the number of + // search actions while typing in the search text box) + this._clearDelay(); + var searchBox = this; + this.timeout = setTimeout(function (event) { + searchBox._onSearch(); + }, + this.delay); + }; + + /** + * Handle onSearch event + * @param {boolean} [forceSearch] If true, search will be executed again even + * when the search text is not changed. + * Default is false. + * @private + */ + SearchBox.prototype._onSearch = function (forceSearch) { + this._clearDelay(); + + var value = this.dom.search.value; + var text = (value.length > 0) ? value : undefined; + if (text != this.lastText || forceSearch) { + // only search again when changed + this.lastText = text; + this.results = this.editor.search(text); + this._setActiveResult(undefined); + + // display search results + if (text != undefined) { + var resultCount = this.results.length; + switch (resultCount) { + case 0: this.dom.results.innerHTML = 'no results'; break; + case 1: this.dom.results.innerHTML = '1 result'; break; + default: this.dom.results.innerHTML = resultCount + ' results'; break; + } + } + else { + this.dom.results.innerHTML = ''; + } + } + }; + + /** + * Handle onKeyDown event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyDown = function (event) { + var keynum = event.which; + if (keynum == 27) { // ESC + this.dom.search.value = ''; // clear search + this._onSearch(); + event.preventDefault(); + event.stopPropagation(); + } + else if (keynum == 13) { // Enter + if (event.ctrlKey) { + // force to search again + this._onSearch(true); + } + else if (event.shiftKey) { + // move to the previous search result + this.previous(); + } + else { + // move to the next search result + this.next(); + } + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle onKeyUp event in the input box + * @param {Event} event + * @private + */ + SearchBox.prototype._onKeyUp = function (event) { + var keynum = event.keyCode; + if (keynum != 27 && keynum != 13) { // !show and !Enter + this._onDelayedSearch(event); // For IE 9 + } + }; + + /** + * Clear the search results + */ + SearchBox.prototype.clear = function () { + this.dom.search.value = ''; + this._onSearch(); + }; + + /** + * Destroy the search box + */ + SearchBox.prototype.destroy = function () { + this.editor = null; + this.dom.container.removeChild(this.dom.table); + this.dom = null; + + this.results = null; + this.activeResult = null; + + this._clearDelay(); + + }; + + module.exports = SearchBox; + + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + + /** + * Node.getRootNode shim + * @param {Node} node node to check + * @return {Node} node's rootNode or `window` if there is ShadowDOM is not supported. + */ + function getRootNode(node){ + return node.getRootNode && node.getRootNode() || window; + } + + /** + * A context menu + * @param {Object[]} items Array containing the menu structure + * TODO: describe structure + * @param {Object} [options] Object with options. Available options: + * {function} close Callback called when the + * context menu is being closed. + * @constructor + */ + function ContextMenu (items, options) { + this.dom = {}; + + var me = this; + var dom = this.dom; + this.anchor = undefined; + this.items = items; + this.eventListeners = {}; + this.selection = undefined; // holds the selection before the menu was opened + this.onClose = options ? options.close : undefined; + + // create root element + var root = document.createElement('div'); + root.className = 'jsoneditor-contextmenu-root'; + dom.root = root; + + // create a container element + var menu = document.createElement('div'); + menu.className = 'jsoneditor-contextmenu'; + dom.menu = menu; + root.appendChild(menu); + + // create a list to hold the menu items + var list = document.createElement('ul'); + list.className = 'jsoneditor-menu'; + menu.appendChild(list); + dom.list = list; + dom.items = []; // list with all buttons + + // create a (non-visible) button to set the focus to the menu + var focusButton = document.createElement('button'); + focusButton.type = 'button'; + dom.focusButton = focusButton; + var li = document.createElement('li'); + li.style.overflow = 'hidden'; + li.style.height = '0'; + li.appendChild(focusButton); + list.appendChild(li); + + function createMenuItems (list, domItems, items) { + items.forEach(function (item) { + if (item.type == 'separator') { + // create a separator + var separator = document.createElement('div'); + separator.className = 'jsoneditor-separator'; + li = document.createElement('li'); + li.appendChild(separator); + list.appendChild(li); + } + else { + var domItem = {}; + + // create a menu item + var li = document.createElement('li'); + list.appendChild(li); + + // create a button in the menu item + var button = document.createElement('button'); + button.type = 'button'; + button.className = item.className; + domItem.button = button; + if (item.title) { + button.title = item.title; + } + if (item.click) { + button.onclick = function (event) { + event.preventDefault(); + me.hide(); + item.click(); + }; + } + li.appendChild(button); + + // create the contents of the button + if (item.submenu) { + // add the icon to the button + var divIcon = document.createElement('div'); + divIcon.className = 'jsoneditor-icon'; + button.appendChild(divIcon); + var divText = document.createElement('div'); + divText.className = 'jsoneditor-text' + + (item.click ? '' : ' jsoneditor-right-margin'); + divText.appendChild(document.createTextNode(item.text)); + button.appendChild(divText); + + var buttonSubmenu; + if (item.click) { + // submenu and a button with a click handler + button.className += ' jsoneditor-default'; + + var buttonExpand = document.createElement('button'); + buttonExpand.type = 'button'; + domItem.buttonExpand = buttonExpand; + buttonExpand.className = 'jsoneditor-expand'; + buttonExpand.innerHTML = '

'; + li.appendChild(buttonExpand); + if (item.submenuTitle) { + buttonExpand.title = item.submenuTitle; + } + + buttonSubmenu = buttonExpand; + } + else { + // submenu and a button without a click handler + var divExpand = document.createElement('div'); + divExpand.className = 'jsoneditor-expand'; + button.appendChild(divExpand); + + buttonSubmenu = button; + } + + // attach a handler to expand/collapse the submenu + buttonSubmenu.onclick = function (event) { + event.preventDefault(); + me._onExpandItem(domItem); + buttonSubmenu.focus(); + }; + + // create the submenu + var domSubItems = []; + domItem.subItems = domSubItems; + var ul = document.createElement('ul'); + domItem.ul = ul; + ul.className = 'jsoneditor-menu'; + ul.style.height = '0'; + li.appendChild(ul); + createMenuItems(ul, domSubItems, item.submenu); + } + else { + // no submenu, just a button with clickhandler + button.innerHTML = '
' + + '
' + item.text + '
'; + } + + domItems.push(domItem); + } + }); + } + createMenuItems(list, this.dom.items, items); + + // TODO: when the editor is small, show the submenu on the right instead of inline? + + // calculate the max height of the menu with one submenu expanded + this.maxHeight = 0; // height in pixels + items.forEach(function (item) { + var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; + me.maxHeight = Math.max(me.maxHeight, height); + }); + } + + /** + * Get the currently visible buttons + * @return {Array.} buttons + * @private + */ + ContextMenu.prototype._getVisibleButtons = function () { + var buttons = []; + var me = this; + this.dom.items.forEach(function (item) { + buttons.push(item.button); + if (item.buttonExpand) { + buttons.push(item.buttonExpand); + } + if (item.subItems && item == me.expandedItem) { + item.subItems.forEach(function (subItem) { + buttons.push(subItem.button); + if (subItem.buttonExpand) { + buttons.push(subItem.buttonExpand); + } + // TODO: change to fully recursive method + }); + } + }); + + return buttons; + }; + + // currently displayed context menu, a singleton. We may only have one visible context menu + ContextMenu.visibleMenu = undefined; + + /** + * Attach the menu to an anchor + * @param {HTMLElement} anchor Anchor where the menu will be attached + * as sibling. + * @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents + */ + ContextMenu.prototype.show = function (anchor, contentWindow) { + this.hide(); + + // determine whether to display the menu below or above the anchor + var showBelow = true; + var parent = anchor.parentNode; + var anchorRect = anchor.getBoundingClientRect(); + var parentRect = parent.getBoundingClientRect() + + if (contentWindow) { + + var contentRect = contentWindow.getBoundingClientRect(); + + if (anchorRect.bottom + this.maxHeight < contentRect.bottom) { + // fits below -> show below + } + else if (anchorRect.top - this.maxHeight > contentRect.top) { + // fits above -> show above + showBelow = false; + } + else { + // doesn't fit above nor below -> show below + } + } + + var leftGap = anchorRect.left - parentRect.left; + var topGap = anchorRect.top - parentRect.top; + + // position the menu + if (showBelow) { + // display the menu below the anchor + var anchorHeight = anchor.offsetHeight; + this.dom.menu.style.left = leftGap + 'px'; + this.dom.menu.style.top = topGap + anchorHeight + 'px'; + this.dom.menu.style.bottom = ''; + } + else { + // display the menu above the anchor + this.dom.menu.style.left = leftGap + 'px'; + this.dom.menu.style.top = topGap + 'px'; + this.dom.menu.style.bottom = '0px'; + } + + // find the root node of the page (window, or a shadow dom root element) + this.rootNode = getRootNode(anchor); + + // attach the menu to the parent of the anchor + parent.insertBefore(this.dom.root, parent.firstChild); + + // create and attach event listeners + var me = this; + var list = this.dom.list; + this.eventListeners.mousedown = util.addEventListener(this.rootNode, 'mousedown', function (event) { + // hide menu on click outside of the menu + var target = event.target; + if ((target != list) && !me._isChildOf(target, list)) { + me.hide(); + event.stopPropagation(); + event.preventDefault(); + } + }); + this.eventListeners.keydown = util.addEventListener(this.rootNode, 'keydown', function (event) { + me._onKeyDown(event); + }); + + // move focus to the first button in the context menu + this.selection = util.getSelection(); + this.anchor = anchor; + setTimeout(function () { + me.dom.focusButton.focus(); + }, 0); + + if (ContextMenu.visibleMenu) { + ContextMenu.visibleMenu.hide(); + } + ContextMenu.visibleMenu = this; + }; + + /** + * Hide the context menu if visible + */ + ContextMenu.prototype.hide = function () { + // remove the menu from the DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + if (this.onClose) { + this.onClose(); + } + } + + // remove all event listeners + // all event listeners are supposed to be attached to document. + for (var name in this.eventListeners) { + if (this.eventListeners.hasOwnProperty(name)) { + var fn = this.eventListeners[name]; + if (fn) { + util.removeEventListener(this.rootNode, name, fn); + } + delete this.eventListeners[name]; + } + } + + if (ContextMenu.visibleMenu == this) { + ContextMenu.visibleMenu = undefined; + } + }; + + /** + * Expand a submenu + * Any currently expanded submenu will be hided. + * @param {Object} domItem + * @private + */ + ContextMenu.prototype._onExpandItem = function (domItem) { + var me = this; + var alreadyVisible = (domItem == this.expandedItem); + + // hide the currently visible submenu + var expandedItem = this.expandedItem; + if (expandedItem) { + //var ul = expandedItem.ul; + expandedItem.ul.style.height = '0'; + expandedItem.ul.style.padding = ''; + setTimeout(function () { + if (me.expandedItem != expandedItem) { + expandedItem.ul.style.display = ''; + util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); + } + }, 300); // timeout duration must match the css transition duration + this.expandedItem = undefined; + } + + if (!alreadyVisible) { + var ul = domItem.ul; + ul.style.display = 'block'; + var height = ul.clientHeight; // force a reflow in Firefox + setTimeout(function () { + if (me.expandedItem == domItem) { + var childsHeight = 0; + for (var i = 0; i < ul.childNodes.length; i++) { + childsHeight += ul.childNodes[i].clientHeight; + } + ul.style.height = childsHeight + 'px'; + ul.style.padding = '5px 10px'; + } + }, 0); + util.addClassName(ul.parentNode, 'jsoneditor-selected'); + this.expandedItem = domItem; + } + }; + + /** + * Handle onkeydown event + * @param {Event} event + * @private + */ + ContextMenu.prototype._onKeyDown = function (event) { + var target = event.target; + var keynum = event.which; + var handled = false; + var buttons, targetIndex, prevButton, nextButton; + + if (keynum == 27) { // ESC + // hide the menu on ESC key + + // restore previous selection and focus + if (this.selection) { + util.setSelection(this.selection); + } + if (this.anchor) { + this.anchor.focus(); + } + + this.hide(); + + handled = true; + } + else if (keynum == 9) { // Tab + if (!event.shiftKey) { // Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == buttons.length - 1) { + // move to first button + buttons[0].focus(); + handled = true; + } + } + else { // Shift+Tab + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + if (targetIndex == 0) { + // move to last button + buttons[buttons.length - 1].focus(); + handled = true; + } + } + } + else if (keynum == 37) { // Arrow Left + if (target.className == 'jsoneditor-expand') { + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton) { + prevButton.focus(); + } + } + handled = true; + } + else if (keynum == 38) { // Arrow Up + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + prevButton = buttons[targetIndex - 1]; + if (prevButton && prevButton.className == 'jsoneditor-expand') { + // skip expand button + prevButton = buttons[targetIndex - 2]; + } + if (!prevButton) { + // move to last button + prevButton = buttons[buttons.length - 1]; + } + if (prevButton) { + prevButton.focus(); + } + handled = true; + } + else if (keynum == 39) { // Arrow Right + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + nextButton.focus(); + } + handled = true; + } + else if (keynum == 40) { // Arrow Down + buttons = this._getVisibleButtons(); + targetIndex = buttons.indexOf(target); + nextButton = buttons[targetIndex + 1]; + if (nextButton && nextButton.className == 'jsoneditor-expand') { + // skip expand button + nextButton = buttons[targetIndex + 2]; + } + if (!nextButton) { + // move to first button + nextButton = buttons[0]; + } + if (nextButton) { + nextButton.focus(); + handled = true; + } + handled = true; + } + // TODO: arrow left and right + + if (handled) { + event.stopPropagation(); + event.preventDefault(); + } + }; + + /** + * Test if an element is a child of a parent element. + * @param {Element} child + * @param {Element} parent + * @return {boolean} isChild + */ + ContextMenu.prototype._isChildOf = function (child, parent) { + var e = child.parentNode; + while (e) { + if (e == parent) { + return true; + } + e = e.parentNode; + } + + return false; + }; + + module.exports = ContextMenu; + + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ContextMenu = __webpack_require__(57); + + /** + * Creates a component that visualize path selection in tree based editors + * @param {HTMLElement} container + * @constructor + */ + function TreePath(container) { + if (container) { + this.path = document.createElement('div'); + this.path.className = 'jsoneditor-treepath'; + container.appendChild(this.path); + this.reset(); + } + }; + + /** + * Reset component to initial status + */ + TreePath.prototype.reset = function () { + this.path.innerHTML = ''; + } + + /** + * Renders the component UI according to a given path objects + * @param {Array} pathObjs a list of path objects + * + */ + TreePath.prototype.setPath = function (pathObjs) { + var me = this; + this.reset(); + if (pathObjs && pathObjs.length) { + pathObjs.forEach(function (pathObj, idx) { + var pathEl = document.createElement('span'); + var sepEl; + pathEl.className = 'jsoneditor-treepath-element'; + pathEl.innerText = pathObj.name; + pathEl.onclick = _onSegmentClick.bind(me, pathObj); + + me.path.appendChild(pathEl); + + if (pathObj.children.length) { + sepEl = document.createElement('span'); + sepEl.className = 'jsoneditor-treepath-seperator'; + sepEl.innerHTML = '►'; + + sepEl.onclick = function () { + var items = []; + pathObj.children.forEach(function (child) { + items.push({ + 'text': child.name, + 'className': 'jsoneditor-type-modes' + (pathObjs[idx + 1] + 1 && pathObjs[idx + 1].name === child.name ? ' jsoneditor-selected' : ''), + 'click': _onContextMenuItemClick.bind(me, pathObj, child.name) + }); + }); + var menu = new ContextMenu(items); + menu.show(sepEl); + }; + + me.path.appendChild(sepEl, me.container); + } + + if(idx === pathObjs.length - 1) { + var leftRectPos = (sepEl || pathEl).getBoundingClientRect().left; + if(me.path.offsetWidth < leftRectPos) { + me.path.scrollLeft = leftRectPos; + } + } + }); + } + + function _onSegmentClick(pathObj) { + if (this.selectionCallback) { + this.selectionCallback(pathObj); + } + }; + + function _onContextMenuItemClick(pathObj, selection) { + if (this.contextMenuCallback) { + this.contextMenuCallback(pathObj, selection); + } + }; + }; + + /** + * set a callback function for selection of path section + * @param {Function} callback function to invoke when section is selected + */ + TreePath.prototype.onSectionSelected = function (callback) { + if (typeof callback === 'function') { + this.selectionCallback = callback; + } + }; + + /** + * set a callback function for selection of path section + * @param {Function} callback function to invoke when section is selected + */ + TreePath.prototype.onContextMenuItemSelected = function (callback) { + if (typeof callback === 'function') { + this.contextMenuCallback = callback; + } + }; + + module.exports = TreePath; + +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var naturalSort = __webpack_require__(60); + var ContextMenu = __webpack_require__(57); + var appendNodeFactory = __webpack_require__(61); + var util = __webpack_require__(54); + + /** + * @constructor Node + * Create a new Node + * @param {./treemode} editor + * @param {Object} [params] Can contain parameters: + * {string} field + * {boolean} fieldEditable + * {*} value + * {String} type Can have values 'auto', 'array', + * 'object', or 'string'. + */ + function Node (editor, params) { + /** @type {./treemode} */ + this.editor = editor; + this.dom = {}; + this.expanded = false; + + if(params && (params instanceof Object)) { + this.setField(params.field, params.fieldEditable); + this.setValue(params.value, params.type); + } + else { + this.setField(''); + this.setValue(null); + } + + this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + } + + // debounce interval for keyboard input in milliseconds + Node.prototype.DEBOUNCE_INTERVAL = 150; + + /** + * Determine whether the field and/or value of this node are editable + * @private + */ + Node.prototype._updateEditability = function () { + this.editable = { + field: true, + value: true + }; + + if (this.editor) { + this.editable.field = this.editor.options.mode === 'tree'; + this.editable.value = this.editor.options.mode !== 'view'; + + if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && + (typeof this.editor.options.onEditable === 'function')) { + var editable = this.editor.options.onEditable({ + field: this.field, + value: this.value, + path: this.getPath() + }); + + if (typeof editable === 'boolean') { + this.editable.field = editable; + this.editable.value = editable; + } + else { + if (typeof editable.field === 'boolean') this.editable.field = editable.field; + if (typeof editable.value === 'boolean') this.editable.value = editable.value; + } + } + } + }; + + /** + * Get the path of this node + * @return {String[]} Array containing the path to this node + */ + Node.prototype.getPath = function () { + var node = this; + var path = []; + while (node) { + var field = !node.parent + ? undefined // do not add an (optional) field name of the root node + : (node.parent.type != 'array') + ? node.field + : node.index; + + if (field !== undefined) { + path.unshift(field); + } + node = node.parent; + } + return path; + }; + + /** + * Find a Node from a JSON path like '.items[3].name' + * @param {string} jsonPath + * @return {Node | null} Returns the Node when found, returns null if not found + */ + Node.prototype.findNode = function (jsonPath) { + var path = util.parsePath(jsonPath); + var node = this; + while (node && path.length > 0) { + var prop = path.shift(); + if (typeof prop === 'number') { + if (node.type !== 'array') { + throw new Error('Cannot get child node at index ' + prop + ': node is no array'); + } + node = node.childs[prop]; + } + else { // string + if (node.type !== 'object') { + throw new Error('Cannot get child node ' + prop + ': node is no object'); + } + node = node.childs.filter(function (child) { + return child.field === prop; + })[0]; + } + } + + return node; + }; + + /** + * Find all parents of this node. The parents are ordered from root node towards + * the original node. + * @return {Array.} + */ + Node.prototype.findParents = function () { + var parents = []; + var parent = this.parent; + while (parent) { + parents.unshift(parent); + parent = parent.parent; + } + return parents; + }; + + /** + * + * @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error + * @param {Node} [child] When this is the error of a parent node, pointing + * to an invalid child node, the child node itself + * can be provided. If provided, clicking the error + * icon will set focus to the invalid child node. + */ + Node.prototype.setError = function (error, child) { + // ensure the dom exists + this.getDom(); + + this.error = error; + var tdError = this.dom.tdError; + if (error) { + if (!tdError) { + tdError = document.createElement('td'); + this.dom.tdError = tdError; + this.dom.tdValue.parentNode.appendChild(tdError); + } + + var popover = document.createElement('div'); + popover.className = 'jsoneditor-popover jsoneditor-right'; + popover.appendChild(document.createTextNode(error.message)); + + var button = document.createElement('button'); + button.type = 'button'; + button.className = 'jsoneditor-schema-error'; + button.appendChild(popover); + + // update the direction of the popover + button.onmouseover = button.onfocus = function updateDirection() { + var directions = ['right', 'above', 'below', 'left']; + for (var i = 0; i < directions.length; i++) { + var direction = directions[i]; + popover.className = 'jsoneditor-popover jsoneditor-' + direction; + + var contentRect = this.editor.content.getBoundingClientRect(); + var popoverRect = popover.getBoundingClientRect(); + var margin = 20; // account for a scroll bar + var fit = util.insideRect(contentRect, popoverRect, margin); + + if (fit) { + break; + } + } + }.bind(this); + + // when clicking the error icon, expand all nodes towards the invalid + // child node, and set focus to the child node + if (child) { + button.onclick = function showInvalidNode() { + child.findParents().forEach(function (parent) { + parent.expand(false); + }); + + child.scrollTo(function () { + child.focus(); + }); + }; + } + + // apply the error message to the node + while (tdError.firstChild) { + tdError.removeChild(tdError.firstChild); + } + tdError.appendChild(button); + } + else { + if (tdError) { + this.dom.tdError.parentNode.removeChild(this.dom.tdError); + delete this.dom.tdError; + } + } + }; + + /** + * Get the index of this node: the index in the list of childs where this + * node is part of + * @return {number} Returns the index, or -1 if this is the root node + */ + Node.prototype.getIndex = function () { + return this.parent ? this.parent.childs.indexOf(this) : -1; + }; + + /** + * Set parent node + * @param {Node} parent + */ + Node.prototype.setParent = function(parent) { + this.parent = parent; + }; + + /** + * Set field + * @param {String} field + * @param {boolean} [fieldEditable] + */ + Node.prototype.setField = function(field, fieldEditable) { + this.field = field; + this.previousField = field; + this.fieldEditable = (fieldEditable === true); + }; + + /** + * Get field + * @return {String} + */ + Node.prototype.getField = function() { + if (this.field === undefined) { + this._getDomField(); + } + + return this.field; + }; + + /** + * Set value. Value is a JSON structure or an element String, Boolean, etc. + * @param {*} value + * @param {String} [type] Specify the type of the value. Can be 'auto', + * 'array', 'object', or 'string' + */ + Node.prototype.setValue = function(value, type) { + var childValue, child; + + // first clear all current childs (if any) + var childs = this.childs; + if (childs) { + while (childs.length) { + this.removeChild(childs[0]); + } + } + + // TODO: remove the DOM of this Node + + this.type = this._getType(value); + + // check if type corresponds with the provided type + if (type && type != this.type) { + if (type == 'string' && this.type == 'auto') { + this.type = type; + } + else { + throw new Error('Type mismatch: ' + + 'cannot cast value of type "' + this.type + + ' to the specified type "' + type + '"'); + } + } + + if (this.type == 'array') { + // array + this.childs = []; + for (var i = 0, iMax = value.length; i < iMax; i++) { + childValue = value[i]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + value: childValue + }); + this.appendChild(child); + } + } + this.value = ''; + } + else if (this.type == 'object') { + // object + this.childs = []; + for (var childField in value) { + if (value.hasOwnProperty(childField)) { + childValue = value[childField]; + if (childValue !== undefined && !(childValue instanceof Function)) { + // ignore undefined and functions + child = new Node(this.editor, { + field: childField, + value: childValue + }); + this.appendChild(child); + } + } + } + this.value = ''; + + // sort object keys + if (this.editor.options.sortObjectKeys === true) { + this.sort('asc'); + } + } + else { + // value + this.childs = undefined; + this.value = value; + } + + this.previousValue = this.value; + }; + + /** + * Get value. Value is a JSON structure + * @return {*} value + */ + Node.prototype.getValue = function() { + //var childs, i, iMax; + + if (this.type == 'array') { + var arr = []; + this.childs.forEach (function (child) { + arr.push(child.getValue()); + }); + return arr; + } + else if (this.type == 'object') { + var obj = {}; + this.childs.forEach (function (child) { + obj[child.getField()] = child.getValue(); + }); + return obj; + } + else { + if (this.value === undefined) { + this._getDomValue(); + } + + return this.value; + } + }; + + /** + * Get the nesting level of this node + * @return {Number} level + */ + Node.prototype.getLevel = function() { + return (this.parent ? this.parent.getLevel() + 1 : 0); + }; + + /** + * Get jsonpath of the current node + * @return {Node[]} Returns an array with nodes + */ + Node.prototype.getNodePath = function () { + var path = this.parent ? this.parent.getNodePath() : []; + path.push(this); + return path; + }; + + /** + * Create a clone of a node + * The complete state of a clone is copied, including whether it is expanded or + * not. The DOM elements are not cloned. + * @return {Node} clone + */ + Node.prototype.clone = function() { + var clone = new Node(this.editor); + clone.type = this.type; + clone.field = this.field; + clone.fieldInnerText = this.fieldInnerText; + clone.fieldEditable = this.fieldEditable; + clone.value = this.value; + clone.valueInnerText = this.valueInnerText; + clone.expanded = this.expanded; + + if (this.childs) { + // an object or array + var cloneChilds = []; + this.childs.forEach(function (child) { + var childClone = child.clone(); + childClone.setParent(clone); + cloneChilds.push(childClone); + }); + clone.childs = cloneChilds; + } + else { + // a value + clone.childs = undefined; + } + + return clone; + }; + + /** + * Expand this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be expanded recursively + */ + Node.prototype.expand = function(recurse) { + if (!this.childs) { + return; + } + + // set this node expanded + this.expanded = true; + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-expanded'; + } + + this.showChilds(); + + if (recurse !== false) { + this.childs.forEach(function (child) { + child.expand(recurse); + }); + } + }; + + /** + * Collapse this node and optionally its childs. + * @param {boolean} [recurse] Optional recursion, true by default. When + * true, all childs will be collapsed recursively + */ + Node.prototype.collapse = function(recurse) { + if (!this.childs) { + return; + } + + this.hideChilds(); + + // collapse childs in case of recurse + if (recurse !== false) { + this.childs.forEach(function (child) { + child.collapse(recurse); + }); + + } + + // make this node collapsed + if (this.dom.expand) { + this.dom.expand.className = 'jsoneditor-collapsed'; + } + this.expanded = false; + }; + + /** + * Recursively show all childs when they are expanded + */ + Node.prototype.showChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + // show row with append button + var append = this.getAppend(); + var nextTr = tr.nextSibling; + if (nextTr) { + table.insertBefore(append, nextTr); + } + else { + table.appendChild(append); + } + + // show childs + this.childs.forEach(function (child) { + table.insertBefore(child.getDom(), append); + child.showChilds(); + }); + } + }; + + /** + * Hide the node with all its childs + */ + Node.prototype.hide = function() { + var tr = this.dom.tr; + var table = tr ? tr.parentNode : undefined; + if (table) { + table.removeChild(tr); + } + this.hideChilds(); + }; + + + /** + * Recursively hide all childs + */ + Node.prototype.hideChilds = function() { + var childs = this.childs; + if (!childs) { + return; + } + if (!this.expanded) { + return; + } + + // hide append row + var append = this.getAppend(); + if (append.parentNode) { + append.parentNode.removeChild(append); + } + + // hide childs + this.childs.forEach(function (child) { + child.hide(); + }); + }; + + + /** + * Goes through the path from the node to the root and ensures that it is expanded + */ + Node.prototype.expandTo = function() { + var currentNode = this.parent; + while (currentNode) { + if (!currentNode.expanded) { + currentNode.expand(); + } + currentNode = currentNode.parent; + } + }; + + + /** + * Add a new child to the node. + * Only applicable when Node value is of type array or object + * @param {Node} node + */ + Node.prototype.appendChild = function(node) { + if (this._hasChilds()) { + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + if (this.type == 'array') { + node.index = this.childs.length; + } + this.childs.push(node); + + if (this.expanded) { + // insert into the DOM, before the appendRow + var newTr = node.getDom(); + var appendTr = this.getAppend(); + var table = appendTr ? appendTr.parentNode : undefined; + if (appendTr && table) { + table.insertBefore(newTr, appendTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.moveBefore = function(node, beforeNode) { + if (this._hasChilds()) { + // create a temporary row, to prevent the scroll position from jumping + // when removing the node + var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; + if (tbody) { + var trTemp = document.createElement('tr'); + trTemp.style.height = tbody.clientHeight + 'px'; + tbody.appendChild(trTemp); + } + + if (node.parent) { + node.parent.removeChild(node); + } + + if (beforeNode instanceof AppendNode) { + this.appendChild(node); + } + else { + this.insertBefore(node, beforeNode); + } + + if (tbody) { + tbody.removeChild(trTemp); + } + } + }; + + /** + * Move a node from its current parent to this node + * Only applicable when Node value is of type array or object. + * If index is out of range, the node will be appended to the end + * @param {Node} node + * @param {Number} index + */ + Node.prototype.moveTo = function (node, index) { + if (node.parent == this) { + // same parent + var currentIndex = this.childs.indexOf(node); + if (currentIndex < index) { + // compensate the index for removal of the node itself + index++; + } + } + + var beforeNode = this.childs[index] || this.append; + this.moveBefore(node, beforeNode); + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} beforeNode + */ + Node.prototype.insertBefore = function(node, beforeNode) { + if (this._hasChilds()) { + if (beforeNode == this.append) { + // append to the child nodes + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.push(node); + } + else { + // insert before a child node + var index = this.childs.indexOf(beforeNode); + if (index == -1) { + throw new Error('Node not found'); + } + + // adjust the link to the parent + node.setParent(this); + node.fieldEditable = (this.type == 'object'); + this.childs.splice(index, 0, node); + } + + if (this.expanded) { + // insert into the DOM + var newTr = node.getDom(); + var nextTr = beforeNode.getDom(); + var table = nextTr ? nextTr.parentNode : undefined; + if (nextTr && table) { + table.insertBefore(newTr, nextTr); + } + + node.showChilds(); + } + + this.updateDom({'updateIndexes': true}); + node.updateDom({'recurse': true}); + } + }; + + /** + * Insert a new child before a given node + * Only applicable when Node value is of type array or object + * @param {Node} node + * @param {Node} afterNode + */ + Node.prototype.insertAfter = function(node, afterNode) { + if (this._hasChilds()) { + var index = this.childs.indexOf(afterNode); + var beforeNode = this.childs[index + 1]; + if (beforeNode) { + this.insertBefore(node, beforeNode); + } + else { + this.appendChild(node); + } + } + }; + + /** + * Search in this node + * The node will be expanded when the text is found one of its childs, else + * it will be collapsed. Searches are case insensitive. + * @param {String} text + * @return {Node[]} results Array with nodes containing the search text + */ + Node.prototype.search = function(text) { + var results = []; + var index; + var search = text ? text.toLowerCase() : undefined; + + // delete old search data + delete this.searchField; + delete this.searchValue; + + // search in field + if (this.field != undefined) { + var field = String(this.field).toLowerCase(); + index = field.indexOf(search); + if (index != -1) { + this.searchField = true; + results.push({ + 'node': this, + 'elem': 'field' + }); + } + + // update dom + this._updateDomField(); + } + + // search in value + if (this._hasChilds()) { + // array, object + + // search the nodes childs + if (this.childs) { + var childResults = []; + this.childs.forEach(function (child) { + childResults = childResults.concat(child.search(text)); + }); + results = results.concat(childResults); + } + + // update dom + if (search != undefined) { + var recurse = false; + if (childResults.length == 0) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + } + } + else { + // string, auto + if (this.value != undefined ) { + var value = String(this.value).toLowerCase(); + index = value.indexOf(search); + if (index != -1) { + this.searchValue = true; + results.push({ + 'node': this, + 'elem': 'value' + }); + } + } + + // update dom + this._updateDomValue(); + } + + return results; + }; + + /** + * Move the scroll position such that this node is in the visible area. + * The node will not get the focus + * @param {function(boolean)} [callback] + */ + Node.prototype.scrollTo = function(callback) { + if (!this.dom.tr || !this.dom.tr.parentNode) { + // if the node is not visible, expand its parents + var parent = this.parent; + var recurse = false; + while (parent) { + parent.expand(recurse); + parent = parent.parent; + } + } + + if (this.dom.tr && this.dom.tr.parentNode) { + this.editor.scrollTo(this.dom.tr.offsetTop, callback); + } + }; + + + // stores the element name currently having the focus + Node.focusElement = undefined; + + /** + * Set focus to this node + * @param {String} [elementName] The field name of the element to get the + * focus available values: 'drag', 'menu', + * 'expand', 'field', 'value' (default) + */ + Node.prototype.focus = function(elementName) { + Node.focusElement = elementName; + + if (this.dom.tr && this.dom.tr.parentNode) { + var dom = this.dom; + + switch (elementName) { + case 'drag': + if (dom.drag) { + dom.drag.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'menu': + dom.menu.focus(); + break; + + case 'expand': + if (this._hasChilds()) { + dom.expand.focus(); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else { + dom.menu.focus(); + } + break; + + case 'field': + if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + + case 'value': + default: + if (dom.select) { + // enum select box + dom.select.focus(); + } + else if (dom.value && !this._hasChilds()) { + dom.value.focus(); + util.selectContentEditable(dom.value); + } + else if (dom.field && this.fieldEditable) { + dom.field.focus(); + util.selectContentEditable(dom.field); + } + else if (this._hasChilds()) { + dom.expand.focus(); + } + else { + dom.menu.focus(); + } + break; + } + } + }; + + /** + * Select all text in an editable div after a delay of 0 ms + * @param {Element} editableDiv + */ + Node.select = function(editableDiv) { + setTimeout(function () { + util.selectContentEditable(editableDiv); + }, 0); + }; + + /** + * Update the values from the DOM field and value of this node + */ + Node.prototype.blur = function() { + // retrieve the actual field and value from the DOM. + this._getDomValue(false); + this._getDomField(false); + }; + + /** + * Check if given node is a child. The method will check recursively to find + * this node. + * @param {Node} node + * @return {boolean} containsNode + */ + Node.prototype.containsNode = function(node) { + if (this == node) { + return true; + } + + var childs = this.childs; + if (childs) { + // TODO: use the js5 Array.some() here? + for (var i = 0, iMax = childs.length; i < iMax; i++) { + if (childs[i].containsNode(node)) { + return true; + } + } + } + + return false; + }; + + /** + * Move given node into this node + * @param {Node} node the childNode to be moved + * @param {Node} beforeNode node will be inserted before given + * node. If no beforeNode is given, + * the node is appended at the end + * @private + */ + Node.prototype._move = function(node, beforeNode) { + if (node == beforeNode) { + // nothing to do... + return; + } + + // check if this node is not a child of the node to be moved here + if (node.containsNode(this)) { + throw new Error('Cannot move a field into a child of itself'); + } + + // remove the original node + if (node.parent) { + node.parent.removeChild(node); + } + + // create a clone of the node + var clone = node.clone(); + node.clearDom(); + + // insert or append the node + if (beforeNode) { + this.insertBefore(clone, beforeNode); + } + else { + this.appendChild(clone); + } + + /* TODO: adjust the field name (to prevent equal field names) + if (this.type == 'object') { + } + */ + }; + + /** + * Remove a child from the node. + * Only applicable when Node value is of type array or object + * @param {Node} node The child node to be removed; + * @return {Node | undefined} node The removed node on success, + * else undefined + */ + Node.prototype.removeChild = function(node) { + if (this.childs) { + var index = this.childs.indexOf(node); + + if (index != -1) { + node.hide(); + + // delete old search results + delete node.searchField; + delete node.searchValue; + + var removedNode = this.childs.splice(index, 1)[0]; + removedNode.parent = null; + + this.updateDom({'updateIndexes': true}); + + return removedNode; + } + } + + return undefined; + }; + + /** + * Remove a child node node from this node + * This method is equal to Node.removeChild, except that _remove fire an + * onChange event. + * @param {Node} node + * @private + */ + Node.prototype._remove = function (node) { + this.removeChild(node); + }; + + /** + * Change the type of the value of this Node + * @param {String} newType + */ + Node.prototype.changeType = function (newType) { + var oldType = this.type; + + if (oldType == newType) { + // type is not changed + return; + } + + if ((newType == 'string' || newType == 'auto') && + (oldType == 'string' || oldType == 'auto')) { + // this is an easy change + this.type = newType; + } + else { + // change from array to object, or from string/auto to object/array + var table = this.dom.tr ? this.dom.tr.parentNode : undefined; + var lastTr; + if (this.expanded) { + lastTr = this.getAppend(); + } + else { + lastTr = this.getDom(); + } + var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; + + // hide current field and all its childs + this.hide(); + this.clearDom(); + + // adjust the field and the value + this.type = newType; + + // adjust childs + if (newType == 'object') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + delete child.index; + child.fieldEditable = true; + if (child.field == undefined) { + child.field = ''; + } + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else if (newType == 'array') { + if (!this.childs) { + this.childs = []; + } + + this.childs.forEach(function (child, index) { + child.clearDom(); + child.fieldEditable = false; + child.index = index; + }); + + if (oldType == 'string' || oldType == 'auto') { + this.expanded = true; + } + } + else { + this.expanded = false; + } + + // create new DOM + if (table) { + if (nextTr) { + table.insertBefore(this.getDom(), nextTr); + } + else { + table.appendChild(this.getDom()); + } + } + this.showChilds(); + } + + if (newType == 'auto' || newType == 'string') { + // cast value to the correct type + if (newType == 'string') { + this.value = String(this.value); + } + else { + this.value = this._stringCast(String(this.value)); + } + + this.focus(); + } + + this.updateDom({'updateIndexes': true}); + }; + + /** + * Retrieve value from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomValue = function(silent) { + if (this.dom.value && this.type != 'array' && this.type != 'object') { + this.valueInnerText = util.getInnerText(this.dom.value); + } + + if (this.valueInnerText != undefined) { + try { + // retrieve the value + var value; + if (this.type == 'string') { + value = this._unescapeHTML(this.valueInnerText); + } + else { + var str = this._unescapeHTML(this.valueInnerText); + value = this._stringCast(str); + } + if (value !== this.value) { + this.value = value; + this._debouncedOnChangeValue(); + } + } + catch (err) { + this.value = undefined; + // TODO: sent an action with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Handle a changed value + * @private + */ + Node.prototype._onChangeValue = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editValue', { + node: this, + oldValue: this.previousValue, + newValue: this.value, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousValue = this.value; + }; + + /** + * Handle a changed field + * @private + */ + Node.prototype._onChangeField = function () { + // get current selection, then override the range such that we can select + // the added/removed text on undo/redo + var oldSelection = this.editor.getSelection(); + if (oldSelection.range) { + var undoDiff = util.textDiff(this.field, this.previousField); + oldSelection.range.startOffset = undoDiff.start; + oldSelection.range.endOffset = undoDiff.end; + } + var newSelection = this.editor.getSelection(); + if (newSelection.range) { + var redoDiff = util.textDiff(this.previousField, this.field); + newSelection.range.startOffset = redoDiff.start; + newSelection.range.endOffset = redoDiff.end; + } + + this.editor._onAction('editField', { + node: this, + oldValue: this.previousField, + newValue: this.field, + oldSelection: oldSelection, + newSelection: newSelection + }); + + this.previousField = this.field; + }; + + /** + * Update dom value: + * - the text color of the value, depending on the type of the value + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomValue = function () { + var domValue = this.dom.value; + if (domValue) { + var classNames = ['jsoneditor-value']; + + + // set text color depending on value type + var value = this.value; + var type = (this.type == 'auto') ? util.type(value) : this.type; + var isUrl = type == 'string' && util.isUrl(value); + classNames.push('jsoneditor-' + type); + if (isUrl) { + classNames.push('jsoneditor-url'); + } + + // visual styling when empty + var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); + if (isEmpty) { + classNames.push('jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchValueActive) { + classNames.push('jsoneditor-highlight-active'); + } + if (this.searchValue) { + classNames.push('jsoneditor-highlight'); + } + + domValue.className = classNames.join(' '); + + // update title + if (type == 'array' || type == 'object') { + var count = this.childs ? this.childs.length : 0; + domValue.title = this.type + ' containing ' + count + ' items'; + } + else if (isUrl && this.editable.value) { + domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; + } + else { + domValue.title = ''; + } + + // show checkbox when the value is a boolean + if (type === 'boolean' && this.editable.value) { + if (!this.dom.checkbox) { + this.dom.checkbox = document.createElement('input'); + this.dom.checkbox.type = 'checkbox'; + this.dom.tdCheckbox = document.createElement('td'); + this.dom.tdCheckbox.className = 'jsoneditor-tree'; + this.dom.tdCheckbox.appendChild(this.dom.checkbox); + + this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); + } + + this.dom.checkbox.checked = this.value; + } + else { + // cleanup checkbox when displayed + if (this.dom.tdCheckbox) { + this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); + delete this.dom.tdCheckbox; + delete this.dom.checkbox; + } + } + + if (this.enum && this.editable.value) { + // create select box when this node has an enum object + if (!this.dom.select) { + this.dom.select = document.createElement('select'); + this.id = this.field + "_" + new Date().getUTCMilliseconds(); + this.dom.select.id = this.id; + this.dom.select.name = this.dom.select.id; + + //Create the default empty option + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = ''; + this.dom.select.option.innerHTML = '--'; + this.dom.select.appendChild(this.dom.select.option); + + //Iterate all enum values and add them as options + for(var i = 0; i < this.enum.length; i++) { + this.dom.select.option = document.createElement('option'); + this.dom.select.option.value = this.enum[i]; + this.dom.select.option.innerHTML = this.enum[i]; + if(this.dom.select.option.value == this.value){ + this.dom.select.option.selected = true; + } + this.dom.select.appendChild(this.dom.select.option); + } + + this.dom.tdSelect = document.createElement('td'); + this.dom.tdSelect.className = 'jsoneditor-tree'; + this.dom.tdSelect.appendChild(this.dom.select); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); + } + + // If the enum is inside a composite type display + // both the simple input and the dropdown field + if(this.schema && ( + !this.schema.hasOwnProperty("oneOf") && + !this.schema.hasOwnProperty("anyOf") && + !this.schema.hasOwnProperty("allOf")) + ) { + this.valueFieldHTML = this.dom.tdValue.innerHTML; + this.dom.tdValue.style.visibility = 'hidden'; + this.dom.tdValue.innerHTML = ''; + } else { + delete this.valueFieldHTML; + } + } + else { + // cleanup select box when displayed + if (this.dom.tdSelect) { + this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); + delete this.dom.tdSelect; + delete this.dom.select; + this.dom.tdValue.innerHTML = this.valueFieldHTML; + this.dom.tdValue.style.visibility = ''; + delete this.valueFieldHTML; + } + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domValue); + } + }; + + /** + * Update dom field: + * - the text color of the field, depending on the text + * - the height of the field, depending on the width + * - background color in case it is empty + * @private + */ + Node.prototype._updateDomField = function () { + var domField = this.dom.field; + if (domField) { + // make backgound color lightgray when empty + var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); + if (isEmpty) { + util.addClassName(domField, 'jsoneditor-empty'); + } + else { + util.removeClassName(domField, 'jsoneditor-empty'); + } + + // highlight when there is a search result + if (this.searchFieldActive) { + util.addClassName(domField, 'jsoneditor-highlight-active'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight-active'); + } + if (this.searchField) { + util.addClassName(domField, 'jsoneditor-highlight'); + } + else { + util.removeClassName(domField, 'jsoneditor-highlight'); + } + + // strip formatting from the contents of the editable div + util.stripFormatting(domField); + } + }; + + /** + * Retrieve field from DOM + * @param {boolean} [silent] If true (default), no errors will be thrown in + * case of invalid data + * @private + */ + Node.prototype._getDomField = function(silent) { + if (this.dom.field && this.fieldEditable) { + this.fieldInnerText = util.getInnerText(this.dom.field); + } + + if (this.fieldInnerText != undefined) { + try { + var field = this._unescapeHTML(this.fieldInnerText); + + if (field !== this.field) { + this.field = field; + this._debouncedOnChangeField(); + } + } + catch (err) { + this.field = undefined; + // TODO: sent an action here, with the new, invalid value? + if (silent !== true) { + throw err; + } + } + } + }; + + /** + * Validate this node and all it's childs + * @return {Array.<{node: Node, error: {message: string}}>} Returns a list with duplicates + */ + Node.prototype.validate = function () { + var errors = []; + + // find duplicate keys + if (this.type === 'object') { + var keys = {}; + var duplicateKeys = []; + for (var i = 0; i < this.childs.length; i++) { + var child = this.childs[i]; + if (keys.hasOwnProperty(child.field)) { + duplicateKeys.push(child.field); + } + keys[child.field] = true; + } + + if (duplicateKeys.length > 0) { + errors = this.childs + .filter(function (node) { + return duplicateKeys.indexOf(node.field) !== -1; + }) + .map(function (node) { + return { + node: node, + error: { + message: 'duplicate key "' + node.field + '"' + } + } + }); + } + } + + // recurse over the childs + if (this.childs) { + for (var i = 0; i < this.childs.length; i++) { + var e = this.childs[i].validate(); + if (e.length > 0) { + errors = errors.concat(e); + } + } + } + + return errors; + }; + + /** + * Clear the dom of the node + */ + Node.prototype.clearDom = function() { + // TODO: hide the node first? + //this.hide(); + // TODO: recursively clear dom? + + this.dom = {}; + }; + + /** + * Get the HTML DOM TR element of the node. + * The dom will be generated when not yet created + * @return {Element} tr HTML DOM TR Element + */ + Node.prototype.getDom = function() { + var dom = this.dom; + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // create row + dom.tr = document.createElement('tr'); + dom.tr.node = this; + + if (this.editor.options.mode === 'tree') { // note: we take here the global setting + var tdDrag = document.createElement('td'); + if (this.editable.field) { + // create draggable area + if (this.parent) { + var domDrag = document.createElement('button'); + domDrag.type = 'button'; + dom.drag = domDrag; + domDrag.className = 'jsoneditor-dragarea'; + domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; + tdDrag.appendChild(domDrag); + } + } + dom.tr.appendChild(tdDrag); + + // create context menu + var tdMenu = document.createElement('td'); + var menu = document.createElement('button'); + menu.type = 'button'; + dom.menu = menu; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + tdMenu.appendChild(dom.menu); + dom.tr.appendChild(tdMenu); + } + + // create tree and field + var tdField = document.createElement('td'); + dom.tr.appendChild(tdField); + dom.tree = this._createDomTree(); + tdField.appendChild(dom.tree); + + this.updateDom({'updateIndexes': true}); + + return dom.tr; + }; + + /** + * DragStart event, fired on mousedown on the dragarea at the left side of a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragStart = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDragStart([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var lastNode = nodes[nodes.length - 1]; + var draggedNode = Node.getNodeFromTarget(event.target); + var beforeNode = lastNode._nextSibling(); + var editor = firstNode.editor; + + // in case of multiple selected nodes, offsetY prevents the selection from + // jumping when you start dragging one of the lower down nodes in the selection + var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); + + if (!editor.mousemove) { + editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { + Node.onDrag(nodes, event); + }); + } + + if (!editor.mouseup) { + editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { + Node.onDragEnd(nodes, event); + }); + } + + editor.highlighter.lock(); + editor.drag = { + oldCursor: document.body.style.cursor, + oldSelection: editor.getSelection(), + oldBeforeNode: beforeNode, + mouseX: event.pageX, + offsetY: offsetY, + level: firstNode.getLevel() + }; + document.body.style.cursor = 'move'; + + event.preventDefault(); + }; + + /** + * Drag event, fired when moving the mouse while dragging a Node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDrag = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + // TODO: this method has grown too large. Split it in a number of methods + var editor = nodes[0].editor; + var mouseY = event.pageY - editor.drag.offsetY; + var mouseX = event.pageX; + var trThis, trPrev, trNext, trFirst, trLast, trRoot; + var nodePrev, nodeNext; + var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; + var moved = false; + + // TODO: add an ESC option, which resets to the original position + + // move up/down + var firstNode = nodes[0]; + trThis = firstNode.dom.tr; + topThis = util.getAbsoluteTop(trThis); + heightThis = trThis.offsetHeight; + if (mouseY < topThis) { + // move up + trPrev = trThis; + do { + trPrev = trPrev.previousSibling; + nodePrev = Node.getNodeFromTarget(trPrev); + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + } + while (trPrev && mouseY < topPrev); + + if (nodePrev && !nodePrev.parent) { + nodePrev = undefined; + } + + if (!nodePrev) { + // move to the first node + trRoot = trThis.parentNode.firstChild; + trPrev = trRoot ? trRoot.nextSibling : undefined; + nodePrev = Node.getNodeFromTarget(trPrev); + if (nodePrev == firstNode) { + nodePrev = undefined; + } + } + + if (nodePrev) { + // check if mouseY is really inside the found node + trPrev = nodePrev.dom.tr; + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + if (mouseY > topPrev + heightThis) { + nodePrev = undefined; + } + } + + if (nodePrev) { + nodes.forEach(function (node) { + nodePrev.parent.moveBefore(node, nodePrev); + }); + moved = true; + } + } + else { + // move down + var lastNode = nodes[nodes.length - 1]; + trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; + trFirst = trLast ? trLast.nextSibling : undefined; + if (trFirst) { + topFirst = util.getAbsoluteTop(trFirst); + trNext = trFirst; + do { + nodeNext = Node.getNodeFromTarget(trNext); + if (trNext) { + bottomNext = trNext.nextSibling ? + util.getAbsoluteTop(trNext.nextSibling) : 0; + heightNext = trNext ? (bottomNext - topFirst) : 0; + + if (nodeNext.parent.childs.length == nodes.length && + nodeNext.parent.childs[nodes.length - 1] == lastNode) { + // We are about to remove the last child of this parent, + // which will make the parents appendNode visible. + topThis += 27; + // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. + } + } + + trNext = trNext.nextSibling; + } + while (trNext && mouseY > topThis + heightNext); + + if (nodeNext && nodeNext.parent) { + // calculate the desired level + var diffX = (mouseX - editor.drag.mouseX); + var diffLevel = Math.round(diffX / 24 / 2); + var level = editor.drag.level + diffLevel; // desired level + var levelNext = nodeNext.getLevel(); // level to be + + // find the best fitting level (move upwards over the append nodes) + trPrev = nodeNext.dom.tr.previousSibling; + while (levelNext < level && trPrev) { + nodePrev = Node.getNodeFromTarget(trPrev); + + var isDraggedNode = nodes.some(function (node) { + return node === nodePrev || nodePrev._isChildOf(node); + }); + + if (isDraggedNode) { + // neglect the dragged nodes themselves and their childs + } + else if (nodePrev instanceof AppendNode) { + var childs = nodePrev.parent.childs; + if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { + // non-visible append node of a list of childs + // consisting of not only this node (else the + // append node will change into a visible "empty" + // text when removing this node). + nodeNext = Node.getNodeFromTarget(trPrev); + levelNext = nodeNext.getLevel(); + } + else { + break; + } + } + else { + break; + } + + trPrev = trPrev.previousSibling; + } + + // move the node when its position is changed + if (trLast.nextSibling != nodeNext.dom.tr) { + nodes.forEach(function (node) { + nodeNext.parent.moveBefore(node, nodeNext); + }); + moved = true; + } + } + } + } + + if (moved) { + // update the dragging parameters when moved + editor.drag.mouseX = mouseX; + editor.drag.level = firstNode.getLevel(); + } + + // auto scroll when hovering around the top of the editor + editor.startAutoScroll(mouseY); + + event.preventDefault(); + }; + + /** + * Drag event, fired on mouseup after having dragged a node + * @param {Node[] | Node} nodes + * @param {Event} event + */ + Node.onDragEnd = function (nodes, event) { + if (!Array.isArray(nodes)) { + return Node.onDrag([nodes], event); + } + if (nodes.length === 0) { + return; + } + + var firstNode = nodes[0]; + var editor = firstNode.editor; + var parent = firstNode.parent; + var firstIndex = parent.childs.indexOf(firstNode); + var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append; + + // set focus to the context menu button of the first node + if (nodes[0]) { + nodes[0].dom.menu.focus(); + } + + var params = { + nodes: nodes, + oldSelection: editor.drag.oldSelection, + newSelection: editor.getSelection(), + oldBeforeNode: editor.drag.oldBeforeNode, + newBeforeNode: beforeNode + }; + + if (params.oldBeforeNode != params.newBeforeNode) { + // only register this action if the node is actually moved to another place + editor._onAction('moveNodes', params); + } + + document.body.style.cursor = editor.drag.oldCursor; + editor.highlighter.unlock(); + nodes.forEach(function (node) { + if (event.target !== node.dom.drag && event.target !== node.dom.menu) { + editor.highlighter.unhighlight(); + } + }); + delete editor.drag; + + if (editor.mousemove) { + util.removeEventListener(window, 'mousemove', editor.mousemove); + delete editor.mousemove; + } + if (editor.mouseup) { + util.removeEventListener(window, 'mouseup', editor.mouseup); + delete editor.mouseup; + } + + // Stop any running auto scroll + editor.stopAutoScroll(); + + event.preventDefault(); + }; + + /** + * Test if this node is a child of an other node + * @param {Node} node + * @return {boolean} isChild + * @private + */ + Node.prototype._isChildOf = function (node) { + var n = this.parent; + while (n) { + if (n == node) { + return true; + } + n = n.parent; + } + + return false; + }; + + /** + * Create an editable field + * @return {Element} domField + * @private + */ + Node.prototype._createDomField = function () { + return document.createElement('div'); + }; + + /** + * Set highlighting for this node and all its childs. + * Only applied to the currently visible (expanded childs) + * @param {boolean} highlight + */ + Node.prototype.setHighlight = function (highlight) { + if (this.dom.tr) { + if (highlight) { + util.addClassName(this.dom.tr, 'jsoneditor-highlight'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); + } + + if (this.append) { + this.append.setHighlight(highlight); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setHighlight(highlight); + }); + } + } + }; + + /** + * Select or deselect a node + * @param {boolean} selected + * @param {boolean} [isFirst] + */ + Node.prototype.setSelected = function (selected, isFirst) { + this.selected = selected; + + if (this.dom.tr) { + if (selected) { + util.addClassName(this.dom.tr, 'jsoneditor-selected'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-selected'); + } + + if (isFirst) { + util.addClassName(this.dom.tr, 'jsoneditor-first'); + } + else { + util.removeClassName(this.dom.tr, 'jsoneditor-first'); + } + + if (this.append) { + this.append.setSelected(selected); + } + + if (this.childs) { + this.childs.forEach(function (child) { + child.setSelected(selected); + }); + } + } + }; + + /** + * Update the value of the node. Only primitive types are allowed, no Object + * or Array is allowed. + * @param {String | Number | Boolean | null} value + */ + Node.prototype.updateValue = function (value) { + this.value = value; + this.updateDom(); + }; + + /** + * Update the field of the node. + * @param {String} field + */ + Node.prototype.updateField = function (field) { + this.field = field; + this.updateDom(); + }; + + /** + * Update the HTML DOM, optionally recursing through the childs + * @param {Object} [options] Available parameters: + * {boolean} [recurse] If true, the + * DOM of the childs will be updated recursively. + * False by default. + * {boolean} [updateIndexes] If true, the childs + * indexes of the node will be updated too. False by + * default. + */ + Node.prototype.updateDom = function (options) { + // update level indentation + var domTree = this.dom.tree; + if (domTree) { + domTree.style.marginLeft = this.getLevel() * 24 + 'px'; + } + + // apply field to DOM + var domField = this.dom.field; + if (domField) { + if (this.fieldEditable) { + // parent is an object + domField.contentEditable = this.editable.field; + domField.spellcheck = false; + domField.className = 'jsoneditor-field'; + } + else { + // parent is an array this is the root node + domField.className = 'jsoneditor-readonly'; + } + + var fieldText; + if (this.index != undefined) { + fieldText = this.index; + } + else if (this.field != undefined) { + fieldText = this.field; + } + else if (this._hasChilds()) { + fieldText = this.type; + } + else { + fieldText = ''; + } + domField.innerHTML = this._escapeHTML(fieldText); + + this._updateSchema(); + } + + // apply value to DOM + var domValue = this.dom.value; + if (domValue) { + var count = this.childs ? this.childs.length : 0; + if (this.type == 'array') { + domValue.innerHTML = '[' + count + ']'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else if (this.type == 'object') { + domValue.innerHTML = '{' + count + '}'; + util.addClassName(this.dom.tr, 'jsoneditor-expandable'); + } + else { + domValue.innerHTML = this._escapeHTML(this.value); + util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); + } + } + + // update field and value + this._updateDomField(); + this._updateDomValue(); + + // update childs indexes + if (options && options.updateIndexes === true) { + // updateIndexes is true or undefined + this._updateDomIndexes(); + } + + if (options && options.recurse === true) { + // recurse is true or undefined. update childs recursively + if (this.childs) { + this.childs.forEach(function (child) { + child.updateDom(options); + }); + } + } + + // update row with append button + if (this.append) { + this.append.updateDom(); + } + }; + + /** + * Locate the JSON schema of the node and check for any enum type + * @private + */ + Node.prototype._updateSchema = function () { + //Locating the schema of the node and checking for any enum type + if(this.editor && this.editor.options) { + // find the part of the json schema matching this nodes path + this.schema = this.editor.options.schema + ? Node._findSchema(this.editor.options.schema, this.getPath()) + : null; + if (this.schema) { + this.enum = Node._findEnum(this.schema); + } + else { + delete this.enum; + } + } + }; + + /** + * find an enum definition in a JSON schema, as property `enum` or inside + * one of the schemas composites (`oneOf`, `anyOf`, `allOf`) + * @param {Object} schema + * @return {Array | null} Returns the enum when found, null otherwise. + * @private + */ + Node._findEnum = function (schema) { + if (schema.enum) { + return schema.enum; + } + + var composite = schema.oneOf || schema.anyOf || schema.allOf; + if (composite) { + var match = composite.filter(function (entry) {return entry.enum}); + if (match.length > 0) { + return match[0].enum; + } + } + + return null + }; + + /** + * Return the part of a JSON schema matching given path. + * @param {Object} schema + * @param {Array.} path + * @return {Object | null} + * @private + */ + Node._findSchema = function (schema, path) { + var childSchema = schema; + var foundSchema = childSchema; + + var allSchemas = schema.oneOf || schema.anyOf || schema.allOf; + if (!allSchemas) { + allSchemas = [schema]; + } + + for (var j = 0; j < allSchemas.length; j++) { + childSchema = allSchemas[j]; + + for (var i = 0; i < path.length && childSchema; i++) { + var key = path[i]; + + if (typeof key === 'string' && childSchema.patternProperties && i == path.length - 1) { + for (var prop in childSchema.patternProperties) { + foundSchema = Node._findSchema(childSchema.patternProperties[prop], path.slice(i, path.length)); + } + } + else if (childSchema.items && childSchema.items.properties) { + childSchema = childSchema.items.properties[key]; + if (childSchema) { + foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); + } + } + else if (typeof key === 'string' && childSchema.properties) { + childSchema = childSchema.properties[key] || null; + if (childSchema) { + foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); + } + } + else if (typeof key === 'number' && childSchema.items) { + childSchema = childSchema.items; + if (childSchema) { + foundSchema = Node._findSchema(childSchema, path.slice(i, path.length)); + } + } + } + + } + return foundSchema + }; + + /** + * Update the DOM of the childs of a node: update indexes and undefined field + * names. + * Only applicable when structure is an array or object + * @private + */ + Node.prototype._updateDomIndexes = function () { + var domValue = this.dom.value; + var childs = this.childs; + if (domValue && childs) { + if (this.type == 'array') { + childs.forEach(function (child, index) { + child.index = index; + var childField = child.dom.field; + if (childField) { + childField.innerHTML = index; + } + }); + } + else if (this.type == 'object') { + childs.forEach(function (child) { + if (child.index != undefined) { + delete child.index; + + if (child.field == undefined) { + child.field = ''; + } + } + }); + } + } + }; + + /** + * Create an editable value + * @private + */ + Node.prototype._createDomValue = function () { + var domValue; + + if (this.type == 'array') { + domValue = document.createElement('div'); + domValue.innerHTML = '[...]'; + } + else if (this.type == 'object') { + domValue = document.createElement('div'); + domValue.innerHTML = '{...}'; + } + else { + if (!this.editable.value && util.isUrl(this.value)) { + // create a link in case of read-only editor and value containing an url + domValue = document.createElement('a'); + domValue.href = this.value; + domValue.target = '_blank'; + domValue.innerHTML = this._escapeHTML(this.value); + } + else { + // create an editable or read-only div + domValue = document.createElement('div'); + domValue.contentEditable = this.editable.value; + domValue.spellcheck = false; + domValue.innerHTML = this._escapeHTML(this.value); + } + } + + return domValue; + }; + + /** + * Create an expand/collapse button + * @return {Element} expand + * @private + */ + Node.prototype._createDomExpandButton = function () { + // create expand button + var expand = document.createElement('button'); + expand.type = 'button'; + if (this._hasChilds()) { + expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed'; + expand.title = + 'Click to expand/collapse this field (Ctrl+E). \n' + + 'Ctrl+Click to expand/collapse including all childs.'; + } + else { + expand.className = 'jsoneditor-invisible'; + expand.title = ''; + } + + return expand; + }; + + + /** + * Create a DOM tree element, containing the expand/collapse button + * @return {Element} domTree + * @private + */ + Node.prototype._createDomTree = function () { + var dom = this.dom; + var domTree = document.createElement('table'); + var tbody = document.createElement('tbody'); + domTree.style.borderCollapse = 'collapse'; // TODO: put in css + domTree.className = 'jsoneditor-values'; + domTree.appendChild(tbody); + var tr = document.createElement('tr'); + tbody.appendChild(tr); + + // create expand button + var tdExpand = document.createElement('td'); + tdExpand.className = 'jsoneditor-tree'; + tr.appendChild(tdExpand); + dom.expand = this._createDomExpandButton(); + tdExpand.appendChild(dom.expand); + dom.tdExpand = tdExpand; + + // create the field + var tdField = document.createElement('td'); + tdField.className = 'jsoneditor-tree'; + tr.appendChild(tdField); + dom.field = this._createDomField(); + tdField.appendChild(dom.field); + dom.tdField = tdField; + + // create a separator + var tdSeparator = document.createElement('td'); + tdSeparator.className = 'jsoneditor-tree'; + tr.appendChild(tdSeparator); + if (this.type != 'object' && this.type != 'array') { + tdSeparator.appendChild(document.createTextNode(':')); + tdSeparator.className = 'jsoneditor-separator'; + } + dom.tdSeparator = tdSeparator; + + // create the value + var tdValue = document.createElement('td'); + tdValue.className = 'jsoneditor-tree'; + tr.appendChild(tdValue); + dom.value = this._createDomValue(); + tdValue.appendChild(dom.value); + dom.tdValue = tdValue; + + return domTree; + }; + + /** + * Handle an event. The event is caught centrally by the editor + * @param {Event} event + */ + Node.prototype.onEvent = function (event) { + var type = event.type, + target = event.target || event.srcElement, + dom = this.dom, + node = this, + expandable = this._hasChilds(); + + // check if mouse is on menu or on dragarea. + // If so, highlight current row and its childs + if (target == dom.drag || target == dom.menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = node.editor.highlighter; + highlighter.highlight(node); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + // expand events + if (type == 'click') { + if (target == dom.expand || + ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + } + } + } + + // swap the value of a boolean when the checkbox displayed left is clicked + if (type == 'change' && target == dom.checkbox) { + this.dom.value.innerHTML = !this.value; + this._getDomValue(); + } + + // update the value of the node based on the selected option + if (type == 'change' && target == dom.select) { + this.dom.value.innerHTML = dom.select.value; + this._getDomValue(); + this._updateDomValue(); + } + + // value events + var domValue = dom.value; + if (target == domValue) { + //noinspection FallthroughInSwitchStatementJS + switch (type) { + case 'blur': + case 'change': + this._getDomValue(true); + this._updateDomValue(); + if (this.value) { + domValue.innerHTML = this._escapeHTML(this.value); + } + break; + + case 'input': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + // TODO: cleanup + this.editor.selection = this.editor.getSelection(); + break; + + case 'click': + if (event.ctrlKey && this.editable.value) { + // if read-only, we use the regular click behavior of an anchor + if (util.isUrl(this.value)) { + event.preventDefault(); + window.open(this.value, '_blank'); + } + } + break; + + case 'keyup': + //this._debouncedGetDomValue(true); // TODO + this._getDomValue(true); + this._updateDomValue(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomValue(true); + node._updateDomValue(); + }, 1); + break; + } + } + + // field events + var domField = dom.field; + if (target == domField) { + switch (type) { + case 'blur': + case 'change': + this._getDomField(true); + this._updateDomField(); + if (this.field) { + domField.innerHTML = this._escapeHTML(this.field); + } + break; + + case 'input': + this._getDomField(true); + this._updateSchema(); + this._updateDomField(); + this._updateDomValue(); + break; + + case 'keydown': + case 'mousedown': + this.editor.selection = this.editor.getSelection(); + break; + + case 'keyup': + this._getDomField(true); + this._updateDomField(); + break; + + case 'cut': + case 'paste': + setTimeout(function () { + node._getDomField(true); + node._updateDomField(); + }, 1); + break; + } + } + + // focus + // when clicked in whitespace left or right from the field or value, set focus + var domTree = dom.tree; + if (target == domTree.parentNode && type == 'click' && !event.hasMoved) { + var left = (event.offsetX != undefined) ? + (event.offsetX < (this.getLevel() + 1) * 24) : + (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF + if (left || expandable) { + // node is expandable when it is an object or array + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + else { + if (domValue && !this.enum) { + util.setEndOfContentEditable(domValue); + domValue.focus(); + } + } + } + if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && + (type == 'click' && !event.hasMoved)) { + if (domField) { + util.setEndOfContentEditable(domField); + domField.focus(); + } + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + /** + * Key down event handler + * @param {Event} event + */ + Node.prototype.onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var target = event.target || event.srcElement; + var ctrlKey = event.ctrlKey; + var shiftKey = event.shiftKey; + var altKey = event.altKey; + var handled = false; + var prevNode, nextNode, nextDom, nextDom2; + var editable = this.editor.options.mode === 'tree'; + var oldSelection; + var oldBeforeNode; + var nodes; + var multiselection; + var selectedNodes = this.editor.multiselection.nodes.length > 0 + ? this.editor.multiselection.nodes + : [this]; + var firstNode = selectedNodes[0]; + var lastNode = selectedNodes[selectedNodes.length - 1]; + + // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup + if (keynum == 13) { // Enter + if (target == this.dom.value) { + if (!this.editable.value || event.ctrlKey) { + if (util.isUrl(this.value)) { + window.open(this.value, '_blank'); + handled = true; + } + } + } + else if (target == this.dom.expand) { + var expandable = this._hasChilds(); + if (expandable) { + var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all + this._onExpand(recurse); + target.focus(); + handled = true; + } + } + } + else if (keynum == 68) { // D + if (ctrlKey && editable) { // Ctrl+D + Node.onDuplicate(selectedNodes); + handled = true; + } + } + else if (keynum == 69) { // E + if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E + this._onExpand(shiftKey); // recurse = shiftKey + target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) + handled = true; + } + } + else if (keynum == 77 && editable) { // M + if (ctrlKey) { // Ctrl+M + this.showContextMenu(target); + handled = true; + } + } + else if (keynum == 46 && editable) { // Del + if (ctrlKey) { // Ctrl+Del + Node.onRemove(selectedNodes); + handled = true; + } + } + else if (keynum == 45 && editable) { // Ins + if (ctrlKey && !shiftKey) { // Ctrl+Ins + this._onInsertBefore(); + handled = true; + } + else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins + this._onInsertAfter(); + handled = true; + } + } + else if (keynum == 35) { // End + if (altKey) { // Alt+End + // find the last node + var endNode = this._lastNode(); + if (endNode) { + endNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 36) { // Home + if (altKey) { // Alt+Home + // find the first node + var homeNode = this._firstNode(); + if (homeNode) { + homeNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + } + else if (keynum == 37) { // Arrow Left + if (altKey && !shiftKey) { // Alt + Arrow Left + // move to left element + var prevElement = this._previousElement(target); + if (prevElement) { + this.focus(this._getElementName(prevElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left + if (lastNode.expanded) { + var appendDom = lastNode.getAppend(); + nextDom = appendDom ? appendDom.nextSibling : undefined; + } + else { + var dom = lastNode.getDom(); + nextDom = dom.nextSibling; + } + if (nextDom) { + nextNode = Node.getNodeFromTarget(nextDom); + nextDom2 = nextDom.nextSibling; + nextNode2 = Node.getNodeFromTarget(nextDom2); + if (nextNode && nextNode instanceof AppendNode && + !(lastNode.parent.childs.length == 1) && + nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 38) { // Arrow Up + if (altKey && !shiftKey) { // Alt + Arrow Up + // find the previous node + prevNode = this._previousNode(); + if (prevNode) { + this.editor.deselect(true); + prevNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up + // select multiple nodes + prevNode = this._previousNode(); + if (prevNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = prevNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + prevNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up + // find the previous node + prevNode = firstNode._previousNode(); + if (prevNode && prevNode.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + else if (keynum == 39) { // Arrow Right + if (altKey && !shiftKey) { // Alt + Arrow Right + // move to right element + var nextElement = this._nextElement(target); + if (nextElement) { + this.focus(this._getElementName(nextElement)); + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right + dom = firstNode.getDom(); + var prevDom = dom.previousSibling; + if (prevDom) { + prevNode = Node.getNodeFromTarget(prevDom); + if (prevNode && prevNode.parent && + (prevNode instanceof AppendNode) + && !prevNode.isVisible()) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + prevNode.parent.moveBefore(node, prevNode); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: prevNode, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + } + } + } + else if (keynum == 40) { // Arrow Down + if (altKey && !shiftKey) { // Alt + Arrow Down + // find the next node + nextNode = this._nextNode(); + if (nextNode) { + this.editor.deselect(true); + nextNode.focus(Node.focusElement || this._getElementName(target)); + } + handled = true; + } + else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down + // select multiple nodes + nextNode = this._nextNode(); + if (nextNode) { + multiselection = this.editor.multiselection; + multiselection.start = multiselection.start || this; + multiselection.end = nextNode; + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + + this.editor.select(nodes); + nextNode.focus('field'); // select field as we know this always exists + } + handled = true; + } + else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down + // find the 2nd next node and move before that one + if (lastNode.expanded) { + nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; + } + else { + nextNode = lastNode._nextNode(); + } + var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); + if (nextNode2 && nextNode2.parent) { + oldSelection = this.editor.getSelection(); + oldBeforeNode = lastNode._nextSibling(); + + selectedNodes.forEach(function (node) { + nextNode2.parent.moveBefore(node, nextNode2); + }); + this.focus(Node.focusElement || this._getElementName(target)); + + this.editor._onAction('moveNodes', { + nodes: selectedNodes, + oldBeforeNode: oldBeforeNode, + newBeforeNode: nextNode2, + oldSelection: oldSelection, + newSelection: this.editor.getSelection() + }); + } + handled = true; + } + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }; + + /** + * Handle the expand event, when clicked on the expand button + * @param {boolean} recurse If true, child nodes will be expanded too + * @private + */ + Node.prototype._onExpand = function (recurse) { + if (recurse) { + // Take the table offline + var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this + var frame = table.parentNode; + var scrollTop = frame.scrollTop; + frame.removeChild(table); + } + + if (this.expanded) { + this.collapse(recurse); + } + else { + this.expand(recurse); + } + + if (recurse) { + // Put the table online again + frame.appendChild(table); + frame.scrollTop = scrollTop; + } + }; + + /** + * Remove nodes + * @param {Node[] | Node} nodes + */ + Node.onRemove = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onRemove([nodes]); + } + + if (nodes && nodes.length > 0) { + var firstNode = nodes[0]; + var parent = firstNode.parent; + var editor = firstNode.editor; + var firstIndex = firstNode.getIndex(); + editor.highlighter.unhighlight(); + + // adjust the focus + var oldSelection = editor.getSelection(); + Node.blurNodes(nodes); + var newSelection = editor.getSelection(); + + // remove the nodes + nodes.forEach(function (node) { + node.parent._remove(node); + }); + + // store history action + editor._onAction('removeNodes', { + nodes: nodes.slice(0), // store a copy of the array! + parent: parent, + index: firstIndex, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + + /** + * Duplicate nodes + * duplicated nodes will be added right after the original nodes + * @param {Node[] | Node} nodes + */ + Node.onDuplicate = function(nodes) { + if (!Array.isArray(nodes)) { + return Node.onDuplicate([nodes]); + } + + if (nodes && nodes.length > 0) { + var lastNode = nodes[nodes.length - 1]; + var parent = lastNode.parent; + var editor = lastNode.editor; + + editor.deselect(editor.multiselection.nodes); + + // duplicate the nodes + var oldSelection = editor.getSelection(); + var afterNode = lastNode; + var clones = nodes.map(function (node) { + var clone = node.clone(); + parent.insertAfter(clone, afterNode); + afterNode = clone; + return clone; + }); + + // set selection to the duplicated nodes + if (nodes.length === 1) { + clones[0].focus(); + } + else { + editor.select(clones); + } + var newSelection = editor.getSelection(); + + editor._onAction('duplicateNodes', { + afterNode: lastNode, + nodes: clones, + parent: parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Handle insert before event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertBefore = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertBefore(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertBeforeNodes', { + nodes: [newNode], + beforeNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle insert after event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onInsertAfter = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.insertAfter(newNode, this); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('insertAfterNodes', { + nodes: [newNode], + afterNode: this, + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Handle append event + * @param {String} [field] + * @param {*} [value] + * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' + * @private + */ + Node.prototype._onAppend = function (field, value, type) { + var oldSelection = this.editor.getSelection(); + + var newNode = new Node(this.editor, { + field: (field != undefined) ? field : '', + value: (value != undefined) ? value : '', + type: type + }); + newNode.expand(true); + this.parent.appendChild(newNode); + this.editor.highlighter.unhighlight(); + newNode.focus('field'); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('appendNodes', { + nodes: [newNode], + parent: this.parent, + oldSelection: oldSelection, + newSelection: newSelection + }); + }; + + /** + * Change the type of the node's value + * @param {String} newType + * @private + */ + Node.prototype._onChangeType = function (newType) { + var oldType = this.type; + if (newType != oldType) { + var oldSelection = this.editor.getSelection(); + this.changeType(newType); + var newSelection = this.editor.getSelection(); + + this.editor._onAction('changeType', { + node: this, + oldType: oldType, + newType: newType, + oldSelection: oldSelection, + newSelection: newSelection + }); + } + }; + + /** + * Sort the child's of the node. Only applicable when the node has type 'object' + * or 'array'. + * @param {String} direction Sorting direction. Available values: "asc", "desc" + * @private + */ + Node.prototype.sort = function (direction) { + if (!this._hasChilds()) { + return; + } + + var order = (direction == 'desc') ? -1 : 1; + var prop = (this.type == 'array') ? 'value': 'field'; + this.hideChilds(); + + var oldChilds = this.childs; + var oldSortOrder = this.sortOrder; + + // copy the array (the old one will be kept for an undo action + this.childs = this.childs.concat(); + + // sort the arrays + this.childs.sort(function (a, b) { + return order * naturalSort(a[prop], b[prop]); + }); + this.sortOrder = (order == 1) ? 'asc' : 'desc'; + + this.editor._onAction('sort', { + node: this, + oldChilds: oldChilds, + oldSort: oldSortOrder, + newChilds: this.childs, + newSort: this.sortOrder + }); + + this.showChilds(); + }; + + /** + * Create a table row with an append button. + * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable + */ + Node.prototype.getAppend = function () { + if (!this.append) { + this.append = new AppendNode(this.editor); + this.append.setParent(this); + } + return this.append.getDom(); + }; + + /** + * Find the node from an event target + * @param {Node} target + * @return {Node | undefined} node or undefined when not found + * @static + */ + Node.getNodeFromTarget = function (target) { + while (target) { + if (target.node) { + return target.node; + } + target = target.parentNode; + } + + return undefined; + }; + + /** + * Remove the focus of given nodes, and move the focus to the (a) node before, + * (b) the node after, or (c) the parent node. + * @param {Array. | Node} nodes + */ + Node.blurNodes = function (nodes) { + if (!Array.isArray(nodes)) { + Node.blurNodes([nodes]); + return; + } + + var firstNode = nodes[0]; + var parent = firstNode.parent; + var firstIndex = firstNode.getIndex(); + + if (parent.childs[firstIndex + nodes.length]) { + parent.childs[firstIndex + nodes.length].focus(); + } + else if (parent.childs[firstIndex - 1]) { + parent.childs[firstIndex - 1].focus(); + } + else { + parent.focus(); + } + }; + + /** + * Get the next sibling of current node + * @return {Node} nextSibling + * @private + */ + Node.prototype._nextSibling = function () { + var index = this.parent.childs.indexOf(this); + return this.parent.childs[index + 1] || this.parent.append; + }; + + /** + * Get the previously rendered node + * @return {Node | null} previousNode + * @private + */ + Node.prototype._previousNode = function () { + var prevNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var prevDom = dom; + do { + prevDom = prevDom.previousSibling; + prevNode = Node.getNodeFromTarget(prevDom); + } + while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); + } + return prevNode; + }; + + /** + * Get the next rendered node + * @return {Node | null} nextNode + * @private + */ + Node.prototype._nextNode = function () { + var nextNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + // find the previous field + var nextDom = dom; + do { + nextDom = nextDom.nextSibling; + nextNode = Node.getNodeFromTarget(nextDom); + } + while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); + } + + return nextNode; + }; + + /** + * Get the first rendered node + * @return {Node | null} firstNode + * @private + */ + Node.prototype._firstNode = function () { + var firstNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var firstDom = dom.parentNode.firstChild; + firstNode = Node.getNodeFromTarget(firstDom); + } + + return firstNode; + }; + + /** + * Get the last rendered node + * @return {Node | null} lastNode + * @private + */ + Node.prototype._lastNode = function () { + var lastNode = null; + var dom = this.getDom(); + if (dom && dom.parentNode) { + var lastDom = dom.parentNode.lastChild; + lastNode = Node.getNodeFromTarget(lastDom); + while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { + lastDom = lastDom.previousSibling; + lastNode = Node.getNodeFromTarget(lastDom); + } + } + return lastNode; + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._previousElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.value: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + return dom.menu; + case dom.menu: + if (dom.drag) { + return dom.drag; + } + // intentional fall through + default: + return null; + } + }; + + /** + * Get the next element which can have focus. + * @param {Element} elem + * @return {Element | null} nextElem + * @private + */ + Node.prototype._nextElement = function (elem) { + var dom = this.dom; + // noinspection FallthroughInSwitchStatementJS + switch (elem) { + case dom.drag: + return dom.menu; + case dom.menu: + if (this._hasChilds()) { + return dom.expand; + } + // intentional fall through + case dom.expand: + if (this.fieldEditable) { + return dom.field; + } + // intentional fall through + case dom.field: + if (!this._hasChilds()) { + return dom.value; + } + default: + return null; + } + }; + + /** + * Get the dom name of given element. returns null if not found. + * For example when element == dom.field, "field" is returned. + * @param {Element} element + * @return {String | null} elementName Available elements with name: 'drag', + * 'menu', 'expand', 'field', 'value' + * @private + */ + Node.prototype._getElementName = function (element) { + var dom = this.dom; + for (var name in dom) { + if (dom.hasOwnProperty(name)) { + if (dom[name] == element) { + return name; + } + } + } + return null; + }; + + /** + * Test if this node has childs. This is the case when the node is an object + * or array. + * @return {boolean} hasChilds + * @private + */ + Node.prototype._hasChilds = function () { + return this.type == 'array' || this.type == 'object'; + }; + + // titles with explanation for the different types + Node.TYPE_TITLES = { + 'auto': 'Field type "auto". ' + + 'The field type is automatically determined from the value ' + + 'and can be a string, number, boolean, or null.', + 'object': 'Field type "object". ' + + 'An object contains an unordered set of key/value pairs.', + 'array': 'Field type "array". ' + + 'An array contains an ordered collection of values.', + 'string': 'Field type "string". ' + + 'Field type is not determined from the value, ' + + 'but always returned as string.' + }; + + Node.prototype.addTemplates = function (menu, append) { + var node = this; + var templates = node.editor.options.templates; + if (templates == null) return; + if (templates.length) { + // create a separator + menu.push({ + 'type': 'separator' + }); + } + var appendData = function (name, data) { + node._onAppend(name, data); + }; + var insertData = function (name, data) { + node._onInsertBefore(name, data); + }; + templates.forEach(function (template) { + menu.push({ + text: template.text, + className: (template.className || 'jsoneditor-type-object'), + title: template.title, + click: (append ? appendData.bind(this, template.field, template.value) : insertData.bind(this, template.field, template.value)) + }); + }); + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor Anchor element to attach the context menu to + * as sibling. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + Node.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var items = []; + + if (this.editable.value) { + items.push({ + text: 'Type', + title: 'Change the type of this field', + className: 'jsoneditor-type-' + this.type, + submenu: [ + { + text: 'Auto', + className: 'jsoneditor-type-auto' + + (this.type == 'auto' ? ' jsoneditor-selected' : ''), + title: titles.auto, + click: function () { + node._onChangeType('auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array' + + (this.type == 'array' ? ' jsoneditor-selected' : ''), + title: titles.array, + click: function () { + node._onChangeType('array'); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object' + + (this.type == 'object' ? ' jsoneditor-selected' : ''), + title: titles.object, + click: function () { + node._onChangeType('object'); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string' + + (this.type == 'string' ? ' jsoneditor-selected' : ''), + title: titles.string, + click: function () { + node._onChangeType('string'); + } + } + ] + }); + } + + if (this._hasChilds()) { + var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc'); + items.push({ + text: 'Sort', + title: 'Sort the childs of this ' + this.type, + className: 'jsoneditor-sort-' + direction, + click: function () { + node.sort(direction); + }, + submenu: [ + { + text: 'Ascending', + className: 'jsoneditor-sort-asc', + title: 'Sort the childs of this ' + this.type + ' in ascending order', + click: function () { + node.sort('asc'); + } + }, + { + text: 'Descending', + className: 'jsoneditor-sort-desc', + title: 'Sort the childs of this ' + this.type +' in descending order', + click: function () { + node.sort('desc'); + } + } + ] + }); + } + + if (this.parent && this.parent._hasChilds()) { + if (items.length) { + // create a separator + items.push({ + 'type': 'separator' + }); + } + + // create append button (for last child node only) + var childs = node.parent.childs; + if (node == childs[childs.length - 1]) { + var appendSubmenu = [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string'); + } + } + ]; + node.addTemplates(appendSubmenu, true); + items.push({ + text: 'Append', + title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', + submenuTitle: 'Select the type of the field to be appended', + className: 'jsoneditor-append', + click: function () { + node._onAppend('', '', 'auto'); + }, + submenu: appendSubmenu + }); + } + + + + // create insert button + var insertSubmenu = [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onInsertBefore('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onInsertBefore('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onInsertBefore('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onInsertBefore('', '', 'string'); + } + } + ]; + node.addTemplates(insertSubmenu, false); + items.push({ + text: 'Insert', + title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', + submenuTitle: 'Select the type of the field to be inserted', + className: 'jsoneditor-insert', + click: function () { + node._onInsertBefore('', '', 'auto'); + }, + submenu: insertSubmenu + }); + + if (this.editable.field) { + // create duplicate button + items.push({ + text: 'Duplicate', + title: 'Duplicate this field (Ctrl+D)', + className: 'jsoneditor-duplicate', + click: function () { + Node.onDuplicate(node); + } + }); + + // create remove button + items.push({ + text: 'Remove', + title: 'Remove this field (Ctrl+Del)', + className: 'jsoneditor-remove', + click: function () { + Node.onRemove(node); + } + }); + } + } + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * get the type of a value + * @param {*} value + * @return {String} type Can be 'object', 'array', 'string', 'auto' + * @private + */ + Node.prototype._getType = function(value) { + if (value instanceof Array) { + return 'array'; + } + if (value instanceof Object) { + return 'object'; + } + if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { + return 'string'; + } + + return 'auto'; + }; + + /** + * cast contents of a string to the correct type. This can be a string, + * a number, a boolean, etc + * @param {String} str + * @return {*} castedStr + * @private + */ + Node.prototype._stringCast = function(str) { + var lower = str.toLowerCase(), + num = Number(str), // will nicely fail with '123ab' + numFloat = parseFloat(str); // will nicely fail with ' ' + + if (str == '') { + return ''; + } + else if (lower == 'null') { + return null; + } + else if (lower == 'true') { + return true; + } + else if (lower == 'false') { + return false; + } + else if (!isNaN(num) && !isNaN(numFloat)) { + return num; + } + else { + return str; + } + }; + + /** + * escape a text, such that it can be displayed safely in an HTML element + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeHTML = function (text) { + if (typeof text !== 'string') { + return String(text); + } + else { + var htmlEscaped = String(text) + .replace(/&/g, '&') // must be replaced first! + .replace(//g, '>') + .replace(/ /g, '  ') // replace double space with an nbsp and space + .replace(/^ /, ' ') // space at start + .replace(/ $/, ' '); // space at end + + var json = JSON.stringify(htmlEscaped); + var html = json.substring(1, json.length - 1); + if (this.editor.options.escapeUnicode === true) { + html = util.escapeUnicodeChars(html); + } + return html; + } + }; + + /** + * unescape a string. + * @param {String} escapedText + * @return {String} text + * @private + */ + Node.prototype._unescapeHTML = function (escapedText) { + var json = '"' + this._escapeJSON(escapedText) + '"'; + var htmlEscaped = util.parse(json); + + return htmlEscaped + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ |\u00A0/g, ' ') + .replace(/&/g, '&'); // must be replaced last + }; + + /** + * escape a text to make it a valid JSON string. The method will: + * - replace unescaped double quotes with '\"' + * - replace unescaped backslash with '\\' + * - replace returns with '\n' + * @param {String} text + * @return {String} escapedText + * @private + */ + Node.prototype._escapeJSON = function (text) { + // TODO: replace with some smart regex (only when a new solution is faster!) + var escaped = ''; + var i = 0; + while (i < text.length) { + var c = text.charAt(i); + if (c == '\n') { + escaped += '\\n'; + } + else if (c == '\\') { + escaped += c; + i++; + + c = text.charAt(i); + if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { + escaped += '\\'; // no valid escape character + } + escaped += c; + } + else if (c == '"') { + escaped += '\\"'; + } + else { + escaped += c; + } + i++; + } + + return escaped; + }; + + // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode + var AppendNode = appendNodeFactory(Node); + + module.exports = Node; + + +/***/ }, +/* 60 */ +/***/ function(module, exports) { + + /* + * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license + * Author: Jim Palmer (based on chunking idea from Dave Koelle) + */ + /*jshint unused:false */ + module.exports = function naturalSort (a, b) { + "use strict"; + var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, + sre = /(^[ ]*|[ ]*$)/g, + dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, + hre = /^0x[0-9a-f]+$/i, + ore = /^0/, + i = function(s) { return naturalSort.insensitive && ('' + s).toLowerCase() || '' + s; }, + // convert all to strings strip whitespace + x = i(a).replace(sre, '') || '', + y = i(b).replace(sre, '') || '', + // chunk/tokenize + xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + // numeric, hex or date detection + xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), + yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, + oFxNcL, oFyNcL; + // first try and sort Hex codes or Dates + if (yD) { + if ( xD < yD ) { return -1; } + else if ( xD > yD ) { return 1; } + } + // natural sorting through split numeric strings and default strings + for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { + // find floats not starting with '0', string or 0 if not defined (Clint Priest) + oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; + oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; + // handle numeric vs string comparison - number < string - (Kyle Adams) + if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; } + // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' + else if (typeof oFxNcL !== typeof oFyNcL) { + oFxNcL += ''; + oFyNcL += ''; + } + if (oFxNcL < oFyNcL) { return -1; } + if (oFxNcL > oFyNcL) { return 1; } + } + return 0; + }; + + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var util = __webpack_require__(54); + var ContextMenu = __webpack_require__(57); + + /** + * A factory function to create an AppendNode, which depends on a Node + * @param {Node} Node + */ + function appendNodeFactory(Node) { + /** + * @constructor AppendNode + * @extends Node + * @param {TreeEditor} editor + * Create a new AppendNode. This is a special node which is created at the + * end of the list with childs for an object or array + */ + function AppendNode (editor) { + /** @type {TreeEditor} */ + this.editor = editor; + this.dom = {}; + } + + AppendNode.prototype = new Node(); + + /** + * Return a table row with an append button. + * @return {Element} dom TR element + */ + AppendNode.prototype.getDom = function () { + // TODO: implement a new solution for the append node + var dom = this.dom; + + if (dom.tr) { + return dom.tr; + } + + this._updateEditability(); + + // a row for the append button + var trAppend = document.createElement('tr'); + trAppend.node = this; + dom.tr = trAppend; + + // TODO: consistent naming + + if (this.editor.options.mode === 'tree') { + // a cell for the dragarea column + dom.tdDrag = document.createElement('td'); + + // create context menu + var tdMenu = document.createElement('td'); + dom.tdMenu = tdMenu; + var menu = document.createElement('button'); + menu.type = 'button'; + menu.className = 'jsoneditor-contextmenu'; + menu.title = 'Click to open the actions menu (Ctrl+M)'; + dom.menu = menu; + tdMenu.appendChild(dom.menu); + } + + // a cell for the contents (showing text 'empty') + var tdAppend = document.createElement('td'); + var domText = document.createElement('div'); + domText.innerHTML = '(empty)'; + domText.className = 'jsoneditor-readonly'; + tdAppend.appendChild(domText); + dom.td = tdAppend; + dom.text = domText; + + this.updateDom(); + + return trAppend; + }; + + /** + * Update the HTML dom of the Node + */ + AppendNode.prototype.updateDom = function () { + var dom = this.dom; + var tdAppend = dom.td; + if (tdAppend) { + tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; + // TODO: not so nice hard coded offset + } + + var domText = dom.text; + if (domText) { + domText.innerHTML = '(empty ' + this.parent.type + ')'; + } + + // attach or detach the contents of the append node: + // hide when the parent has childs, show when the parent has no childs + var trAppend = dom.tr; + if (!this.isVisible()) { + if (dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.removeChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.removeChild(dom.tdMenu); + } + trAppend.removeChild(tdAppend); + } + } + else { + if (!dom.tr.firstChild) { + if (dom.tdDrag) { + trAppend.appendChild(dom.tdDrag); + } + if (dom.tdMenu) { + trAppend.appendChild(dom.tdMenu); + } + trAppend.appendChild(tdAppend); + } + } + }; + + /** + * Check whether the AppendNode is currently visible. + * the AppendNode is visible when its parent has no childs (i.e. is empty). + * @return {boolean} isVisible + */ + AppendNode.prototype.isVisible = function () { + return (this.parent.childs.length == 0); + }; + + /** + * Show a contextmenu for this node + * @param {HTMLElement} anchor The element to attach the menu to. + * @param {function} [onClose] Callback method called when the context menu + * is being closed. + */ + AppendNode.prototype.showContextMenu = function (anchor, onClose) { + var node = this; + var titles = Node.TYPE_TITLES; + var appendSubmenu = [ + { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto'); + } + }, + { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []); + } + }, + { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}); + } + }, + { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string'); + } + } + ]; + node.addTemplates(appendSubmenu, true); + var items = [ + // create append button + { + 'text': 'Append', + 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + 'submenuTitle': 'Select the type of the field to be appended', + 'className': 'jsoneditor-insert', + 'click': function () { + node._onAppend('', '', 'auto'); + }, + 'submenu': appendSubmenu + } + ]; + + var menu = new ContextMenu(items, {close: onClose}); + menu.show(anchor, this.editor.content); + }; + + /** + * Handle an event. The event is catched centrally by the editor + * @param {Event} event + */ + AppendNode.prototype.onEvent = function (event) { + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + + // highlight the append nodes parent + var menu = dom.menu; + if (target == menu) { + if (type == 'mouseover') { + this.editor.highlighter.highlight(this.parent); + } + else if (type == 'mouseout') { + this.editor.highlighter.unhighlight(); + } + } + + // context menu events + if (type == 'click' && target == dom.menu) { + var highlighter = this.editor.highlighter; + highlighter.highlight(this.parent); + highlighter.lock(); + util.addClassName(dom.menu, 'jsoneditor-selected'); + this.showContextMenu(dom.menu, function () { + util.removeClassName(dom.menu, 'jsoneditor-selected'); + highlighter.unlock(); + highlighter.unhighlight(); + }); + } + + if (type == 'keydown') { + this.onKeyDown(event); + } + }; + + return AppendNode; + } + + module.exports = appendNodeFactory; + + +/***/ }, +/* 62 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ContextMenu = __webpack_require__(57); + + /** + * Create a select box to be used in the editor menu's, which allows to switch mode + * @param {HTMLElement} container + * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' + * @param {function(mode: string)} onSwitch Callback invoked on switch + * @constructor + */ + function ModeSwitcher(container, modes, current, onSwitch) { + // available modes + var availableModes = { + code: { + 'text': 'Code', + 'title': 'Switch to code highlighter', + 'click': function () { + onSwitch('code') + } + }, + form: { + 'text': 'Form', + 'title': 'Switch to form editor', + 'click': function () { + onSwitch('form'); + } + }, + text: { + 'text': 'Text', + 'title': 'Switch to plain text editor', + 'click': function () { + onSwitch('text'); + } + }, + tree: { + 'text': 'Tree', + 'title': 'Switch to tree editor', + 'click': function () { + onSwitch('tree'); + } + }, + view: { + 'text': 'View', + 'title': 'Switch to tree view', + 'click': function () { + onSwitch('view'); + } + } + }; + + // list the selected modes + var items = []; + for (var i = 0; i < modes.length; i++) { + var mode = modes[i]; + var item = availableModes[mode]; + if (!item) { + throw new Error('Unknown mode "' + mode + '"'); + } + + item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); + items.push(item); + } + + // retrieve the title of current mode + var currentMode = availableModes[current]; + if (!currentMode) { + throw new Error('Unknown mode "' + current + '"'); + } + var currentTitle = currentMode.text; + + // create the html element + var box = document.createElement('button'); + box.type = 'button'; + box.className = 'jsoneditor-modes jsoneditor-separator'; + box.innerHTML = currentTitle + ' ▾'; + box.title = 'Switch editor mode'; + box.onclick = function () { + var menu = new ContextMenu(items); + menu.show(box); + }; + + var frame = document.createElement('div'); + frame.className = 'jsoneditor-modes'; + frame.style.position = 'relative'; + frame.appendChild(box); + + container.appendChild(frame); + + this.dom = { + container: container, + box: box, + frame: frame + }; + } + + /** + * Set focus to switcher + */ + ModeSwitcher.prototype.focus = function () { + this.dom.box.focus(); + }; + + /** + * Destroy the ModeSwitcher, remove from DOM + */ + ModeSwitcher.prototype.destroy = function () { + if (this.dom && this.dom.frame && this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + this.dom = null; + }; + + module.exports = ModeSwitcher; + + +/***/ }, +/* 63 */ +/***/ function(module, exports) { + + 'use strict'; + + function completely(config) { + config = config || {}; + config.confirmKeys = config.confirmKeys || [39, 35, 9] // right, end, tab + + var fontSize = ''; + var fontFamily = ''; + + var wrapper = document.createElement('div'); + wrapper.style.position = 'relative'; + wrapper.style.outline = '0'; + wrapper.style.border = '0'; + wrapper.style.margin = '0'; + wrapper.style.padding = '0'; + + var dropDown = document.createElement('div'); + dropDown.className = 'autocomplete dropdown'; + dropDown.style.position = 'absolute'; + dropDown.style.visibility = 'hidden'; + + var spacer; + var leftSide; // <-- it will contain the leftSide part of the textfield (the bit that was already autocompleted) + var createDropDownController = function (elem, rs) { + var rows = []; + var ix = 0; + var oldIndex = -1; + + var onMouseOver = function () { this.style.outline = '1px solid #ddd'; } + var onMouseOut = function () { this.style.outline = '0'; } + var onMouseDown = function () { p.hide(); p.onmouseselection(this.__hint, p.rs); } + + var p = { + rs: rs, + hide: function () { + elem.style.visibility = 'hidden'; + //rs.hideDropDown(); + }, + refresh: function (token, array) { + elem.style.visibility = 'hidden'; + ix = 0; + elem.innerHTML = ''; + var vph = (window.innerHeight || document.documentElement.clientHeight); + var rect = elem.parentNode.getBoundingClientRect(); + var distanceToTop = rect.top - 6; // heuristic give 6px + var distanceToBottom = vph - rect.bottom - 6; // distance from the browser border. + + rows = []; + for (var i = 0; i < array.length; i++) { + if (array[i].indexOf(token) !== 0) { continue; } + var divRow = document.createElement('div'); + divRow.className = 'item'; + //divRow.style.color = config.color; + divRow.onmouseover = onMouseOver; + divRow.onmouseout = onMouseOut; + divRow.onmousedown = onMouseDown; + divRow.__hint = array[i]; + divRow.innerHTML = token + '' + array[i].substring(token.length) + ''; + rows.push(divRow); + elem.appendChild(divRow); + } + if (rows.length === 0) { + return; // nothing to show. + } + if (rows.length === 1 && token === rows[0].__hint) { + return; // do not show the dropDown if it has only one element which matches what we have just displayed. + } + + if (rows.length < 2) return; + p.highlight(0); + + if (distanceToTop > distanceToBottom * 3) { // Heuristic (only when the distance to the to top is 4 times more than distance to the bottom + elem.style.maxHeight = distanceToTop + 'px'; // we display the dropDown on the top of the input text + elem.style.top = ''; + elem.style.bottom = '100%'; + } else { + elem.style.top = '100%'; + elem.style.bottom = ''; + elem.style.maxHeight = distanceToBottom + 'px'; + } + elem.style.visibility = 'visible'; + }, + highlight: function (index) { + if (oldIndex != -1 && rows[oldIndex]) { + rows[oldIndex].className = "item"; + } + rows[index].className = "item hover"; + oldIndex = index; + }, + move: function (step) { // moves the selection either up or down (unless it's not possible) step is either +1 or -1. + if (elem.style.visibility === 'hidden') return ''; // nothing to move if there is no dropDown. (this happens if the user hits escape and then down or up) + if (ix + step === -1 || ix + step === rows.length) return rows[ix].__hint; // NO CIRCULAR SCROLLING. + ix += step; + p.highlight(ix); + return rows[ix].__hint;//txtShadow.value = uRows[uIndex].__hint ; + }, + onmouseselection: function () { } // it will be overwritten. + }; + return p; + } + + function setEndOfContenteditable(contentEditableElement) { + var range, selection; + if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ + { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + else if (document.selection)//IE 8 and lower + { + range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) + range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + range.select();//Select the range (make it the visible selection + } + } + + function calculateWidthForText(text) { + if (spacer === undefined) { // on first call only. + spacer = document.createElement('span'); + spacer.style.visibility = 'hidden'; + spacer.style.position = 'fixed'; + spacer.style.outline = '0'; + spacer.style.margin = '0'; + spacer.style.padding = '0'; + spacer.style.border = '0'; + spacer.style.left = '0'; + spacer.style.whiteSpace = 'pre'; + spacer.style.fontSize = fontSize; + spacer.style.fontFamily = fontFamily; + spacer.style.fontWeight = 'normal'; + document.body.appendChild(spacer); + } + + // Used to encode an HTML string into a plain text. + // taken from http://stackoverflow.com/questions/1219860/javascript-jquery-html-encoding + spacer.innerHTML = String(text).replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + return spacer.getBoundingClientRect().right; + } + + var rs = { + onArrowDown: function () { }, // defaults to no action. + onArrowUp: function () { }, // defaults to no action. + onEnter: function () { }, // defaults to no action. + onTab: function () { }, // defaults to no action. + startFrom: 0, + options: [], + element: null, + elementHint: null, + elementStyle: null, + wrapper: wrapper, // Only to allow easy access to the HTML elements to the final user (possibly for minor customizations) + show: function (element, startPos, options) { + this.startFrom = startPos; + this.wrapper.remove(); + if (this.elementHint) { + this.elementHint.remove(); + this.elementHint = null; + } + + if (fontSize == '') { + fontSize = window.getComputedStyle(element).getPropertyValue('font-size'); + } + if (fontFamily == '') { + fontFamily = window.getComputedStyle(element).getPropertyValue('font-family'); + } + + var w = element.getBoundingClientRect().right - element.getBoundingClientRect().left; + dropDown.style.marginLeft = '0'; + dropDown.style.marginTop = element.getBoundingClientRect().height + 'px'; + this.options = options; + + if (this.element != element) { + this.element = element; + this.elementStyle = { + zIndex: this.element.style.zIndex, + position: this.element.style.position, + backgroundColor: this.element.style.backgroundColor, + borderColor: this.element.style.borderColor + } + } + + this.element.style.zIndex = 3; + this.element.style.position = 'relative'; + this.element.style.backgroundColor = 'transparent'; + this.element.style.borderColor = 'transparent'; + + this.elementHint = element.cloneNode(); + this.elementHint.className = 'autocomplete hint'; + this.elementHint.style.zIndex = 2; + this.elementHint.style.position = 'absolute'; + this.elementHint.onfocus = function () { this.element.focus(); }.bind(this); + + + + if (this.element.addEventListener) { + this.element.removeEventListener("keydown", keyDownHandler); + this.element.addEventListener("keydown", keyDownHandler, false); + this.element.removeEventListener("blur", onBlurHandler); + this.element.addEventListener("blur", onBlurHandler, false); + } + + wrapper.appendChild(this.elementHint); + wrapper.appendChild(dropDown); + element.parentElement.appendChild(wrapper); + + + this.repaint(element); + }, + setText: function (text) { + this.element.innerText = text; + }, + getText: function () { + return this.element.innerText; + }, + hideDropDown: function () { + this.wrapper.remove(); + if (this.elementHint) { + this.elementHint.remove(); + this.elementHint = null; + dropDownController.hide(); + this.element.style.zIndex = this.elementStyle.zIndex; + this.element.style.position = this.elementStyle.position; + this.element.style.backgroundColor = this.elementStyle.backgroundColor; + this.element.style.borderColor = this.elementStyle.borderColor; + } + + }, + repaint: function (element) { + var text = element.innerText; + text = text.replace('\n', ''); + + var startFrom = this.startFrom; + var options = this.options; + var optionsLength = this.options.length; + + // breaking text in leftSide and token. + + var token = text.substring(this.startFrom); + leftSide = text.substring(0, this.startFrom); + + for (var i = 0; i < optionsLength; i++) { + var opt = this.options[i]; + if (opt.indexOf(token) === 0) { // <-- how about upperCase vs. lowercase + this.elementHint.innerText = leftSide + opt; + break; + } + } + // moving the dropDown and refreshing it. + dropDown.style.left = calculateWidthForText(leftSide) + 'px'; + dropDownController.refresh(token, this.options); + this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + 10 + 'px' + var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); + if (!wasDropDownHidden) + this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + dropDown.clientWidth + 'px'; + } + }; + + var dropDownController = createDropDownController(dropDown, rs); + + var keyDownHandler = function (e) { + //console.log("Keydown:" + e.keyCode); + e = e || window.event; + var keyCode = e.keyCode; + + if (this.elementHint == null) return; + + if (keyCode == 33) { return; } // page up (do nothing) + if (keyCode == 34) { return; } // page down (do nothing); + + if (keyCode == 27) { //escape + rs.hideDropDown(); + rs.element.focus(); + e.preventDefault(); + e.stopPropagation(); + return; + } + + if (config.confirmKeys.indexOf(keyCode) >= 0) { // (autocomplete triggered) + if (keyCode == 9) { + if (this.elementHint.innerText.length == 0) { + rs.onTab(); + } + } + if (this.elementHint.innerText.length > 0) { // if there is a hint + if (this.element.innerText != this.elementHint.innerText) { + this.element.innerText = this.elementHint.innerText; + rs.hideDropDown(); + setEndOfContenteditable(this.element); + if (keyCode == 9) { + rs.element.focus(); + e.preventDefault(); + e.stopPropagation(); + } + } + } + return; + } + + if (keyCode == 13) { // enter (autocomplete triggered) + if (this.elementHint.innerText.length == 0) { // if there is a hint + rs.onEnter(); + } else { + var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); + dropDownController.hide(); + + if (wasDropDownHidden) { + rs.hideDropDown(); + rs.element.focus(); + rs.onEnter(); + return; + } + + this.element.innerText = this.elementHint.innerText; + rs.hideDropDown(); + setEndOfContenteditable(this.element); + e.preventDefault(); + e.stopPropagation(); + } + return; + } + + if (keyCode == 40) { // down + var m = dropDownController.move(+1); + if (m == '') { rs.onArrowDown(); } + this.elementHint.innerText = leftSide + m; + e.preventDefault(); + e.stopPropagation(); + return; + } + + if (keyCode == 38) { // up + var m = dropDownController.move(-1); + if (m == '') { rs.onArrowUp(); } + this.elementHint.innerText = leftSide + m; + e.preventDefault(); + e.stopPropagation(); + return; + } + + }.bind(rs); + + var onBlurHandler = function (e) { + rs.hideDropDown(); + //console.log("Lost focus."); + }.bind(rs); + + dropDownController.onmouseselection = function (text, rs) { + rs.element.innerText = rs.elementHint.innerText = leftSide + text; + rs.hideDropDown(); + window.setTimeout(function () { + rs.element.focus(); + setEndOfContenteditable(rs.element); + }, 1); + }; + + return rs; + } + + module.exports = completely; + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var ace = __webpack_require__(65); + var ModeSwitcher = __webpack_require__(62); + var util = __webpack_require__(54); + + // create a mixin with the functions for text mode + var textmode = {}; + + var MAX_ERRORS = 3; // maximum number of displayed errors at the bottom + + var DEFAULT_THEME = 'ace/theme/jsoneditor'; + + /** + * Create a text editor + * @param {Element} container + * @param {Object} [options] Object with options. available options: + * {String} mode Available values: + * "text" (default) + * or "code". + * {Number} indentation Number of indentation + * spaces. 2 by default. + * {function} onChange Callback method + * triggered on change + * {function} onModeChange Callback method + * triggered after setMode + * {function} onEditable Determine if textarea is readOnly + * readOnly defaults true + * {Object} ace A custom instance of + * Ace editor. + * {boolean} escapeUnicode If true, unicode + * characters are escaped. + * false by default. + * @private + */ + textmode.create = function (container, options) { + // read options + options = options || {}; + + if(typeof options.statusBar === 'undefined') { + options.statusBar = true; + } + + this.options = options; + + // indentation + if (options.indentation) { + this.indentation = Number(options.indentation); + } + else { + this.indentation = 2; // number of spaces + } + + // grab ace from options if provided + var _ace = options.ace ? options.ace : ace; + // TODO: make the option options.ace deprecated, it's not needed anymore (see #309) + + // determine mode + this.mode = (options.mode == 'code') ? 'code' : 'text'; + if (this.mode == 'code') { + // verify whether Ace editor is available and supported + if (typeof _ace === 'undefined') { + this.mode = 'text'; + console.warn('Failed to load Ace editor, falling back to plain text mode. Please use a JSONEditor bundle including Ace, or pass Ace as via the configuration option `ace`.'); + } + } + + // determine theme + this.theme = options.theme || DEFAULT_THEME; + if (this.theme === DEFAULT_THEME && _ace) { + try { + __webpack_require__(71); + } + catch (err) { + console.error(err); + } + } + + var me = this; + this.container = container; + this.dom = {}; + this.aceEditor = undefined; // ace code editor + this.textarea = undefined; // plain text editor (fallback when Ace is not available) + this.validateSchema = null; + + // create a debounced validate function + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + + this.width = container.clientWidth; + this.height = container.clientHeight; + + this.frame = document.createElement('div'); + this.frame.className = 'jsoneditor jsoneditor-mode-' + this.options.mode; + this.frame.onclick = function (event) { + // prevent default submit action when the editor is located inside a form + event.preventDefault(); + }; + this.frame.onkeydown = function (event) { + me._onKeyDown(event); + }; + + // create menu + this.menu = document.createElement('div'); + this.menu.className = 'jsoneditor-menu'; + this.frame.appendChild(this.menu); + + // create format button + var buttonFormat = document.createElement('button'); + buttonFormat.type = 'button'; + buttonFormat.className = 'jsoneditor-format'; + buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; + this.menu.appendChild(buttonFormat); + buttonFormat.onclick = function () { + try { + me.format(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create compact button + var buttonCompact = document.createElement('button'); + buttonCompact.type = 'button'; + buttonCompact.className = 'jsoneditor-compact'; + buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; + this.menu.appendChild(buttonCompact); + buttonCompact.onclick = function () { + try { + me.compact(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create repair button + var buttonRepair = document.createElement('button'); + buttonRepair.type = 'button'; + buttonRepair.className = 'jsoneditor-repair'; + buttonRepair.title = 'Repair JSON: fix quotes and escape characters, remove comments and JSONP notation, turn JavaScript objects into JSON.'; + this.menu.appendChild(buttonRepair); + buttonRepair.onclick = function () { + try { + me.repair(); + me._onChange(); + } + catch (err) { + me._onError(err); + } + }; + + // create mode box + if (this.options && this.options.modes && this.options.modes.length) { + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + // switch mode and restore focus + me.setMode(mode); + me.modeSwitcher.focus(); + }); + } + + var emptyNode = {}; + var isReadOnly = (this.options.onEditable + && typeof(this.options.onEditable === 'function') + && !this.options.onEditable(emptyNode)); + + this.content = document.createElement('div'); + this.content.className = 'jsoneditor-outer'; + this.frame.appendChild(this.content); + + this.container.appendChild(this.frame); + + if (this.mode == 'code') { + this.editorDom = document.createElement('div'); + this.editorDom.style.height = '100%'; // TODO: move to css + this.editorDom.style.width = '100%'; // TODO: move to css + this.content.appendChild(this.editorDom); + + var aceEditor = _ace.edit(this.editorDom); + aceEditor.$blockScrolling = Infinity; + aceEditor.setTheme(this.theme); + aceEditor.setOptions({ readOnly: isReadOnly }); + aceEditor.setShowPrintMargin(false); + aceEditor.setFontSize(13); + aceEditor.getSession().setMode('ace/mode/json'); + aceEditor.getSession().setTabSize(this.indentation); + aceEditor.getSession().setUseSoftTabs(true); + aceEditor.getSession().setUseWrapMode(true); + aceEditor.commands.bindKey('Ctrl-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + aceEditor.commands.bindKey('Command-L', null); // disable Ctrl+L (is used by the browser to select the address bar) + this.aceEditor = aceEditor; + + // TODO: deprecated since v5.0.0. Cleanup backward compatibility some day + if (!this.hasOwnProperty('editor')) { + Object.defineProperty(this, 'editor', { + get: function () { + console.warn('Property "editor" has been renamed to "aceEditor".'); + return me.aceEditor; + }, + set: function (aceEditor) { + console.warn('Property "editor" has been renamed to "aceEditor".'); + me.aceEditor = aceEditor; + } + }); + } + + var poweredBy = document.createElement('a'); + poweredBy.appendChild(document.createTextNode('powered by ace')); + poweredBy.href = 'http://ace.ajax.org'; + poweredBy.target = '_blank'; + poweredBy.className = 'jsoneditor-poweredBy'; + poweredBy.onclick = function () { + // TODO: this anchor falls below the margin of the content, + // therefore the normal a.href does not work. We use a click event + // for now, but this should be fixed. + window.open(poweredBy.href, poweredBy.target); + }; + this.menu.appendChild(poweredBy); + + // register onchange event + aceEditor.on('change', this._onChange.bind(this)); + aceEditor.on('changeSelection', this._onSelect.bind(this)); + } + else { + // load a plain text textarea + var textarea = document.createElement('textarea'); + textarea.className = 'jsoneditor-text'; + textarea.spellcheck = false; + this.content.appendChild(textarea); + this.textarea = textarea; + this.textarea.readOnly = isReadOnly; + + // register onchange event + if (this.textarea.oninput === null) { + this.textarea.oninput = this._onChange.bind(this); + } + else { + // oninput is undefined. For IE8- + this.textarea.onchange = this._onChange.bind(this); + } + + textarea.onselect = this._onSelect.bind(this); + textarea.onmousedown = this._onMouseDown.bind(this); + textarea.onblur = this._onBlur.bind(this); + } + + if (options.statusBar) { + if (this.mode === 'code') { + util.addClassName(this.content, 'has-status-bar'); + + this.curserInfoElements = {}; + var statusBar = document.createElement('div'); + statusBar.className = 'jsoneditor-statusbar'; + this.frame.appendChild(statusBar); + + var lnLabel = document.createElement('span'); + lnLabel.className = 'jsoneditor-curserinfo-label'; + lnLabel.innerText = 'Ln:'; + + var lnVal = document.createElement('span'); + lnVal.className = 'jsoneditor-curserinfo-val'; + lnVal.innerText = 0; + + statusBar.appendChild(lnLabel); + statusBar.appendChild(lnVal); + + var colLabel = document.createElement('span'); + colLabel.className = 'jsoneditor-curserinfo-label'; + colLabel.innerText = 'Col:'; + + var colVal = document.createElement('span'); + colVal.className = 'jsoneditor-curserinfo-val'; + colVal.innerText = 0; + + statusBar.appendChild(colLabel); + statusBar.appendChild(colVal); + + this.curserInfoElements.colVal = colVal; + this.curserInfoElements.lnVal = lnVal; + + var countLabel = document.createElement('span'); + countLabel.className = 'jsoneditor-curserinfo-label'; + countLabel.innerText = 'characters selected'; + countLabel.style.display = 'none'; + + var countVal = document.createElement('span'); + countVal.className = 'jsoneditor-curserinfo-count'; + countVal.innerText = 0; + countVal.style.display = 'none'; + + this.curserInfoElements.countLabel = countLabel; + this.curserInfoElements.countVal = countVal; + + statusBar.appendChild(countVal); + statusBar.appendChild(countLabel); + } + } + + this.setSchema(this.options.schema, this.options.schemaRefs); + }; + + /** + * Handle a change: + * - Validate JSON schema + * - Send a callback to the onChange listener if provided + * @private + */ + textmode._onChange = function () { + // validate JSON schema (if configured) + this._debouncedValidate(); + + // trigger the onChange callback + if (this.options.onChange) { + try { + this.options.onChange(); + } + catch (err) { + console.error('Error in onChange callback: ', err); + } + } + }; + + /** + * Handle text selection + * Calculates the cursor position and selection range and updates menu + * @private + */ + textmode._onSelect = function () { + if(this.options.statusBar) { + if (this.textarea) { + var selectionRange = util.getInputSelection(this.textarea); + if (selectionRange.start !== selectionRange.end) { + this._setSelectionCountDisplay(Math.abs(selectionRange.end - selectionRange.start)); + } + } else if (this.aceEditor && this.curserInfoElements) { + var curserPos = this.aceEditor.getCursorPosition(); + var selectedText = this.aceEditor.getSelectedText(); + + this.curserInfoElements.lnVal.innerText = curserPos.row + 1; + this.curserInfoElements.colVal.innerText = curserPos.column + 1; + this._setSelectionCountDisplay(selectedText.length); + } + } + }; + + /** + * Event handler for keydown. Handles shortcut keys + * @param {Event} event + * @private + */ + textmode._onKeyDown = function (event) { + var keynum = event.which || event.keyCode; + var handled = false; + + if (keynum == 220 && event.ctrlKey) { + if (event.shiftKey) { // Ctrl+Shift+\ + this.compact(); + this._onChange(); + } + else { // Ctrl+\ + this.format(); + this._onChange(); + } + handled = true; + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + + this._setSelectionCountDisplay(); + }; + + /** + * Event handler for mousedown. + * @param {Event} event + * @private + */ + textmode._onMouseDown = function (event) { + this._setSelectionCountDisplay(); + }; + + /** + * Event handler for blur. + * @param {Event} event + * @private + */ + textmode._onBlur = function (event) { + this._setSelectionCountDisplay(); + }; + + textmode._setSelectionCountDisplay = function (value) { + if (this.options.statusBar && this.curserInfoElements) { + if (value && this.curserInfoElements && this.curserInfoElements.countVal) { + this.curserInfoElements.countVal.innerText = value; + this.curserInfoElements.countVal.style.display = 'inline'; + this.curserInfoElements.countLabel.style.display = 'inline'; + } else { + this.curserInfoElements.countVal.style.display = 'none'; + this.curserInfoElements.countLabel.style.display = 'none'; + } + } + }; + + /** + * Destroy the editor. Clean up DOM, event listeners, and web workers. + */ + textmode.destroy = function () { + // remove old ace editor + if (this.aceEditor) { + this.aceEditor.destroy(); + this.aceEditor = null; + } + + if (this.frame && this.container && this.frame.parentNode == this.container) { + this.container.removeChild(this.frame); + } + + if (this.modeSwitcher) { + this.modeSwitcher.destroy(); + this.modeSwitcher = null; + } + + this.textarea = null; + + this._debouncedValidate = null; + }; + + /** + * Compact the code in the text editor + */ + textmode.compact = function () { + var json = this.get(); + var text = JSON.stringify(json); + this.setText(text); + }; + + /** + * Format the code in the text editor + */ + textmode.format = function () { + var json = this.get(); + var text = JSON.stringify(json, null, this.indentation); + this.setText(text); + }; + + /** + * Repair the code in the text editor + */ + textmode.repair = function () { + var text = this.getText(); + var sanitizedText = util.sanitize(text); + this.setText(sanitizedText); + }; + + /** + * Set focus to the formatter + */ + textmode.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + if (this.aceEditor) { + this.aceEditor.focus(); + } + }; + + /** + * Resize the formatter + */ + textmode.resize = function () { + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + /** + * Set json data in the formatter + * @param {Object} json + */ + textmode.set = function(json) { + this.setText(JSON.stringify(json, null, this.indentation)); + }; + + /** + * Get json data from the formatter + * @return {Object} json + */ + textmode.get = function() { + var text = this.getText(); + var json; + + try { + json = util.parse(text); // this can throw an error + } + catch (err) { + // try to sanitize json, replace JavaScript notation with JSON notation + text = util.sanitize(text); + + // try to parse again + json = util.parse(text); // this can throw an error + } + + return json; + }; + + /** + * Get the text contents of the editor + * @return {String} jsonText + */ + textmode.getText = function() { + if (this.textarea) { + return this.textarea.value; + } + if (this.aceEditor) { + return this.aceEditor.getValue(); + } + return ''; + }; + + /** + * Set the text contents of the editor + * @param {String} jsonText + */ + textmode.setText = function(jsonText) { + var text; + + if (this.options.escapeUnicode === true) { + text = util.escapeUnicodeChars(jsonText); + } + else { + text = jsonText; + } + + if (this.textarea) { + this.textarea.value = text; + } + if (this.aceEditor) { + // prevent emitting onChange events while setting new text + var originalOnChange = this.options.onChange; + this.options.onChange = null; + + this.aceEditor.setValue(text, -1); + + this.options.onChange = originalOnChange; + } + // validate JSON schema + this.validate(); + }; + + /** + * Validate current JSON object against the configured JSON schema + * Throws an exception when no JSON schema is configured + */ + textmode.validate = function () { + // clear all current errors + if (this.dom.validationErrors) { + this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); + this.dom.validationErrors = null; + + this.content.style.marginBottom = ''; + this.content.style.paddingBottom = ''; + } + + var doValidate = false; + var errors = []; + var json; + try { + json = this.get(); // this can fail when there is no valid json + doValidate = true; + } + catch (err) { + // no valid JSON, don't validate + } + + // only validate the JSON when parsing the JSON succeeded + if (doValidate && this.validateSchema) { + var valid = this.validateSchema(json); + if (!valid) { + errors = this.validateSchema.errors.map(function (error) { + return util.improveSchemaError(error); + }); + } + } + + if (errors.length > 0) { + // limit the number of displayed errors + var limit = errors.length > MAX_ERRORS; + if (limit) { + errors = errors.slice(0, MAX_ERRORS); + var hidden = this.validateSchema.errors.length - MAX_ERRORS; + errors.push('(' + hidden + ' more errors...)') + } + + var validationErrors = document.createElement('div'); + validationErrors.innerHTML = '' + + '' + + errors.map(function (error) { + var message; + if (typeof error === 'string') { + message = ''; + } + else { + message = '' + + ''; + } + + return '' + message + '' + }).join('') + + '' + + '
' + error + '
' + error.dataPath + '' + error.message + '
'; + + this.dom.validationErrors = validationErrors; + this.frame.appendChild(validationErrors); + + var height = validationErrors.clientHeight; + this.content.style.marginBottom = (-height) + 'px'; + this.content.style.paddingBottom = height + 'px'; + } + + // update the height of the ace editor + if (this.aceEditor) { + var force = false; + this.aceEditor.resize(force); + } + }; + + // define modes + module.exports = [ + { + mode: 'text', + mixin: textmode, + data: 'text', + load: textmode.format + }, + { + mode: 'code', + mixin: textmode, + data: 'text', + load: textmode.format + } + ]; + + +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { + + var ace + if (window.ace) { + // use the already loaded instance of Ace + ace = window.ace + } + else { + try { + // load brace + ace = __webpack_require__(66); + + // load required Ace plugins + __webpack_require__(68); + __webpack_require__(70); + } + catch (err) { + // failed to load brace (can be minimalist bundle). + // No worries, the editor will fall back to plain text if needed. + } + } + + module.exports = ace; + + +/***/ }, +/* 66 */ +/***/ function(module, exports, __webpack_require__) { + + /* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + + /** + * Define a module along with a payload + * @param module a name for the payload + * @param payload a function to call with (acequire, exports, module) params + */ + + (function() { + + var ACE_NAMESPACE = "ace"; + + var global = (function() { return this; })(); + if (!global && typeof window != "undefined") global = window; // strict mode + + + if (!ACE_NAMESPACE && typeof acequirejs !== "undefined") + return; + + + var define = function(module, deps, payload) { + if (typeof module !== "string") { + if (define.original) + define.original.apply(this, arguments); + else { + console.error("dropping module because define wasn\'t a string."); + console.trace(); + } + return; + } + if (arguments.length == 2) + payload = deps; + if (!define.modules[module]) { + define.payloads[module] = payload; + define.modules[module] = null; + } + }; + + define.modules = {}; + define.payloads = {}; + + /** + * Get at functionality define()ed using the function above + */ + var _acequire = function(parentId, module, callback) { + if (typeof module === "string") { + var payload = lookup(parentId, module); + if (payload != undefined) { + callback && callback(); + return payload; + } + } else if (Object.prototype.toString.call(module) === "[object Array]") { + var params = []; + for (var i = 0, l = module.length; i < l; ++i) { + var dep = lookup(parentId, module[i]); + if (dep == undefined && acequire.original) + return; + params.push(dep); + } + return callback && callback.apply(null, params) || true; + } + }; + + var acequire = function(module, callback) { + var packagedModule = _acequire("", module, callback); + if (packagedModule == undefined && acequire.original) + return acequire.original.apply(this, arguments); + return packagedModule; + }; + + var normalizeModule = function(parentId, moduleName) { + // normalize plugin acequires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative acequires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + return moduleName; + }; + + /** + * Internal function to lookup moduleNames and resolve them by calling the + * definition function if needed. + */ + var lookup = function(parentId, moduleName) { + moduleName = normalizeModule(parentId, moduleName); + + var module = define.modules[moduleName]; + if (!module) { + module = define.payloads[moduleName]; + if (typeof module === 'function') { + var exports = {}; + var mod = { + id: moduleName, + uri: '', + exports: exports, + packaged: true + }; + + var req = function(module, callback) { + return _acequire(moduleName, module, callback); + }; + + var returnValue = module(req, exports, mod); + exports = returnValue || mod.exports; + define.modules[moduleName] = exports; + delete define.payloads[moduleName]; + } + module = define.modules[moduleName] = exports || module; + } + return module; + }; + + function exportAce(ns) { + var root = global; + if (ns) { + if (!global[ns]) + global[ns] = {}; + root = global[ns]; + } + + if (!root.define || !root.define.packaged) { + define.original = root.define; + root.define = define; + root.define.packaged = true; + } + + if (!root.acequire || !root.acequire.packaged) { + acequire.original = root.acequire; + root.acequire = acequire; + root.acequire.packaged = true; + } + } + + exportAce(ACE_NAMESPACE); + + })(); + + ace.define("ace/lib/regexp",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + if (!compliantLastIndexIncrement) { + RegExp.prototype.test = function (str) { + var match = real.exec.call(this, str); + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + + }); + + ace.define("ace/lib/es5-shim",["require","exports","module"], function(acequire, exports, module) { + + function Empty() {} + + if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + var target = this; + if (typeof target != "function") { + throw new TypeError("Function.prototype.bind called on incompatible " + target); + } + var args = slice.call(arguments, 1); // for normal call + var bound = function () { + + if (this instanceof bound) { + + var result = target.apply( + this, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return this; + + } else { + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + if(target.prototype) { + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; + } + var call = Function.prototype.call; + var prototypeOfArray = Array.prototype; + var prototypeOfObject = Object.prototype; + var slice = prototypeOfArray.slice; + var _toString = call.bind(prototypeOfObject.toString); + var owns = call.bind(prototypeOfObject.hasOwnProperty); + var defineGetter; + var defineSetter; + var lookupGetter; + var lookupSetter; + var supportsAccessors; + if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); + } + if ([1,2].splice(0).length != 2) { + if(function() { // test IE < 9 to splice bug - see issue #138 + function makeArray(l) { + var a = new Array(l+2); + a[0] = a[1] = 0; + return a; + } + var array = [], lengthBefore; + + array.splice.apply(array, makeArray(20)); + array.splice.apply(array, makeArray(26)); + + lengthBefore = array.length; //46 + array.splice(5, 0, "XXX"); // add one element + + lengthBefore + 1 == array.length + + if (lengthBefore + 1 == array.length) { + return true;// has right splice implementation without bugs + } + }()) {//IE 6/7 + var array_splice = Array.prototype.splice; + Array.prototype.splice = function(start, deleteCount) { + if (!arguments.length) { + return []; + } else { + return array_splice.apply(this, [ + start === void 0 ? 0 : start, + deleteCount === void 0 ? (this.length - start) : deleteCount + ].concat(slice.call(arguments, 2))) + } + }; + } else {//IE8 + Array.prototype.splice = function(pos, removeCount){ + var length = this.length; + if (pos > 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } + } + if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; + } + var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; + } + if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; + } + if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; + } + if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; + } + if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; + } + if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; + } + if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; + } + if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; + } + if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; + } + if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; + } + if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; + } + if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; + } + if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; + } + + function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } + } + if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } + } + + if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; + } + if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; + } + if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; + } + if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; + } + try { + Object.freeze(function () {}); + } catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); + } + if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; + } + if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; + } + if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; + } + if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; + } + if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + + } + if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; + } + var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; + if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; + } + + function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; + } + + function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); + } + + function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); + } + var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); + }; + + }); + + ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(acequire, exports, module) { + "use strict"; + + acequire("./regexp"); + acequire("./es5-shim"); + + }); + + ace.define("ace/lib/dom",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var XHTML_NS = "http://www.w3.org/1999/xhtml"; + + exports.getDocumentHead = function(doc) { + if (!doc) + doc = document; + return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; + }; + + exports.createElement = function(tag, ns) { + return document.createElementNS ? + document.createElementNS(ns || XHTML_NS, tag) : + document.createElement(tag); + }; + + exports.hasCssClass = function(el, name) { + var classes = (el.className + "").split(/\s+/g); + return classes.indexOf(name) !== -1; + }; + exports.addCssClass = function(el, name) { + if (!exports.hasCssClass(el, name)) { + el.className += " " + name; + } + }; + exports.removeCssClass = function(el, name) { + var classes = el.className.split(/\s+/g); + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + classes.splice(index, 1); + } + el.className = classes.join(" "); + }; + + exports.toggleCssClass = function(el, name) { + var classes = el.className.split(/\s+/g), add = true; + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + add = false; + classes.splice(index, 1); + } + if (add) + classes.push(name); + + el.className = classes.join(" "); + return add; + }; + exports.setCssClass = function(node, className, include) { + if (include) { + exports.addCssClass(node, className); + } else { + exports.removeCssClass(node, className); + } + }; + + exports.hasCssString = function(id, doc) { + var index = 0, sheets; + doc = doc || document; + + if (doc.createStyleSheet && (sheets = doc.styleSheets)) { + while (index < sheets.length) + if (sheets[index++].owningElement.id === id) return true; + } else if ((sheets = doc.getElementsByTagName("style"))) { + while (index < sheets.length) + if (sheets[index++].id === id) return true; + } + + return false; + }; + + exports.importCssString = function importCssString(cssText, id, doc) { + doc = doc || document; + if (id && exports.hasCssString(id, doc)) + return null; + + var style; + + if (id) + cssText += "\n/*# sourceURL=ace/css/" + id + " */"; + + if (doc.createStyleSheet) { + style = doc.createStyleSheet(); + style.cssText = cssText; + if (id) + style.owningElement.id = id; + } else { + style = exports.createElement("style"); + style.appendChild(doc.createTextNode(cssText)); + if (id) + style.id = id; + + exports.getDocumentHead(doc).appendChild(style); + } + }; + + exports.importCssStylsheet = function(uri, doc) { + if (doc.createStyleSheet) { + doc.createStyleSheet(uri); + } else { + var link = exports.createElement('link'); + link.rel = 'stylesheet'; + link.href = uri; + + exports.getDocumentHead(doc).appendChild(link); + } + }; + + exports.getInnerWidth = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingLeft"), 10) + + parseInt(exports.computedStyle(element, "paddingRight"), 10) + + element.clientWidth + ); + }; + + exports.getInnerHeight = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingTop"), 10) + + parseInt(exports.computedStyle(element, "paddingBottom"), 10) + + element.clientHeight + ); + }; + + exports.scrollbarWidth = function(document) { + var inner = exports.createElement("ace_inner"); + inner.style.width = "100%"; + inner.style.minWidth = "0px"; + inner.style.height = "200px"; + inner.style.display = "block"; + + var outer = exports.createElement("ace_outer"); + var style = outer.style; + + style.position = "absolute"; + style.left = "-10000px"; + style.overflow = "hidden"; + style.width = "200px"; + style.minWidth = "0px"; + style.height = "150px"; + style.display = "block"; + + outer.appendChild(inner); + + var body = document.documentElement; + body.appendChild(outer); + + var noScrollbar = inner.offsetWidth; + + style.overflow = "scroll"; + var withScrollbar = inner.offsetWidth; + + if (noScrollbar == withScrollbar) { + withScrollbar = outer.clientWidth; + } + + body.removeChild(outer); + + return noScrollbar-withScrollbar; + }; + + if (typeof document == "undefined") { + exports.importCssString = function() {}; + return; + } + + if (window.pageYOffset !== undefined) { + exports.getPageScrollTop = function() { + return window.pageYOffset; + }; + + exports.getPageScrollLeft = function() { + return window.pageXOffset; + }; + } + else { + exports.getPageScrollTop = function() { + return document.body.scrollTop; + }; + + exports.getPageScrollLeft = function() { + return document.body.scrollLeft; + }; + } + + if (window.getComputedStyle) + exports.computedStyle = function(element, style) { + if (style) + return (window.getComputedStyle(element, "") || {})[style] || ""; + return window.getComputedStyle(element, "") || {}; + }; + else + exports.computedStyle = function(element, style) { + if (style) + return element.currentStyle[style]; + return element.currentStyle; + }; + exports.setInnerHtml = function(el, innerHtml) { + var element = el.cloneNode(false);//document.createElement("div"); + element.innerHTML = innerHtml; + el.parentNode.replaceChild(element, el); + return element; + }; + + if ("textContent" in document.documentElement) { + exports.setInnerText = function(el, innerText) { + el.textContent = innerText; + }; + + exports.getInnerText = function(el) { + return el.textContent; + }; + } + else { + exports.setInnerText = function(el, innerText) { + el.innerText = innerText; + }; + + exports.getInnerText = function(el) { + return el.innerText; + }; + } + + exports.getParentWindow = function(document) { + return document.defaultView || document.parentWindow; + }; + + }); + + ace.define("ace/lib/oop",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + + exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; + }; + + exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); + }; + + }); + + ace.define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + acequire("./fixoldbrowsers"); + + var oop = acequire("./oop"); + var Keys = (function() { + var ret = { + MODIFIER_KEYS: { + 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta' + }, + + KEY_MODS: { + "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, + "super": 8, "meta": 8, "command": 8, "cmd": 8 + }, + + FUNCTION_KEYS : { + 8 : "Backspace", + 9 : "Tab", + 13 : "Return", + 19 : "Pause", + 27 : "Esc", + 32 : "Space", + 33 : "PageUp", + 34 : "PageDown", + 35 : "End", + 36 : "Home", + 37 : "Left", + 38 : "Up", + 39 : "Right", + 40 : "Down", + 44 : "Print", + 45 : "Insert", + 46 : "Delete", + 96 : "Numpad0", + 97 : "Numpad1", + 98 : "Numpad2", + 99 : "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", + '-13': "NumpadEnter", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "Numlock", + 145: "Scrolllock" + }, + + PRINTABLE_KEYS: { + 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', + 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a', + 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', + 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', + 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', + 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.', + 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', + 219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*' + } + }; + var name, i; + for (i in ret.FUNCTION_KEYS) { + name = ret.FUNCTION_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + for (i in ret.PRINTABLE_KEYS) { + name = ret.PRINTABLE_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + oop.mixin(ret, ret.MODIFIER_KEYS); + oop.mixin(ret, ret.PRINTABLE_KEYS); + oop.mixin(ret, ret.FUNCTION_KEYS); + ret.enter = ret["return"]; + ret.escape = ret.esc; + ret.del = ret["delete"]; + ret[173] = '-'; + + (function() { + var mods = ["cmd", "ctrl", "alt", "shift"]; + for (var i = Math.pow(2, mods.length); i--;) { + ret.KEY_MODS[i] = mods.filter(function(x) { + return i & ret.KEY_MODS[x]; + }).join("-") + "-"; + } + })(); + + ret.KEY_MODS[0] = ""; + ret.KEY_MODS[-1] = "input-"; + + return ret; + })(); + oop.mixin(exports, Keys); + + exports.keyCodeToString = function(keyCode) { + var keyString = Keys[keyCode]; + if (typeof keyString != "string") + keyString = String.fromCharCode(keyCode); + return keyString.toLowerCase(); + }; + + }); + + ace.define("ace/lib/useragent",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + exports.OS = { + LINUX: "LINUX", + MAC: "MAC", + WINDOWS: "WINDOWS" + }; + exports.getOS = function() { + if (exports.isMac) { + return exports.OS.MAC; + } else if (exports.isLinux) { + return exports.OS.LINUX; + } else { + return exports.OS.WINDOWS; + } + }; + if (typeof navigator != "object") + return; + + var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); + var ua = navigator.userAgent; + exports.isWin = (os == "win"); + exports.isMac = (os == "mac"); + exports.isLinux = (os == "linux"); + exports.isIE = + (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) + ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) + : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie + + exports.isOldIE = exports.isIE && exports.isIE < 9; + exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko"; + exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv:(\d+)/)||[])[1], 10) < 4; + exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; + exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; + + exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; + + exports.isAIR = ua.indexOf("AdobeAIR") >= 0; + + exports.isIPad = ua.indexOf("iPad") >= 0; + + exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; + + exports.isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; + + if (exports.isIOS) exports.isMac = true; + + }); + + ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var keys = acequire("./keys"); + var useragent = acequire("./useragent"); + + var pressedKeys = null; + var ts = 0; + + exports.addListener = function(elem, type, callback) { + if (elem.addEventListener) { + return elem.addEventListener(type, callback, false); + } + if (elem.attachEvent) { + var wrapper = function() { + callback.call(elem, window.event); + }; + callback._wrapper = wrapper; + elem.attachEvent("on" + type, wrapper); + } + }; + + exports.removeListener = function(elem, type, callback) { + if (elem.removeEventListener) { + return elem.removeEventListener(type, callback, false); + } + if (elem.detachEvent) { + elem.detachEvent("on" + type, callback._wrapper || callback); + } + }; + exports.stopEvent = function(e) { + exports.stopPropagation(e); + exports.preventDefault(e); + return false; + }; + + exports.stopPropagation = function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; + }; + + exports.preventDefault = function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; + }; + exports.getButton = function(e) { + if (e.type == "dblclick") + return 0; + if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) + return 2; + if (e.preventDefault) { + return e.button; + } + else { + return {1:0, 2:2, 4:1}[e.button]; + } + }; + + exports.capture = function(el, eventHandler, releaseCaptureHandler) { + function onMouseUp(e) { + eventHandler && eventHandler(e); + releaseCaptureHandler && releaseCaptureHandler(e); + + exports.removeListener(document, "mousemove", eventHandler, true); + exports.removeListener(document, "mouseup", onMouseUp, true); + exports.removeListener(document, "dragstart", onMouseUp, true); + } + + exports.addListener(document, "mousemove", eventHandler, true); + exports.addListener(document, "mouseup", onMouseUp, true); + exports.addListener(document, "dragstart", onMouseUp, true); + + return onMouseUp; + }; + + exports.addTouchMoveListener = function (el, callback) { + var startx, starty; + exports.addListener(el, "touchstart", function (e) { + var touches = e.touches; + var touchObj = touches[0]; + startx = touchObj.clientX; + starty = touchObj.clientY; + }); + exports.addListener(el, "touchmove", function (e) { + var touches = e.touches; + if (touches.length > 1) return; + + var touchObj = touches[0]; + + e.wheelX = startx - touchObj.clientX; + e.wheelY = starty - touchObj.clientY; + + startx = touchObj.clientX; + starty = touchObj.clientY; + + callback(e); + }); + }; + + exports.addMouseWheelListener = function(el, callback) { + if ("onmousewheel" in el) { + exports.addListener(el, "mousewheel", function(e) { + var factor = 8; + if (e.wheelDeltaX !== undefined) { + e.wheelX = -e.wheelDeltaX / factor; + e.wheelY = -e.wheelDeltaY / factor; + } else { + e.wheelX = 0; + e.wheelY = -e.wheelDelta / factor; + } + callback(e); + }); + } else if ("onwheel" in el) { + exports.addListener(el, "wheel", function(e) { + var factor = 0.35; + switch (e.deltaMode) { + case e.DOM_DELTA_PIXEL: + e.wheelX = e.deltaX * factor || 0; + e.wheelY = e.deltaY * factor || 0; + break; + case e.DOM_DELTA_LINE: + case e.DOM_DELTA_PAGE: + e.wheelX = (e.deltaX || 0) * 5; + e.wheelY = (e.deltaY || 0) * 5; + break; + } + + callback(e); + }); + } else { + exports.addListener(el, "DOMMouseScroll", function(e) { + if (e.axis && e.axis == e.HORIZONTAL_AXIS) { + e.wheelX = (e.detail || 0) * 5; + e.wheelY = 0; + } else { + e.wheelX = 0; + e.wheelY = (e.detail || 0) * 5; + } + callback(e); + }); + } + }; + + exports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) { + var clicks = 0; + var startX, startY, timer; + var eventNames = { + 2: "dblclick", + 3: "tripleclick", + 4: "quadclick" + }; + + function onMousedown(e) { + if (exports.getButton(e) !== 0) { + clicks = 0; + } else if (e.detail > 1) { + clicks++; + if (clicks > 4) + clicks = 1; + } else { + clicks = 1; + } + if (useragent.isIE) { + var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; + if (!timer || isNewClick) + clicks = 1; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600); + + if (clicks == 1) { + startX = e.clientX; + startY = e.clientY; + } + } + + e._clicks = clicks; + + eventHandler[callbackName]("mousedown", e); + + if (clicks > 4) + clicks = 0; + else if (clicks > 1) + return eventHandler[callbackName](eventNames[clicks], e); + } + function onDblclick(e) { + clicks = 2; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600); + eventHandler[callbackName]("mousedown", e); + eventHandler[callbackName](eventNames[clicks], e); + } + if (!Array.isArray(elements)) + elements = [elements]; + elements.forEach(function(el) { + exports.addListener(el, "mousedown", onMousedown); + if (useragent.isOldIE) + exports.addListener(el, "dblclick", onDblclick); + }); + }; + + var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) + ? function(e) { + return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); + } + : function(e) { + return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + }; + + exports.getModifierString = function(e) { + return keys.KEY_MODS[getModifierHash(e)]; + }; + + function normalizeCommandKeys(callback, e, keyCode) { + var hashId = getModifierHash(e); + + if (!useragent.isMac && pressedKeys) { + if (e.getModifierState && (e.getModifierState("OS") || e.getModifierState("Win"))) + hashId |= 8; + if (pressedKeys.altGr) { + if ((3 & hashId) != 3) + pressedKeys.altGr = 0; + else + return; + } + if (keyCode === 18 || keyCode === 17) { + var location = "location" in e ? e.location : e.keyLocation; + if (keyCode === 17 && location === 1) { + if (pressedKeys[keyCode] == 1) + ts = e.timeStamp; + } else if (keyCode === 18 && hashId === 3 && location === 2) { + var dt = e.timeStamp - ts; + if (dt < 50) + pressedKeys.altGr = true; + } + } + } + + if (keyCode in keys.MODIFIER_KEYS) { + keyCode = -1; + } + if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) { + keyCode = -1; + } + + if (!hashId && keyCode === 13) { + var location = "location" in e ? e.location : e.keyLocation; + if (location === 3) { + callback(e, hashId, -keyCode); + if (e.defaultPrevented) + return; + } + } + + if (useragent.isChromeOS && hashId & 8) { + callback(e, hashId, keyCode); + if (e.defaultPrevented) + return; + else + hashId &= ~8; + } + if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) { + return false; + } + + return callback(e, hashId, keyCode); + } + + + exports.addCommandKeyListener = function(el, callback) { + var addListener = exports.addListener; + if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { + var lastKeyDownKeyCode = null; + addListener(el, "keydown", function(e) { + lastKeyDownKeyCode = e.keyCode; + }); + addListener(el, "keypress", function(e) { + return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); + }); + } else { + var lastDefaultPrevented = null; + + addListener(el, "keydown", function(e) { + pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1; + var result = normalizeCommandKeys(callback, e, e.keyCode); + lastDefaultPrevented = e.defaultPrevented; + return result; + }); + + addListener(el, "keypress", function(e) { + if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) { + exports.stopEvent(e); + lastDefaultPrevented = null; + } + }); + + addListener(el, "keyup", function(e) { + pressedKeys[e.keyCode] = null; + }); + + if (!pressedKeys) { + resetPressedKeys(); + addListener(window, "focus", resetPressedKeys); + } + } + }; + function resetPressedKeys() { + pressedKeys = Object.create(null); + } + + if (typeof window == "object" && window.postMessage && !useragent.isOldIE) { + var postMessageId = 1; + exports.nextTick = function(callback, win) { + win = win || window; + var messageName = "zero-timeout-message-" + postMessageId; + exports.addListener(win, "message", function listener(e) { + if (e.data == messageName) { + exports.stopPropagation(e); + exports.removeListener(win, "message", listener); + callback(); + } + }); + win.postMessage(messageName, "*"); + }; + } + + + exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || window.oRequestAnimationFrame); + + if (exports.nextFrame) + exports.nextFrame = exports.nextFrame.bind(window); + else + exports.nextFrame = function(callback) { + setTimeout(callback, 17); + }; + }); + + ace.define("ace/lib/lang",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + exports.last = function(a) { + return a[a.length - 1]; + }; + + exports.stringReverse = function(string) { + return string.split("").reverse().join(""); + }; + + exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; + }; + + var trimBeginRegexp = /^\s\s*/; + var trimEndRegexp = /\s\s*$/; + + exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); + }; + + exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); + }; + + exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; + }; + + exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i PLACEHOLDER.length) + data = data.substr(9); + else if (data.substr(0, 4) == PLACEHOLDER.substr(0, 4)) + data = data.substr(4, data.length - PLACEHOLDER.length + 1); + else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) + data = data.slice(0, -1); + if (data == PLACEHOLDER.charAt(0)) { + } else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) + data = data.slice(0, -1); + + if (data) + host.onTextInput(data); + } + if (copied) { + copied = false; + } + if (afterContextMenu) + afterContextMenu = false; + }; + var onInput = function(e) { + if (inComposition) + return; + var data = text.value; + sendText(data); + resetValue(); + }; + + var handleClipboardData = function(e, data, forceIEMime) { + var clipboardData = e.clipboardData || window.clipboardData; + if (!clipboardData || BROKEN_SETDATA) + return; + var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain"; + try { + if (data) { + return clipboardData.setData(mime, data) !== false; + } else { + return clipboardData.getData(mime); + } + } catch(e) { + if (!forceIEMime) + return handleClipboardData(e, data, true); + } + }; + + var doCopy = function(e, isCut) { + var data = host.getCopyText(); + if (!data) + return event.preventDefault(e); + + if (handleClipboardData(e, data)) { + if (useragent.isIOS) { + cut = isCut; + text.value = "\n aa" + data + "a a\n"; + text.setSelectionRange(4, 4 + data.length); + copied = { + value: data + }; + } + isCut ? host.onCut() : host.onCopy(); + if (!useragent.isIOS) event.preventDefault(e); + } else { + copied = true; + text.value = data; + text.select(); + setTimeout(function(){ + copied = false; + resetValue(); + resetSelection(); + isCut ? host.onCut() : host.onCopy(); + }); + } + }; + + var onCut = function(e) { + doCopy(e, true); + }; + + var onCopy = function(e) { + doCopy(e, false); + }; + + var onPaste = function(e) { + var data = handleClipboardData(e); + if (typeof data == "string") { + if (data) + host.onPaste(data, e); + if (useragent.isIE) + setTimeout(resetSelection); + event.preventDefault(e); + } + else { + text.value = ""; + pasted = true; + } + }; + + event.addCommandKeyListener(text, host.onCommandKey.bind(host)); + + event.addListener(text, "select", onSelect); + + event.addListener(text, "input", onInput); + + event.addListener(text, "cut", onCut); + event.addListener(text, "copy", onCopy); + event.addListener(text, "paste", onPaste); + var onCompositionStart = function(e) { + if (inComposition || !host.onCompositionStart || host.$readOnly) + return; + inComposition = {}; + inComposition.canUndo = host.session.$undoManager; + host.onCompositionStart(); + setTimeout(onCompositionUpdate, 0); + host.on("mousedown", onCompositionEnd); + if (inComposition.canUndo && !host.selection.isEmpty()) { + host.insert(""); + host.session.markUndoGroup(); + host.selection.clearSelection(); + } + host.session.markUndoGroup(); + }; + + var onCompositionUpdate = function() { + if (!inComposition || !host.onCompositionUpdate || host.$readOnly) + return; + var val = text.value.replace(/\x01/g, ""); + if (inComposition.lastValue === val) return; + + host.onCompositionUpdate(val); + if (inComposition.lastValue) + host.undo(); + if (inComposition.canUndo) + inComposition.lastValue = val; + if (inComposition.lastValue) { + var r = host.selection.getRange(); + host.insert(inComposition.lastValue); + host.session.markUndoGroup(); + inComposition.range = host.selection.getRange(); + host.selection.setRange(r); + host.selection.clearSelection(); + } + }; + + var onCompositionEnd = function(e) { + if (!host.onCompositionEnd || host.$readOnly) return; + var c = inComposition; + inComposition = false; + var timer = setTimeout(function() { + timer = null; + var str = text.value.replace(/\x01/g, ""); + if (inComposition) + return; + else if (str == c.lastValue) + resetValue(); + else if (!c.lastValue && str) { + resetValue(); + sendText(str); + } + }); + inputHandler = function compositionInputHandler(str) { + if (timer) + clearTimeout(timer); + str = str.replace(/\x01/g, ""); + if (str == c.lastValue) + return ""; + if (c.lastValue && timer) + host.undo(); + return str; + }; + host.onCompositionEnd(); + host.removeListener("mousedown", onCompositionEnd); + if (e.type == "compositionend" && c.range) { + host.selection.setRange(c.range); + } + var needsOnInput = + (!!useragent.isChrome && useragent.isChrome >= 53) || + (!!useragent.isWebKit && useragent.isWebKit >= 603); + + if (needsOnInput) { + onInput(); + } + }; + + + + var syncComposition = lang.delayedCall(onCompositionUpdate, 50); + + event.addListener(text, "compositionstart", onCompositionStart); + if (useragent.isGecko) { + event.addListener(text, "text", function(){syncComposition.schedule();}); + } else { + event.addListener(text, "keyup", function(){syncComposition.schedule();}); + event.addListener(text, "keydown", function(){syncComposition.schedule();}); + } + event.addListener(text, "compositionend", onCompositionEnd); + + this.getElement = function() { + return text; + }; + + this.setReadOnly = function(readOnly) { + text.readOnly = readOnly; + }; + + this.onContextMenu = function(e) { + afterContextMenu = true; + resetSelection(host.selection.isEmpty()); + host._emit("nativecontextmenu", {target: host, domEvent: e}); + this.moveToMouse(e, true); + }; + + this.moveToMouse = function(e, bringToFront) { + if (!tempStyle) + tempStyle = text.style.cssText; + text.style.cssText = (bringToFront ? "z-index:100000;" : "") + + "height:" + text.style.height + ";" + + (useragent.isIE ? "opacity:0.1;" : ""); + + var rect = host.container.getBoundingClientRect(); + var style = dom.computedStyle(host.container); + var top = rect.top + (parseInt(style.borderTopWidth) || 0); + var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); + var maxTop = rect.bottom - top - text.clientHeight -2; + var move = function(e) { + text.style.left = e.clientX - left - 2 + "px"; + text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; + }; + move(e); + + if (e.type != "mousedown") + return; + + if (host.renderer.$keepTextAreaAtCursor) + host.renderer.$keepTextAreaAtCursor = null; + + clearTimeout(closeTimeout); + if (useragent.isWin) + event.capture(host.container, move, onContextMenuClose); + }; + + this.onContextMenuClose = onContextMenuClose; + var closeTimeout; + function onContextMenuClose() { + clearTimeout(closeTimeout); + closeTimeout = setTimeout(function () { + if (tempStyle) { + text.style.cssText = tempStyle; + tempStyle = ''; + } + if (host.renderer.$keepTextAreaAtCursor == null) { + host.renderer.$keepTextAreaAtCursor = true; + host.renderer.$moveTextAreaToCursor(); + } + }, 0); + } + + var onContextMenu = function(e) { + host.textInput.onContextMenu(e); + onContextMenuClose(); + }; + event.addListener(text, "mouseup", onContextMenu); + event.addListener(text, "mousedown", function(e) { + e.preventDefault(); + onContextMenuClose(); + }); + event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); + event.addListener(text, "contextmenu", onContextMenu); + + if (useragent.isIOS) { + var typingResetTimeout = null; + var typing = false; + + parentNode.addEventListener("keydown", function (e) { + if (typingResetTimeout) clearTimeout(typingResetTimeout); + typing = true; + }); + + parentNode.addEventListener("keyup", function (e) { + typingResetTimeout = setTimeout(function () { + typing = false; + }, 100); + }); + var detectArrowKeys = function(e) { + if (document.activeElement !== text) return; + if (typing) return; + + if (cut) { + return setTimeout(function () { + cut = false; + }, 100); + } + var selectionStart = text.selectionStart; + var selectionEnd = text.selectionEnd; + text.setSelectionRange(4, 5); + if (selectionStart == selectionEnd) { + switch (selectionStart) { + case 0: host.onCommandKey(null, 0, KEYS.up); break; + case 1: host.onCommandKey(null, 0, KEYS.home); break; + case 2: host.onCommandKey(null, MODS.option, KEYS.left); break; + case 4: host.onCommandKey(null, 0, KEYS.left); break; + case 5: host.onCommandKey(null, 0, KEYS.right); break; + case 7: host.onCommandKey(null, MODS.option, KEYS.right); break; + case 8: host.onCommandKey(null, 0, KEYS.end); break; + case 9: host.onCommandKey(null, 0, KEYS.down); break; + } + } else { + switch (selectionEnd) { + case 6: host.onCommandKey(null, MODS.shift, KEYS.right); break; + case 7: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.right); break; + case 8: host.onCommandKey(null, MODS.shift, KEYS.end); break; + case 9: host.onCommandKey(null, MODS.shift, KEYS.down); break; + } + switch (selectionStart) { + case 0: host.onCommandKey(null, MODS.shift, KEYS.up); break; + case 1: host.onCommandKey(null, MODS.shift, KEYS.home); break; + case 2: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.left); break; + case 3: host.onCommandKey(null, MODS.shift, KEYS.left); break; + } + } + }; + document.addEventListener("selectionchange", detectArrowKeys); + host.on("destroy", function() { + document.removeEventListener("selectionchange", detectArrowKeys); + }); + } + }; + + exports.TextInput = TextInput; + }); + + ace.define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/keyboard/textinput_ios"], function(acequire, exports, module) { + "use strict"; + + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var BROKEN_SETDATA = useragent.isChrome < 18; + var USE_IE_MIME_TYPE = useragent.isIE; + + var TextInputIOS = acequire("./textinput_ios").TextInput; + var TextInput = function(parentNode, host) { + if (useragent.isIOS) + return TextInputIOS.call(this, parentNode, host); + + var text = dom.createElement("textarea"); + text.className = "ace_text-input"; + + text.setAttribute("wrap", "off"); + text.setAttribute("autocorrect", "off"); + text.setAttribute("autocapitalize", "off"); + text.setAttribute("spellcheck", false); + + text.style.opacity = "0"; + parentNode.insertBefore(text, parentNode.firstChild); + + var PLACEHOLDER = "\u2028\u2028"; + + var copied = false; + var pasted = false; + var inComposition = false; + var tempStyle = ''; + var isSelectionEmpty = true; + try { var isFocused = document.activeElement === text; } catch(e) {} + + event.addListener(text, "blur", function(e) { + host.onBlur(e); + isFocused = false; + }); + event.addListener(text, "focus", function(e) { + isFocused = true; + host.onFocus(e); + resetSelection(); + }); + this.focus = function() { + if (tempStyle) return text.focus(); + var top = text.style.top; + text.style.position = "fixed"; + text.style.top = "0px"; + text.focus(); + setTimeout(function() { + text.style.position = ""; + if (text.style.top == "0px") + text.style.top = top; + }, 0); + }; + this.blur = function() { + text.blur(); + }; + this.isFocused = function() { + return isFocused; + }; + var syncSelection = lang.delayedCall(function() { + isFocused && resetSelection(isSelectionEmpty); + }); + var syncValue = lang.delayedCall(function() { + if (!inComposition) { + text.value = PLACEHOLDER; + isFocused && resetSelection(); + } + }); + + function resetSelection(isEmpty) { + if (inComposition) + return; + inComposition = true; + + if (inputHandler) { + var selectionStart = 0; + var selectionEnd = isEmpty ? 0 : text.value.length - 1; + } else { + var selectionStart = isEmpty ? 2 : 1; + var selectionEnd = 2; + } + try { + text.setSelectionRange(selectionStart, selectionEnd); + } catch(e){} + + inComposition = false; + } + + function resetValue() { + if (inComposition) + return; + text.value = PLACEHOLDER; + if (useragent.isWebKit) + syncValue.schedule(); + } + + useragent.isWebKit || host.addEventListener('changeSelection', function() { + if (host.selection.isEmpty() != isSelectionEmpty) { + isSelectionEmpty = !isSelectionEmpty; + syncSelection.schedule(); + } + }); + + resetValue(); + if (isFocused) + host.onFocus(); + + + var isAllSelected = function(text) { + return text.selectionStart === 0 && text.selectionEnd === text.value.length; + }; + + var onSelect = function(e) { + if (copied) { + copied = false; + } else if (isAllSelected(text)) { + host.selectAll(); + resetSelection(); + } else if (inputHandler) { + resetSelection(host.selection.isEmpty()); + } + }; + + var inputHandler = null; + this.setInputHandler = function(cb) {inputHandler = cb;}; + this.getInputHandler = function() {return inputHandler;}; + var afterContextMenu = false; + + var sendText = function(data) { + if (inputHandler) { + data = inputHandler(data); + inputHandler = null; + } + if (pasted) { + resetSelection(); + if (data) + host.onPaste(data); + pasted = false; + } else if (data == PLACEHOLDER.charAt(0)) { + if (afterContextMenu) + host.execCommand("del", {source: "ace"}); + else // some versions of android do not fire keydown when pressing backspace + host.execCommand("backspace", {source: "ace"}); + } else { + if (data.substring(0, 2) == PLACEHOLDER) + data = data.substr(2); + else if (data.charAt(0) == PLACEHOLDER.charAt(0)) + data = data.substr(1); + else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) + data = data.slice(0, -1); + if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0)) + data = data.slice(0, -1); + + if (data) + host.onTextInput(data); + } + if (afterContextMenu) + afterContextMenu = false; + }; + var onInput = function(e) { + if (inComposition) + return; + var data = text.value; + sendText(data); + resetValue(); + }; + + var handleClipboardData = function(e, data, forceIEMime) { + var clipboardData = e.clipboardData || window.clipboardData; + if (!clipboardData || BROKEN_SETDATA) + return; + var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain"; + try { + if (data) { + return clipboardData.setData(mime, data) !== false; + } else { + return clipboardData.getData(mime); + } + } catch(e) { + if (!forceIEMime) + return handleClipboardData(e, data, true); + } + }; + + var doCopy = function(e, isCut) { + var data = host.getCopyText(); + if (!data) + return event.preventDefault(e); + + if (handleClipboardData(e, data)) { + isCut ? host.onCut() : host.onCopy(); + event.preventDefault(e); + } else { + copied = true; + text.value = data; + text.select(); + setTimeout(function(){ + copied = false; + resetValue(); + resetSelection(); + isCut ? host.onCut() : host.onCopy(); + }); + } + }; + + var onCut = function(e) { + doCopy(e, true); + }; + + var onCopy = function(e) { + doCopy(e, false); + }; + + var onPaste = function(e) { + var data = handleClipboardData(e); + if (typeof data == "string") { + if (data) + host.onPaste(data, e); + if (useragent.isIE) + setTimeout(resetSelection); + event.preventDefault(e); + } + else { + text.value = ""; + pasted = true; + } + }; + + event.addCommandKeyListener(text, host.onCommandKey.bind(host)); + + event.addListener(text, "select", onSelect); + + event.addListener(text, "input", onInput); + + event.addListener(text, "cut", onCut); + event.addListener(text, "copy", onCopy); + event.addListener(text, "paste", onPaste); + if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)) { + event.addListener(parentNode, "keydown", function(e) { + if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) + return; + + switch (e.keyCode) { + case 67: + onCopy(e); + break; + case 86: + onPaste(e); + break; + case 88: + onCut(e); + break; + } + }); + } + var onCompositionStart = function(e) { + if (inComposition || !host.onCompositionStart || host.$readOnly) + return; + inComposition = {}; + inComposition.canUndo = host.session.$undoManager; + host.onCompositionStart(); + setTimeout(onCompositionUpdate, 0); + host.on("mousedown", onCompositionEnd); + if (inComposition.canUndo && !host.selection.isEmpty()) { + host.insert(""); + host.session.markUndoGroup(); + host.selection.clearSelection(); + } + host.session.markUndoGroup(); + }; + + var onCompositionUpdate = function() { + if (!inComposition || !host.onCompositionUpdate || host.$readOnly) + return; + var val = text.value.replace(/\u2028/g, ""); + if (inComposition.lastValue === val) return; + + host.onCompositionUpdate(val); + if (inComposition.lastValue) + host.undo(); + if (inComposition.canUndo) + inComposition.lastValue = val; + if (inComposition.lastValue) { + var r = host.selection.getRange(); + host.insert(inComposition.lastValue); + host.session.markUndoGroup(); + inComposition.range = host.selection.getRange(); + host.selection.setRange(r); + host.selection.clearSelection(); + } + }; + + var onCompositionEnd = function(e) { + if (!host.onCompositionEnd || host.$readOnly) return; + var c = inComposition; + inComposition = false; + var timer = setTimeout(function() { + timer = null; + var str = text.value.replace(/\u2028/g, ""); + if (inComposition) + return; + else if (str == c.lastValue) + resetValue(); + else if (!c.lastValue && str) { + resetValue(); + sendText(str); + } + }); + inputHandler = function compositionInputHandler(str) { + if (timer) + clearTimeout(timer); + str = str.replace(/\u2028/g, ""); + if (str == c.lastValue) + return ""; + if (c.lastValue && timer) + host.undo(); + return str; + }; + host.onCompositionEnd(); + host.removeListener("mousedown", onCompositionEnd); + if (e.type == "compositionend" && c.range) { + host.selection.setRange(c.range); + } + var needsOnInput = + (!!useragent.isChrome && useragent.isChrome >= 53) || + (!!useragent.isWebKit && useragent.isWebKit >= 603); + + if (needsOnInput) { + onInput(); + } + }; + + + + var syncComposition = lang.delayedCall(onCompositionUpdate, 50); + + event.addListener(text, "compositionstart", onCompositionStart); + if (useragent.isGecko) { + event.addListener(text, "text", function(){syncComposition.schedule();}); + } else { + event.addListener(text, "keyup", function(){syncComposition.schedule();}); + event.addListener(text, "keydown", function(){syncComposition.schedule();}); + } + event.addListener(text, "compositionend", onCompositionEnd); + + this.getElement = function() { + return text; + }; + + this.setReadOnly = function(readOnly) { + text.readOnly = readOnly; + }; + + this.onContextMenu = function(e) { + afterContextMenu = true; + resetSelection(host.selection.isEmpty()); + host._emit("nativecontextmenu", {target: host, domEvent: e}); + this.moveToMouse(e, true); + }; + + this.moveToMouse = function(e, bringToFront) { + if (!tempStyle) + tempStyle = text.style.cssText; + text.style.cssText = (bringToFront ? "z-index:100000;" : "") + + "height:" + text.style.height + ";" + + (useragent.isIE ? "opacity:0.1;" : ""); + + var rect = host.container.getBoundingClientRect(); + var style = dom.computedStyle(host.container); + var top = rect.top + (parseInt(style.borderTopWidth) || 0); + var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); + var maxTop = rect.bottom - top - text.clientHeight -2; + var move = function(e) { + text.style.left = e.clientX - left - 2 + "px"; + text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; + }; + move(e); + + if (e.type != "mousedown") + return; + + if (host.renderer.$keepTextAreaAtCursor) + host.renderer.$keepTextAreaAtCursor = null; + + clearTimeout(closeTimeout); + if (useragent.isWin) + event.capture(host.container, move, onContextMenuClose); + }; + + this.onContextMenuClose = onContextMenuClose; + var closeTimeout; + function onContextMenuClose() { + clearTimeout(closeTimeout); + closeTimeout = setTimeout(function () { + if (tempStyle) { + text.style.cssText = tempStyle; + tempStyle = ''; + } + if (host.renderer.$keepTextAreaAtCursor == null) { + host.renderer.$keepTextAreaAtCursor = true; + host.renderer.$moveTextAreaToCursor(); + } + }, 0); + } + + var onContextMenu = function(e) { + host.textInput.onContextMenu(e); + onContextMenuClose(); + }; + event.addListener(text, "mouseup", onContextMenu); + event.addListener(text, "mousedown", function(e) { + e.preventDefault(); + onContextMenuClose(); + }); + event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); + event.addListener(text, "contextmenu", onContextMenu); + }; + + exports.TextInput = TextInput; + }); + + ace.define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + + var DRAG_OFFSET = 0; // pixels + var SCROLL_COOLDOWN_T = 250; // milliseconds + + function DefaultHandlers(mouseHandler) { + mouseHandler.$clickSelection = null; + + var editor = mouseHandler.editor; + editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler)); + editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler)); + editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler)); + editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler)); + editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler)); + editor.setDefaultHandler("touchmove", this.onTouchMove.bind(mouseHandler)); + + var exports = ["select", "startSelect", "selectEnd", "selectAllEnd", "selectByWordsEnd", + "selectByLinesEnd", "dragWait", "dragWaitEnd", "focusWait"]; + + exports.forEach(function(x) { + mouseHandler[x] = this[x]; + }, this); + + mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange"); + mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange"); + } + + (function() { + + this.onMouseDown = function(ev) { + var inSelection = ev.inSelection(); + var pos = ev.getDocumentPosition(); + this.mousedownEvent = ev; + var editor = this.editor; + + var button = ev.getButton(); + if (button !== 0) { + var selectionRange = editor.getSelectionRange(); + var selectionEmpty = selectionRange.isEmpty(); + editor.$blockScrolling++; + if (selectionEmpty || button == 1) + editor.selection.moveToPosition(pos); + editor.$blockScrolling--; + if (button == 2) { + editor.textInput.onContextMenu(ev.domEvent); + if (!useragent.isMozilla) + ev.preventDefault(); + } + return; + } + + this.mousedownEvent.time = Date.now(); + if (inSelection && !editor.isFocused()) { + editor.focus(); + if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) { + this.setState("focusWait"); + this.captureMouse(ev); + return; + } + } + + this.captureMouse(ev); + this.startSelect(pos, ev.domEvent._clicks > 1); + return ev.preventDefault(); + }; + + this.startSelect = function(pos, waitForClickSelection) { + pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); + var editor = this.editor; + editor.$blockScrolling++; + if (this.mousedownEvent.getShiftKey()) + editor.selection.selectToPosition(pos); + else if (!waitForClickSelection) + editor.selection.moveToPosition(pos); + if (!waitForClickSelection) + this.select(); + if (editor.renderer.scroller.setCapture) { + editor.renderer.scroller.setCapture(); + } + editor.setStyle("ace_selecting"); + this.setState("select"); + editor.$blockScrolling--; + }; + + this.select = function() { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmp = this.$clickSelection.comparePoint(cursor); + + if (cmp == -1) { + anchor = this.$clickSelection.end; + } else if (cmp == 1) { + anchor = this.$clickSelection.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.extendSelectionBy = function(unitName) { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + var range = editor.selection[unitName](cursor.row, cursor.column); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmpStart = this.$clickSelection.comparePoint(range.start); + var cmpEnd = this.$clickSelection.comparePoint(range.end); + + if (cmpStart == -1 && cmpEnd <= 0) { + anchor = this.$clickSelection.end; + if (range.end.row != cursor.row || range.end.column != cursor.column) + cursor = range.start; + } else if (cmpEnd == 1 && cmpStart >= 0) { + anchor = this.$clickSelection.start; + if (range.start.row != cursor.row || range.start.column != cursor.column) + cursor = range.end; + } else if (cmpStart == -1 && cmpEnd == 1) { + cursor = range.end; + anchor = range.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.selectEnd = + this.selectAllEnd = + this.selectByWordsEnd = + this.selectByLinesEnd = function() { + this.$clickSelection = null; + this.editor.unsetStyle("ace_selecting"); + if (this.editor.renderer.scroller.releaseCapture) { + this.editor.renderer.scroller.releaseCapture(); + } + }; + + this.focusWait = function() { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + var time = Date.now(); + + if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) + this.startSelect(this.mousedownEvent.getDocumentPosition()); + }; + + this.onDoubleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + var session = editor.session; + + var range = session.getBracketRange(pos); + if (range) { + if (range.isEmpty()) { + range.start.column--; + range.end.column++; + } + this.setState("select"); + } else { + range = editor.selection.getWordRange(pos.row, pos.column); + this.setState("selectByWords"); + } + this.$clickSelection = range; + this.select(); + }; + + this.onTripleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + + this.setState("selectByLines"); + var range = editor.getSelectionRange(); + if (range.isMultiLine() && range.contains(pos.row, pos.column)) { + this.$clickSelection = editor.selection.getLineRange(range.start.row); + this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end; + } else { + this.$clickSelection = editor.selection.getLineRange(pos.row); + } + this.select(); + }; + + this.onQuadClick = function(ev) { + var editor = this.editor; + + editor.selectAll(); + this.$clickSelection = editor.getSelectionRange(); + this.setState("selectAll"); + }; + + this.onMouseWheel = function(ev) { + if (ev.getAccelKey()) + return; + if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) { + ev.wheelX = ev.wheelY; + ev.wheelY = 0; + } + + var editor = this.editor; + + if (!this.$lastScroll) + this.$lastScroll = { t: 0, vx: 0, vy: 0, allowed: 0 }; + + var prevScroll = this.$lastScroll; + var t = ev.domEvent.timeStamp; + var dt = t - prevScroll.t; + var vx = ev.wheelX / dt; + var vy = ev.wheelY / dt; + if (dt < SCROLL_COOLDOWN_T) { + vx = (vx + prevScroll.vx) / 2; + vy = (vy + prevScroll.vy) / 2; + } + + var direction = Math.abs(vx / vy); + + var canScroll = false; + if (direction >= 1 && editor.renderer.isScrollableBy(ev.wheelX * ev.speed, 0)) + canScroll = true; + if (direction <= 1 && editor.renderer.isScrollableBy(0, ev.wheelY * ev.speed)) + canScroll = true; + + if (canScroll) { + prevScroll.allowed = t; + } else if (t - prevScroll.allowed < SCROLL_COOLDOWN_T) { + var isSlower = Math.abs(vx) <= 1.1 * Math.abs(prevScroll.vx) + && Math.abs(vy) <= 1.1 * Math.abs(prevScroll.vy); + if (isSlower) { + canScroll = true; + prevScroll.allowed = t; + } + else { + prevScroll.allowed = 0; + } + } + + prevScroll.t = t; + prevScroll.vx = vx; + prevScroll.vy = vy; + + if (canScroll) { + editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + return ev.stop(); + } + }; + + this.onTouchMove = function(ev) { + this.editor._emit("mousewheel", ev); + }; + + }).call(DefaultHandlers.prototype); + + exports.DefaultHandlers = DefaultHandlers; + + function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); + } + + function calcRangeOrientation(range, cursor) { + if (range.start.row == range.end.row) + var cmp = 2 * cursor.column - range.start.column - range.end.column; + else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column) + var cmp = cursor.column - 4; + else + var cmp = 2 * cursor.row - range.start.row - range.end.row; + + if (cmp < 0) + return {cursor: range.start, anchor: range.end}; + else + return {cursor: range.end, anchor: range.start}; + } + + }); + + ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + function Tooltip (parentNode) { + this.isOpen = false; + this.$element = null; + this.$parentNode = parentNode; + } + + (function() { + this.$init = function() { + this.$element = dom.createElement("div"); + this.$element.className = "ace_tooltip"; + this.$element.style.display = "none"; + this.$parentNode.appendChild(this.$element); + return this.$element; + }; + this.getElement = function() { + return this.$element || this.$init(); + }; + this.setText = function(text) { + dom.setInnerText(this.getElement(), text); + }; + this.setHtml = function(html) { + this.getElement().innerHTML = html; + }; + this.setPosition = function(x, y) { + this.getElement().style.left = x + "px"; + this.getElement().style.top = y + "px"; + }; + this.setClassName = function(className) { + dom.addCssClass(this.getElement(), className); + }; + this.show = function(text, x, y) { + if (text != null) + this.setText(text); + if (x != null && y != null) + this.setPosition(x, y); + if (!this.isOpen) { + this.getElement().style.display = "block"; + this.isOpen = true; + } + }; + + this.hide = function() { + if (this.isOpen) { + this.getElement().style.display = "none"; + this.isOpen = false; + } + }; + this.getHeight = function() { + return this.getElement().offsetHeight; + }; + this.getWidth = function() { + return this.getElement().offsetWidth; + }; + + this.destroy = function() { + this.isOpen = false; + if (this.$element && this.$element.parentNode) { + this.$element.parentNode.removeChild(this.$element); + } + }; + + }).call(Tooltip.prototype); + + exports.Tooltip = Tooltip; + }); + + ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(acequire, exports, module) { + "use strict"; + var dom = acequire("../lib/dom"); + var oop = acequire("../lib/oop"); + var event = acequire("../lib/event"); + var Tooltip = acequire("../tooltip").Tooltip; + + function GutterHandler(mouseHandler) { + var editor = mouseHandler.editor; + var gutter = editor.renderer.$gutterLayer; + var tooltip = new GutterTooltip(editor.container); + + mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) { + if (!editor.isFocused() || e.getButton() != 0) + return; + var gutterRegion = gutter.getRegion(e); + + if (gutterRegion == "foldWidgets") + return; + + var row = e.getDocumentPosition().row; + var selection = editor.session.selection; + + if (e.getShiftKey()) + selection.selectTo(row, 0); + else { + if (e.domEvent.detail == 2) { + editor.selectAll(); + return e.preventDefault(); + } + mouseHandler.$clickSelection = editor.selection.getLineRange(row); + } + mouseHandler.setState("selectByLines"); + mouseHandler.captureMouse(e); + return e.preventDefault(); + }); + + + var tooltipTimeout, mouseEvent, tooltipAnnotation; + + function showTooltip() { + var row = mouseEvent.getDocumentPosition().row; + var annotation = gutter.$annotations[row]; + if (!annotation) + return hideTooltip(); + + var maxRow = editor.session.getLength(); + if (row == maxRow) { + var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row; + var pos = mouseEvent.$pos; + if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column)) + return hideTooltip(); + } + + if (tooltipAnnotation == annotation) + return; + tooltipAnnotation = annotation.text.join("
"); + + tooltip.setHtml(tooltipAnnotation); + tooltip.show(); + editor._signal("showGutterTooltip", tooltip); + editor.on("mousewheel", hideTooltip); + + if (mouseHandler.$tooltipFollowsMouse) { + moveTooltip(mouseEvent); + } else { + var gutterElement = mouseEvent.domEvent.target; + var rect = gutterElement.getBoundingClientRect(); + var style = tooltip.getElement().style; + style.left = rect.right + "px"; + style.top = rect.bottom + "px"; + } + } + + function hideTooltip() { + if (tooltipTimeout) + tooltipTimeout = clearTimeout(tooltipTimeout); + if (tooltipAnnotation) { + tooltip.hide(); + tooltipAnnotation = null; + editor._signal("hideGutterTooltip", tooltip); + editor.removeEventListener("mousewheel", hideTooltip); + } + } + + function moveTooltip(e) { + tooltip.setPosition(e.x, e.y); + } + + mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) { + var target = e.domEvent.target || e.domEvent.srcElement; + if (dom.hasCssClass(target, "ace_fold-widget")) + return hideTooltip(); + + if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse) + moveTooltip(e); + + mouseEvent = e; + if (tooltipTimeout) + return; + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + if (mouseEvent && !mouseHandler.isMousePressed) + showTooltip(); + else + hideTooltip(); + }, 50); + }); + + event.addListener(editor.renderer.$gutter, "mouseout", function(e) { + mouseEvent = null; + if (!tooltipAnnotation || tooltipTimeout) + return; + + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + hideTooltip(); + }, 50); + }); + + editor.on("changeSession", hideTooltip); + } + + function GutterTooltip(parentNode) { + Tooltip.call(this, parentNode); + } + + oop.inherits(GutterTooltip, Tooltip); + + (function(){ + this.setPosition = function(x, y) { + var windowWidth = window.innerWidth || document.documentElement.clientWidth; + var windowHeight = window.innerHeight || document.documentElement.clientHeight; + var width = this.getWidth(); + var height = this.getHeight(); + x += 15; + y += 15; + if (x + width > windowWidth) { + x -= (x + width) - windowWidth; + } + if (y + height > windowHeight) { + y -= 20 + height; + } + Tooltip.prototype.setPosition.call(this, x, y); + }; + + }).call(GutterTooltip.prototype); + + + + exports.GutterHandler = GutterHandler; + + }); + + ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + var MouseEvent = exports.MouseEvent = function(domEvent, editor) { + this.domEvent = domEvent; + this.editor = editor; + + this.x = this.clientX = domEvent.clientX; + this.y = this.clientY = domEvent.clientY; + + this.$pos = null; + this.$inSelection = null; + + this.propagationStopped = false; + this.defaultPrevented = false; + }; + + (function() { + + this.stopPropagation = function() { + event.stopPropagation(this.domEvent); + this.propagationStopped = true; + }; + + this.preventDefault = function() { + event.preventDefault(this.domEvent); + this.defaultPrevented = true; + }; + + this.stop = function() { + this.stopPropagation(); + this.preventDefault(); + }; + this.getDocumentPosition = function() { + if (this.$pos) + return this.$pos; + + this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY); + return this.$pos; + }; + this.inSelection = function() { + if (this.$inSelection !== null) + return this.$inSelection; + + var editor = this.editor; + + + var selectionRange = editor.getSelectionRange(); + if (selectionRange.isEmpty()) + this.$inSelection = false; + else { + var pos = this.getDocumentPosition(); + this.$inSelection = selectionRange.contains(pos.row, pos.column); + } + + return this.$inSelection; + }; + this.getButton = function() { + return event.getButton(this.domEvent); + }; + this.getShiftKey = function() { + return this.domEvent.shiftKey; + }; + + this.getAccelKey = useragent.isMac + ? function() { return this.domEvent.metaKey; } + : function() { return this.domEvent.ctrlKey; }; + + }).call(MouseEvent.prototype); + + }); + + ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + + var AUTOSCROLL_DELAY = 200; + var SCROLL_CURSOR_DELAY = 200; + var SCROLL_CURSOR_HYSTERESIS = 5; + + function DragdropHandler(mouseHandler) { + + var editor = mouseHandler.editor; + + var blankImage = dom.createElement("img"); + blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (useragent.isOpera) + blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;"; + + var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"]; + + exports.forEach(function(x) { + mouseHandler[x] = this[x]; + }, this); + editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler)); + + + var mouseTarget = editor.container; + var dragSelectionMarker, x, y; + var timerId, range; + var dragCursor, counter = 0; + var dragOperation; + var isInternal; + var autoScrollStartTime; + var cursorMovedTime; + var cursorPointOnCaretMoved; + + this.onDragStart = function(e) { + if (this.cancelDrag || !mouseTarget.draggable) { + var self = this; + setTimeout(function(){ + self.startSelect(); + self.captureMouse(e); + }, 0); + return e.preventDefault(); + } + range = editor.getSelectionRange(); + + var dataTransfer = e.dataTransfer; + dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove"; + if (useragent.isOpera) { + editor.container.appendChild(blankImage); + blankImage.scrollTop = 0; + } + dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0); + if (useragent.isOpera) { + editor.container.removeChild(blankImage); + } + dataTransfer.clearData(); + dataTransfer.setData("Text", editor.session.getTextRange()); + + isInternal = true; + this.setState("drag"); + }; + + this.onDragEnd = function(e) { + mouseTarget.draggable = false; + isInternal = false; + this.setState(null); + if (!editor.getReadOnly()) { + var dropEffect = e.dataTransfer.dropEffect; + if (!dragOperation && dropEffect == "move") + editor.session.remove(editor.getSelectionRange()); + editor.renderer.$cursorLayer.setBlinking(true); + } + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + }; + + this.onDragEnter = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) + addDragMarker(); + counter++; + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragOver = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) { + addDragMarker(); + counter++; + } + if (onMouseMoveTimer !== null) + onMouseMoveTimer = null; + + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragLeave = function(e) { + counter--; + if (counter <= 0 && dragSelectionMarker) { + clearDragMarker(); + dragOperation = null; + return event.preventDefault(e); + } + }; + + this.onDrop = function(e) { + if (!dragCursor) + return; + var dataTransfer = e.dataTransfer; + if (isInternal) { + switch (dragOperation) { + case "move": + if (range.contains(dragCursor.row, dragCursor.column)) { + range = { + start: dragCursor, + end: dragCursor + }; + } else { + range = editor.moveText(range, dragCursor); + } + break; + case "copy": + range = editor.moveText(range, dragCursor, true); + break; + } + } else { + var dropData = dataTransfer.getData('Text'); + range = { + start: dragCursor, + end: editor.session.insert(dragCursor, dropData) + }; + editor.focus(); + dragOperation = null; + } + clearDragMarker(); + return event.preventDefault(e); + }; + + event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler)); + event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler)); + event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler)); + event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler)); + event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler)); + event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler)); + + function scrollCursorIntoView(cursor, prevCursor) { + var now = Date.now(); + var vMovement = !prevCursor || cursor.row != prevCursor.row; + var hMovement = !prevCursor || cursor.column != prevCursor.column; + if (!cursorMovedTime || vMovement || hMovement) { + editor.$blockScrolling += 1; + editor.moveCursorToPosition(cursor); + editor.$blockScrolling -= 1; + cursorMovedTime = now; + cursorPointOnCaretMoved = {x: x, y: y}; + } else { + var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y); + if (distance > SCROLL_CURSOR_HYSTERESIS) { + cursorMovedTime = null; + } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) { + editor.renderer.scrollCursorIntoView(); + cursorMovedTime = null; + } + } + } + + function autoScroll(cursor, prevCursor) { + var now = Date.now(); + var lineHeight = editor.renderer.layerConfig.lineHeight; + var characterWidth = editor.renderer.layerConfig.characterWidth; + var editorRect = editor.renderer.scroller.getBoundingClientRect(); + var offsets = { + x: { + left: x - editorRect.left, + right: editorRect.right - x + }, + y: { + top: y - editorRect.top, + bottom: editorRect.bottom - y + } + }; + var nearestXOffset = Math.min(offsets.x.left, offsets.x.right); + var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom); + var scrollCursor = {row: cursor.row, column: cursor.column}; + if (nearestXOffset / characterWidth <= 2) { + scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2); + } + if (nearestYOffset / lineHeight <= 1) { + scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1); + } + var vScroll = cursor.row != scrollCursor.row; + var hScroll = cursor.column != scrollCursor.column; + var vMovement = !prevCursor || cursor.row != prevCursor.row; + if (vScroll || (hScroll && !vMovement)) { + if (!autoScrollStartTime) + autoScrollStartTime = now; + else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY) + editor.renderer.scrollCursorIntoView(scrollCursor); + } else { + autoScrollStartTime = null; + } + } + + function onDragInterval() { + var prevCursor = dragCursor; + dragCursor = editor.renderer.screenToTextCoordinates(x, y); + scrollCursorIntoView(dragCursor, prevCursor); + autoScroll(dragCursor, prevCursor); + } + + function addDragMarker() { + range = editor.selection.toOrientedRange(); + dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle()); + editor.clearSelection(); + if (editor.isFocused()) + editor.renderer.$cursorLayer.setBlinking(false); + clearInterval(timerId); + onDragInterval(); + timerId = setInterval(onDragInterval, 20); + counter = 0; + event.addListener(document, "mousemove", onMouseMove); + } + + function clearDragMarker() { + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + editor.$blockScrolling += 1; + editor.selection.fromOrientedRange(range); + editor.$blockScrolling -= 1; + if (editor.isFocused() && !isInternal) + editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly()); + range = null; + dragCursor = null; + counter = 0; + autoScrollStartTime = null; + cursorMovedTime = null; + event.removeListener(document, "mousemove", onMouseMove); + } + var onMouseMoveTimer = null; + function onMouseMove() { + if (onMouseMoveTimer == null) { + onMouseMoveTimer = setTimeout(function() { + if (onMouseMoveTimer != null && dragSelectionMarker) + clearDragMarker(); + }, 20); + } + } + + function canAccept(dataTransfer) { + var types = dataTransfer.types; + return !types || Array.prototype.some.call(types, function(type) { + return type == 'text/plain' || type == 'Text'; + }); + } + + function getDropEffect(e) { + var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized']; + var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized']; + + var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey; + var effectAllowed = "uninitialized"; + try { + effectAllowed = e.dataTransfer.effectAllowed.toLowerCase(); + } catch (e) {} + var dropEffect = "none"; + + if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + else if (moveAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "move"; + else if (copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + + return dropEffect; + } + } + + (function() { + + this.dragWait = function() { + var interval = Date.now() - this.mousedownEvent.time; + if (interval > this.editor.getDragDelay()) + this.startDrag(); + }; + + this.dragWaitEnd = function() { + var target = this.editor.container; + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + this.selectEnd(); + }; + + this.dragReadyEnd = function(e) { + this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()); + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + this.dragWaitEnd(); + }; + + this.startDrag = function(){ + this.cancelDrag = false; + var editor = this.editor; + var target = editor.container; + target.draggable = true; + editor.renderer.$cursorLayer.setBlinking(false); + editor.setStyle("ace_dragging"); + var cursorStyle = useragent.isWin ? "default" : "move"; + editor.renderer.setCursorStyle(cursorStyle); + this.setState("dragReady"); + }; + + this.onMouseDrag = function(e) { + var target = this.editor.container; + if (useragent.isIE && this.state == "dragReady") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 3) + target.dragDrop(); + } + if (this.state === "dragWait") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 0) { + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + } + } + }; + + this.onMouseDown = function(e) { + if (!this.$dragEnabled) + return; + this.mousedownEvent = e; + var editor = this.editor; + + var inSelection = e.inSelection(); + var button = e.getButton(); + var clickCount = e.domEvent.detail || 1; + if (clickCount === 1 && button === 0 && inSelection) { + if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey())) + return; + this.mousedownEvent.time = Date.now(); + var eventTarget = e.domEvent.target || e.domEvent.srcElement; + if ("unselectable" in eventTarget) + eventTarget.unselectable = "on"; + if (editor.getDragDelay()) { + if (useragent.isWebKit) { + this.cancelDrag = true; + var mouseTarget = editor.container; + mouseTarget.draggable = true; + } + this.setState("dragWait"); + } else { + this.startDrag(); + } + this.captureMouse(e, this.onMouseDrag.bind(this)); + e.defaultPrevented = true; + } + }; + + }).call(DragdropHandler.prototype); + + + function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); + } + + exports.DragdropHandler = DragdropHandler; + + }); + + ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + var dom = acequire("./dom"); + + exports.get = function (url, callback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + callback(xhr.responseText); + } + }; + xhr.send(null); + }; + + exports.loadScript = function(path, callback) { + var head = dom.getDocumentHead(); + var s = document.createElement('script'); + + s.src = path; + head.appendChild(s); + + s.onload = s.onreadystatechange = function(_, isAbort) { + if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { + s = s.onload = s.onreadystatechange = null; + if (!isAbort) + callback(); + } + }; + }; + exports.qualifyURL = function(url) { + var a = document.createElement('a'); + a.href = url; + return a.href; + }; + + }); + + ace.define("ace/lib/event_emitter",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var EventEmitter = {}; + var stopPropagation = function() { this.propagationStopped = true; }; + var preventDefault = function() { this.defaultPrevented = true; }; + + EventEmitter._emit = + EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i 1) + base = parts[parts.length - 2]; + var path = options[component + "Path"]; + if (path == null) { + path = options.basePath; + } else if (sep == "/") { + component = sep = ""; + } + if (path && path.slice(-1) != "/") + path += "/"; + return path + component + sep + base + this.get("suffix"); + }; + + exports.setModuleUrl = function(name, subst) { + return options.$moduleUrls[name] = subst; + }; + + exports.$loading = {}; + exports.loadModule = function(moduleName, onLoad) { + var module, moduleType; + if (Array.isArray(moduleName)) { + moduleType = moduleName[0]; + moduleName = moduleName[1]; + } + + try { + module = acequire(moduleName); + } catch (e) {} + if (module && !exports.$loading[moduleName]) + return onLoad && onLoad(module); + + if (!exports.$loading[moduleName]) + exports.$loading[moduleName] = []; + + exports.$loading[moduleName].push(onLoad); + + if (exports.$loading[moduleName].length > 1) + return; + + var afterLoad = function() { + acequire([moduleName], function(module) { + exports._emit("load.module", {name: moduleName, module: module}); + var listeners = exports.$loading[moduleName]; + exports.$loading[moduleName] = null; + listeners.forEach(function(onLoad) { + onLoad && onLoad(module); + }); + }); + }; + + if (!exports.get("packaged")) + return afterLoad(); + net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); + }; + init(true);function init(packaged) { + + if (!global || !global.document) + return; + + options.packaged = packaged || acequire.packaged || module.packaged || (global.define && __webpack_require__(67).packaged); + + var scriptOptions = {}; + var scriptUrl = ""; + var currentScript = (document.currentScript || document._currentScript ); // native or polyfill + var currentDocument = currentScript && currentScript.ownerDocument || document; + + var scripts = currentDocument.getElementsByTagName("script"); + for (var i=0; i 0){ + if (action == 0x10){ + for(i = condPos; i < ix; i++){ + levels[i] = 1; + } + condPos = -1; + } else { + condPos = -1; + } + } + cond = impTab[newState][6]; + if (cond){ + if(condPos == -1){ + condPos = ix; + } + }else{ + if (condPos > -1){ + for(i = condPos; i < ix; i++){ + levels[i] = newLevel; + } + condPos = -1; + } + } + if (charTypes[ix] == B){ + levels[ix] = 0; + } + hiLevel |= newLevel; + } + if (hasUBAT_S){ + for(i = 0; i < len; i++){ + if(charTypes[i] == S){ + levels[i] = dir; + for(var j = i - 1; j >= 0; j--){ + if(charTypes[j] == WS){ + levels[j] = dir; + }else{ + break; + } + } + } + } + } + } + + function _invertLevel(lev, levels, _array) { + if (hiLevel < lev){ + return; + } + if (lev == 1 && dir == RTL && !hasUBAT_B){ + _array.reverse(); + return; + } + var len = _array.length, start = 0, end, lo, hi, tmp; + while(start < len){ + if (levels[start] >= lev){ + end = start + 1; + while(end < len && levels[end] >= lev){ + end++; + } + for(lo = start, hi = end - 1 ; lo < hi; lo++, hi--){ + tmp = _array[lo]; + _array[lo] = _array[hi]; + _array[hi] = tmp; + } + start = end; + } + start++; + } + } + + function _getCharClass(chars, types, classes, ix) { + var cType = types[ix], wType, nType, len, i; + switch(cType){ + case L: + case R: + lastArabic = false; + case ON: + case AN: + return cType; + case EN: + return lastArabic ? AN : EN; + case AL: + lastArabic = true; + hasUBAT_AL = true; + return R; + case WS: + return ON; + case CS: + if (ix < 1 || (ix + 1) >= types.length || + ((wType = classes[ix - 1]) != EN && wType != AN) || + ((nType = types[ix + 1]) != EN && nType != AN)){ + return ON; + } + if (lastArabic){nType = AN;} + return nType == wType ? nType : ON; + case ES: + wType = ix > 0 ? classes[ix - 1] : B; + if (wType == EN && (ix + 1) < types.length && types[ix + 1] == EN){ + return EN; + } + return ON; + case ET: + if (ix > 0 && classes[ix - 1] == EN){ + return EN; + } + if (lastArabic){ + return ON; + } + i = ix + 1; + len = types.length; + while (i < len && types[i] == ET){ + i++; + } + if (i < len && types[i] == EN){ + return EN; + } + return ON; + case NSM: + len = types.length; + i = ix + 1; + while (i < len && types[i] == NSM){ + i++; + } + if (i < len){ + var c = chars[ix], rtlCandidate = (c >= 0x0591 && c <= 0x08FF) || c == 0xFB1E; + + wType = types[i]; + if (rtlCandidate && (wType == R || wType == AL)){ + return R; + } + } + + if (ix < 1 || (wType = types[ix - 1]) == B){ + return ON; + } + return classes[ix - 1]; + case B: + lastArabic = false; + hasUBAT_B = true; + return dir; + case S: + hasUBAT_S = true; + return ON; + case LRE: + case RLE: + case LRO: + case RLO: + case PDF: + lastArabic = false; + case BN: + return ON; + } + } + + function _getCharacterType( ch ) { + var uc = ch.charCodeAt(0), hi = uc >> 8; + + if (hi == 0) { + return ((uc > 0x00BF) ? L : UnicodeTBL00[uc]); + } else if (hi == 5) { + return (/[\u0591-\u05f4]/.test(ch) ? R : L); + } else if (hi == 6) { + if (/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(ch)) + return NSM; + else if (/[\u0660-\u0669\u066b-\u066c]/.test(ch)) + return AN; + else if (uc == 0x066A) + return ET; + else if (/[\u06f0-\u06f9]/.test(ch)) + return EN; + else + return AL; + } else if (hi == 0x20 && uc <= 0x205F) { + return UnicodeTBL20[uc & 0xFF]; + } else if (hi == 0xFE) { + return (uc >= 0xFE70 ? AL : ON); + } + return ON; + } + + function _isArabicDiacritics( ch ) { + return (ch >= '\u064b' && ch <= '\u0655'); + } + exports.L = L; + exports.R = R; + exports.EN = EN; + exports.ON_R = 3; + exports.AN = 4; + exports.R_H = 5; + exports.B = 6; + + exports.DOT = "\xB7"; + exports.doBidiReorder = function(text, textCharTypes, isRtl) { + if (text.length < 2) + return {}; + + var chars = text.split(""), logicalFromVisual = new Array(chars.length), + bidiLevels = new Array(chars.length), levels = []; + + dir = isRtl ? RTL : LTR; + + _computeLevels(chars, levels, chars.length, textCharTypes); + + for (var i = 0; i < logicalFromVisual.length; logicalFromVisual[i] = i, i++); + + _invertLevel(2, levels, logicalFromVisual); + _invertLevel(1, levels, logicalFromVisual); + + for (var i = 0; i < logicalFromVisual.length - 1; i++) { //fix levels to reflect character width + if (textCharTypes[i] === AN) { + levels[i] = exports.AN; + } else if (levels[i] === R && ((textCharTypes[i] > AL && textCharTypes[i] < LRE) + || textCharTypes[i] === ON || textCharTypes[i] === BN)) { + levels[i] = exports.ON_R; + } else if ((i > 0 && chars[i - 1] === '\u0644') && /\u0622|\u0623|\u0625|\u0627/.test(chars[i])) { + levels[i - 1] = levels[i] = exports.R_H; + i++; + } + } + if (chars[chars.length - 1] === exports.DOT) + levels[chars.length - 1] = exports.B; + + for (var i = 0; i < logicalFromVisual.length; i++) { + bidiLevels[i] = levels[logicalFromVisual[i]]; + } + + return {'logicalFromVisual': logicalFromVisual, 'bidiLevels': bidiLevels}; + }; + exports.hasBidiCharacters = function(text, textCharTypes){ + var ret = false; + for (var i = 0; i < text.length; i++){ + textCharTypes[i] = _getCharacterType(text.charAt(i)); + if (!ret && (textCharTypes[i] == R || textCharTypes[i] == AL)) + ret = true; + } + return ret; + }; + exports.getVisualFromLogicalIdx = function(logIdx, rowMap) { + for (var i = 0; i < rowMap.logicalFromVisual.length; i++) { + if (rowMap.logicalFromVisual[i] == logIdx) + return i; + } + return 0; + }; + + }); + + ace.define("ace/bidihandler",["require","exports","module","ace/lib/bidiutil","ace/lib/lang","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var bidiUtil = acequire("./lib/bidiutil"); + var lang = acequire("./lib/lang"); + var useragent = acequire("./lib/useragent"); + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var BidiHandler = function(session) { + this.session = session; + this.bidiMap = {}; + this.currentRow = null; + this.bidiUtil = bidiUtil; + this.charWidths = []; + this.EOL = "\xAC"; + this.showInvisibles = true; + this.isRtlDir = false; + this.line = ""; + this.wrapIndent = 0; + this.isLastRow = false; + this.EOF = "\xB6"; + this.seenBidi = false; + }; + + (function() { + this.isBidiRow = function(screenRow, docRow, splitIndex) { + if (!this.seenBidi) + return false; + if (screenRow !== this.currentRow) { + this.currentRow = screenRow; + this.updateRowLine(docRow, splitIndex); + this.updateBidiMap(); + } + return this.bidiMap.bidiLevels; + }; + + this.onChange = function(delta) { + if (!this.seenBidi) { + if (delta.action == "insert" && bidiRE.test(delta.lines.join("\n"))) { + this.seenBidi = true; + this.currentRow = null; + } + } + else { + this.currentRow = null; + } + }; + + this.getDocumentRow = function() { + var docRow = 0; + var rowCache = this.session.$screenRowCache; + if (rowCache.length) { + var index = this.session.$getRowCacheIndex(rowCache, this.currentRow); + if (index >= 0) + docRow = this.session.$docRowCache[index]; + } + + return docRow; + }; + + this.getSplitIndex = function() { + var splitIndex = 0; + var rowCache = this.session.$screenRowCache; + if (rowCache.length) { + var currentIndex, prevIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow); + while (this.currentRow - splitIndex > 0) { + currentIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow - splitIndex - 1); + if (currentIndex !== prevIndex) + break; + + prevIndex = currentIndex; + splitIndex++; + } + } + + return splitIndex; + }; + + this.updateRowLine = function(docRow, splitIndex) { + if (docRow === undefined) + docRow = this.getDocumentRow(); + + this.wrapIndent = 0; + this.isLastRow = (docRow === this.session.getLength() - 1); + this.line = this.session.getLine(docRow); + if (this.session.$useWrapMode) { + var splits = this.session.$wrapData[docRow]; + if (splits) { + if (splitIndex === undefined) + splitIndex = this.getSplitIndex(); + + if(splitIndex > 0 && splits.length) { + this.wrapIndent = splits.indent; + this.line = (splitIndex < splits.length) ? + this.line.substring(splits[splitIndex - 1], splits[splits.length - 1]) : + this.line.substring(splits[splits.length - 1]); + } else { + this.line = this.line.substring(0, splits[splitIndex]); + } + } + } + var session = this.session, shift = 0, size; + this.line = this.line.replace(/\t|[\u1100-\u2029, \u202F-\uFFE6]/g, function(ch, i){ + if (ch === '\t' || session.isFullWidth(ch.charCodeAt(0))) { + size = (ch === '\t') ? session.getScreenTabSize(i + shift) : 2; + shift += size - 1; + return lang.stringRepeat(bidiUtil.DOT, size); + } + return ch; + }); + }; + + this.updateBidiMap = function() { + var textCharTypes = [], endOfLine = this.isLastRow ? this.EOF : this.EOL; + var line = this.line + (this.showInvisibles ? endOfLine : bidiUtil.DOT); + if (bidiUtil.hasBidiCharacters(line, textCharTypes)) { + this.bidiMap = bidiUtil.doBidiReorder(line, textCharTypes, this.isRtlDir); + } else { + this.bidiMap = {}; + } + }; + this.markAsDirty = function() { + this.currentRow = null; + }; + this.updateCharacterWidths = function(fontMetrics) { + if (!this.seenBidi) + return; + if (this.characterWidth === fontMetrics.$characterSize.width) + return; + + var characterWidth = this.characterWidth = fontMetrics.$characterSize.width; + var bidiCharWidth = fontMetrics.$measureCharWidth("\u05d4"); + + this.charWidths[bidiUtil.L] = this.charWidths[bidiUtil.EN] = this.charWidths[bidiUtil.ON_R] = characterWidth; + this.charWidths[bidiUtil.R] = this.charWidths[bidiUtil.AN] = bidiCharWidth; + this.charWidths[bidiUtil.R_H] = useragent.isChrome ? bidiCharWidth : bidiCharWidth * 0.45; + this.charWidths[bidiUtil.B] = 0; + + this.currentRow = null; + }; + + this.getShowInvisibles = function() { + return this.showInvisibles; + }; + + this.setShowInvisibles = function(showInvisibles) { + this.showInvisibles = showInvisibles; + this.currentRow = null; + }; + + this.setEolChar = function(eolChar) { + this.EOL = eolChar; + }; + + this.setTextDir = function(isRtlDir) { + this.isRtlDir = isRtlDir; + }; + this.getPosLeft = function(col) { + col -= this.wrapIndent; + var visualIdx = bidiUtil.getVisualFromLogicalIdx(col > 0 ? col - 1 : 0, this.bidiMap), + levels = this.bidiMap.bidiLevels, left = 0; + + if (col === 0 && levels[visualIdx] % 2 !== 0) + visualIdx++; + + for (var i = 0; i < visualIdx; i++) { + left += this.charWidths[levels[i]]; + } + + if (col !== 0 && levels[visualIdx] % 2 === 0) + left += this.charWidths[levels[visualIdx]]; + + if (this.wrapIndent) + left += this.wrapIndent * this.charWidths[bidiUtil.L]; + + return left; + }; + this.getSelections = function(startCol, endCol) { + var map = this.bidiMap, levels = map.bidiLevels, level, offset = this.wrapIndent * this.charWidths[bidiUtil.L], selections = [], + selColMin = Math.min(startCol, endCol) - this.wrapIndent, selColMax = Math.max(startCol, endCol) - this.wrapIndent, + isSelected = false, isSelectedPrev = false, selectionStart = 0; + + for (var logIdx, visIdx = 0; visIdx < levels.length; visIdx++) { + logIdx = map.logicalFromVisual[visIdx]; + level = levels[visIdx]; + isSelected = (logIdx >= selColMin) && (logIdx < selColMax); + if (isSelected && !isSelectedPrev) { + selectionStart = offset; + } else if (!isSelected && isSelectedPrev) { + selections.push({left: selectionStart, width: offset - selectionStart}); + } + offset += this.charWidths[level]; + isSelectedPrev = isSelected; + } + + if (isSelected && (visIdx === levels.length)) { + selections.push({left: selectionStart, width: offset - selectionStart}); + } + + return selections; + }; + this.offsetToCol = function(posX) { + var logicalIdx = 0, posX = Math.max(posX, 0), + offset = 0, visualIdx = 0, levels = this.bidiMap.bidiLevels, + charWidth = this.charWidths[levels[visualIdx]]; + + if (this.wrapIndent) { + posX -= this.wrapIndent * this.charWidths[bidiUtil.L]; + } + + while(posX > offset + charWidth/2) { + offset += charWidth; + if(visualIdx === levels.length - 1) { + charWidth = 0; + break; + } + charWidth = this.charWidths[levels[++visualIdx]]; + } + + if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && (levels[visualIdx] % 2 === 0)){ + if(posX < offset) + visualIdx--; + logicalIdx = this.bidiMap.logicalFromVisual[visualIdx]; + + } else if (visualIdx > 0 && (levels[visualIdx - 1] % 2 === 0) && (levels[visualIdx] % 2 !== 0)){ + logicalIdx = 1 + ((posX > offset) ? this.bidiMap.logicalFromVisual[visualIdx] + : this.bidiMap.logicalFromVisual[visualIdx - 1]); + + } else if ((this.isRtlDir && visualIdx === levels.length - 1 && charWidth === 0 && (levels[visualIdx - 1] % 2 === 0)) + || (!this.isRtlDir && visualIdx === 0 && (levels[visualIdx] % 2 !== 0))){ + logicalIdx = 1 + this.bidiMap.logicalFromVisual[visualIdx]; + } else { + if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && charWidth !== 0) + visualIdx--; + logicalIdx = this.bidiMap.logicalFromVisual[visualIdx]; + } + + return (logicalIdx + this.wrapIndent); + }; + + }).call(BidiHandler.prototype); + + exports.BidiHandler = BidiHandler; + }); + + ace.define("ace/range",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + var comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; + }; + var Range = function(startRow, startColumn, endRow, endColumn) { + this.start = { + row: startRow, + column: startColumn + }; + + this.end = { + row: endRow, + column: endColumn + }; + }; + + (function() { + this.isEqual = function(range) { + return this.start.row === range.start.row && + this.end.row === range.end.row && + this.start.column === range.start.column && + this.end.column === range.end.column; + }; + this.toString = function() { + return ("Range: [" + this.start.row + "/" + this.start.column + + "] -> [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + } + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0); + else + return new Range(this.start.row, 0, this.end.row, 0); + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + + }).call(Range.prototype); + Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); + }; + Range.comparePoints = comparePoints; + + Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; + }; + + + exports.Range = Range; + }); + + ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var lang = acequire("./lib/lang"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Range = acequire("./range").Range; + var Selection = function(session) { + this.session = session; + this.doc = session.getDocument(); + + this.clearSelection(); + this.lead = this.selectionLead = this.doc.createAnchor(0, 0); + this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0); + + var self = this; + this.lead.on("change", function(e) { + self._emit("changeCursor"); + if (!self.$isEmpty) + self._emit("changeSelection"); + if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column) + self.$desiredColumn = null; + }); + + this.selectionAnchor.on("change", function() { + if (!self.$isEmpty) + self._emit("changeSelection"); + }); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.isEmpty = function() { + return (this.$isEmpty || ( + this.anchor.row == this.lead.row && + this.anchor.column == this.lead.column + )); + }; + this.isMultiLine = function() { + if (this.isEmpty()) { + return false; + } + + return this.getRange().isMultiLine(); + }; + this.getCursor = function() { + return this.lead.getPosition(); + }; + this.setSelectionAnchor = function(row, column) { + this.anchor.setPosition(row, column); + + if (this.$isEmpty) { + this.$isEmpty = false; + this._emit("changeSelection"); + } + }; + this.getSelectionAnchor = function() { + if (this.$isEmpty) + return this.getSelectionLead(); + else + return this.anchor.getPosition(); + }; + this.getSelectionLead = function() { + return this.lead.getPosition(); + }; + this.shiftSelection = function(columns) { + if (this.$isEmpty) { + this.moveCursorTo(this.lead.row, this.lead.column + columns); + return; + } + + var anchor = this.getSelectionAnchor(); + var lead = this.getSelectionLead(); + + var isBackwards = this.isBackwards(); + + if (!isBackwards || anchor.column !== 0) + this.setSelectionAnchor(anchor.row, anchor.column + columns); + + if (isBackwards || lead.column !== 0) { + this.$moveSelection(function() { + this.moveCursorTo(lead.row, lead.column + columns); + }); + } + }; + this.isBackwards = function() { + var anchor = this.anchor; + var lead = this.lead; + return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)); + }; + this.getRange = function() { + var anchor = this.anchor; + var lead = this.lead; + + if (this.isEmpty()) + return Range.fromPoints(lead, lead); + + if (this.isBackwards()) { + return Range.fromPoints(lead, anchor); + } + else { + return Range.fromPoints(anchor, lead); + } + }; + this.clearSelection = function() { + if (!this.$isEmpty) { + this.$isEmpty = true; + this._emit("changeSelection"); + } + }; + this.selectAll = function() { + var lastRow = this.doc.getLength() - 1; + this.setSelectionAnchor(0, 0); + this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); + }; + this.setRange = + this.setSelectionRange = function(range, reverse) { + if (reverse) { + this.setSelectionAnchor(range.end.row, range.end.column); + this.selectTo(range.start.row, range.start.column); + } else { + this.setSelectionAnchor(range.start.row, range.start.column); + this.selectTo(range.end.row, range.end.column); + } + if (this.getRange().isEmpty()) + this.$isEmpty = true; + this.$desiredColumn = null; + }; + + this.$moveSelection = function(mover) { + var lead = this.lead; + if (this.$isEmpty) + this.setSelectionAnchor(lead.row, lead.column); + + mover.call(this); + }; + this.selectTo = function(row, column) { + this.$moveSelection(function() { + this.moveCursorTo(row, column); + }); + }; + this.selectToPosition = function(pos) { + this.$moveSelection(function() { + this.moveCursorToPosition(pos); + }); + }; + this.moveTo = function(row, column) { + this.clearSelection(); + this.moveCursorTo(row, column); + }; + this.moveToPosition = function(pos) { + this.clearSelection(); + this.moveCursorToPosition(pos); + }; + this.selectUp = function() { + this.$moveSelection(this.moveCursorUp); + }; + this.selectDown = function() { + this.$moveSelection(this.moveCursorDown); + }; + this.selectRight = function() { + this.$moveSelection(this.moveCursorRight); + }; + this.selectLeft = function() { + this.$moveSelection(this.moveCursorLeft); + }; + this.selectLineStart = function() { + this.$moveSelection(this.moveCursorLineStart); + }; + this.selectLineEnd = function() { + this.$moveSelection(this.moveCursorLineEnd); + }; + this.selectFileEnd = function() { + this.$moveSelection(this.moveCursorFileEnd); + }; + this.selectFileStart = function() { + this.$moveSelection(this.moveCursorFileStart); + }; + this.selectWordRight = function() { + this.$moveSelection(this.moveCursorWordRight); + }; + this.selectWordLeft = function() { + this.$moveSelection(this.moveCursorWordLeft); + }; + this.getWordRange = function(row, column) { + if (typeof column == "undefined") { + var cursor = row || this.lead; + row = cursor.row; + column = cursor.column; + } + return this.session.getWordRange(row, column); + }; + this.selectWord = function() { + this.setSelectionRange(this.getWordRange()); + }; + this.selectAWord = function() { + var cursor = this.getCursor(); + var range = this.session.getAWordRange(cursor.row, cursor.column); + this.setSelectionRange(range); + }; + + this.getLineRange = function(row, excludeLastChar) { + var rowStart = typeof row == "number" ? row : this.lead.row; + var rowEnd; + + var foldLine = this.session.getFoldLine(rowStart); + if (foldLine) { + rowStart = foldLine.start.row; + rowEnd = foldLine.end.row; + } else { + rowEnd = rowStart; + } + if (excludeLastChar === true) + return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length); + else + return new Range(rowStart, 0, rowEnd + 1, 0); + }; + this.selectLine = function() { + this.setSelectionRange(this.getLineRange()); + }; + this.moveCursorUp = function() { + this.moveCursorBy(-1, 0); + }; + this.moveCursorDown = function() { + this.moveCursorBy(1, 0); + }; + this.wouldMoveIntoSoftTab = function(cursor, tabSize, direction) { + var start = cursor.column; + var end = cursor.column + tabSize; + + if (direction < 0) { + start = cursor.column - tabSize; + end = cursor.column; + } + return this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(start, end).split(" ").length-1 == tabSize; + }; + this.moveCursorLeft = function() { + var cursor = this.lead.getPosition(), + fold; + + if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + } else if (cursor.column === 0) { + if (cursor.row > 0) { + this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); + } + } + else { + var tabSize = this.session.getTabSize(); + if (this.wouldMoveIntoSoftTab(cursor, tabSize, -1) && !this.session.getNavigateWithinSoftTabs()) { + this.moveCursorBy(0, -tabSize); + } else { + this.moveCursorBy(0, -1); + } + } + }; + this.moveCursorRight = function() { + var cursor = this.lead.getPosition(), + fold; + if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { + this.moveCursorTo(fold.end.row, fold.end.column); + } + else if (this.lead.column == this.doc.getLine(this.lead.row).length) { + if (this.lead.row < this.doc.getLength() - 1) { + this.moveCursorTo(this.lead.row + 1, 0); + } + } + else { + var tabSize = this.session.getTabSize(); + var cursor = this.lead; + if (this.wouldMoveIntoSoftTab(cursor, tabSize, 1) && !this.session.getNavigateWithinSoftTabs()) { + this.moveCursorBy(0, tabSize); + } else { + this.moveCursorBy(0, 1); + } + } + }; + this.moveCursorLineStart = function() { + var row = this.lead.row; + var column = this.lead.column; + var screenRow = this.session.documentToScreenRow(row, column); + var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0); + var beforeCursor = this.session.getDisplayLine( + row, null, firstColumnPosition.row, + firstColumnPosition.column + ); + + var leadingSpace = beforeCursor.match(/^\s*/); + if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart) + firstColumnPosition.column += leadingSpace[0].length; + this.moveCursorToPosition(firstColumnPosition); + }; + this.moveCursorLineEnd = function() { + var lead = this.lead; + var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column); + if (this.lead.column == lineEnd.column) { + var line = this.session.getLine(lineEnd.row); + if (lineEnd.column == line.length) { + var textEnd = line.search(/\s+$/); + if (textEnd > 0) + lineEnd.column = textEnd; + } + } + + this.moveCursorTo(lineEnd.row, lineEnd.column); + }; + this.moveCursorFileEnd = function() { + var row = this.doc.getLength() - 1; + var column = this.doc.getLine(row).length; + this.moveCursorTo(row, column); + }; + this.moveCursorFileStart = function() { + this.moveCursorTo(0, 0); + }; + this.moveCursorLongWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + this.moveCursorTo(fold.end.row, fold.end.column); + return; + } + if (match = this.session.nonTokenRe.exec(rightOfCursor)) { + column += this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; + rightOfCursor = line.substring(column); + } + if (column >= line.length) { + this.moveCursorTo(row, line.length); + this.moveCursorRight(); + if (row < this.doc.getLength() - 1) + this.moveCursorWordRight(); + return; + } + if (match = this.session.tokenRe.exec(rightOfCursor)) { + column += this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + this.moveCursorLongWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + return; + } + + var str = this.session.getFoldStringAt(row, column, -1); + if (str == null) { + str = this.doc.getLine(row).substring(0, column); + } + + var leftOfCursor = lang.stringReverse(str); + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + if (match = this.session.nonTokenRe.exec(leftOfCursor)) { + column -= this.session.nonTokenRe.lastIndex; + leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); + this.session.nonTokenRe.lastIndex = 0; + } + if (column <= 0) { + this.moveCursorTo(row, 0); + this.moveCursorLeft(); + if (row > 0) + this.moveCursorWordLeft(); + return; + } + if (match = this.session.tokenRe.exec(leftOfCursor)) { + column -= this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + + this.$shortWordEndIndex = function(rightOfCursor) { + var match, index = 0, ch; + var whitespaceRe = /\s/; + var tokenRe = this.session.tokenRe; + + tokenRe.lastIndex = 0; + if (match = this.session.tokenRe.exec(rightOfCursor)) { + index = this.session.tokenRe.lastIndex; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + + if (index < 1) { + tokenRe.lastIndex = 0; + while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) { + tokenRe.lastIndex = 0; + index ++; + if (whitespaceRe.test(ch)) { + if (index > 2) { + index--; + break; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + if (index > 2) + break; + } + } + } + } + } + tokenRe.lastIndex = 0; + + return index; + }; + + this.moveCursorShortWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var fold = this.session.getFoldAt(row, column, 1); + if (fold) + return this.moveCursorTo(fold.end.row, fold.end.column); + + if (column == line.length) { + var l = this.doc.getLength(); + do { + row++; + rightOfCursor = this.doc.getLine(row); + } while (row < l && /^\s*$/.test(rightOfCursor)); + + if (!/^\s+/.test(rightOfCursor)) + rightOfCursor = ""; + column = 0; + } + + var index = this.$shortWordEndIndex(rightOfCursor); + + this.moveCursorTo(row, column + index); + }; + + this.moveCursorShortWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) + return this.moveCursorTo(fold.start.row, fold.start.column); + + var line = this.session.getLine(row).substring(0, column); + if (column === 0) { + do { + row--; + line = this.doc.getLine(row); + } while (row > 0 && /^\s*$/.test(line)); + + column = line.length; + if (!/\s+$/.test(line)) + line = ""; + } + + var leftOfCursor = lang.stringReverse(line); + var index = this.$shortWordEndIndex(leftOfCursor); + + return this.moveCursorTo(row, column - index); + }; + + this.moveCursorWordRight = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordRight(); + else + this.moveCursorShortWordRight(); + }; + + this.moveCursorWordLeft = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordLeft(); + else + this.moveCursorShortWordLeft(); + }; + this.moveCursorBy = function(rows, chars) { + var screenPos = this.session.documentToScreenPosition( + this.lead.row, + this.lead.column + ); + + var offsetX; + + if (chars === 0) { + if (rows !== 0) { + if (this.session.$bidiHandler.isBidiRow(screenPos.row, this.lead.row)) { + offsetX = this.session.$bidiHandler.getPosLeft(screenPos.column); + screenPos.column = Math.round(offsetX / this.session.$bidiHandler.charWidths[0]); + } else { + offsetX = screenPos.column * this.session.$bidiHandler.charWidths[0]; + } + } + + if (this.$desiredColumn) + screenPos.column = this.$desiredColumn; + else + this.$desiredColumn = screenPos.column; + } + + var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column, offsetX); + + if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) { + if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) { + if (docPos.row > 0 || rows > 0) + docPos.row++; + } + } + this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0); + }; + this.moveCursorToPosition = function(position) { + this.moveCursorTo(position.row, position.column); + }; + this.moveCursorTo = function(row, column, keepDesiredColumn) { + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + row = fold.start.row; + column = fold.start.column; + } + + this.$keepDesiredColumnOnChange = true; + var line = this.session.getLine(row); + if (/[\uDC00-\uDFFF]/.test(line.charAt(column)) && line.charAt(column - 1)) { + if (this.lead.row == row && this.lead.column == column + 1) + column = column - 1; + else + column = column + 1; + } + this.lead.setPosition(row, column); + this.$keepDesiredColumnOnChange = false; + + if (!keepDesiredColumn) + this.$desiredColumn = null; + }; + this.moveCursorToScreen = function(row, column, keepDesiredColumn) { + var pos = this.session.screenToDocumentPosition(row, column); + this.moveCursorTo(pos.row, pos.column, keepDesiredColumn); + }; + this.detach = function() { + this.lead.detach(); + this.anchor.detach(); + this.session = this.doc = null; + }; + + this.fromOrientedRange = function(range) { + this.setSelectionRange(range, range.cursor == range.start); + this.$desiredColumn = range.desiredColumn || this.$desiredColumn; + }; + + this.toOrientedRange = function(range) { + var r = this.getRange(); + if (range) { + range.start.column = r.start.column; + range.start.row = r.start.row; + range.end.column = r.end.column; + range.end.row = r.end.row; + } else { + range = r; + } + + range.cursor = this.isBackwards() ? range.start : range.end; + range.desiredColumn = this.$desiredColumn; + return range; + }; + this.getRangeOfMovements = function(func) { + var start = this.getCursor(); + try { + func(this); + var end = this.getCursor(); + return Range.fromPoints(start,end); + } catch(e) { + return Range.fromPoints(start,start); + } finally { + this.moveCursorToPosition(start); + } + }; + + this.toJSON = function() { + if (this.rangeCount) { + var data = this.ranges.map(function(r) { + var r1 = r.clone(); + r1.isBackwards = r.cursor == r.start; + return r1; + }); + } else { + var data = this.getRange(); + data.isBackwards = this.isBackwards(); + } + return data; + }; + + this.fromJSON = function(data) { + if (data.start == undefined) { + if (this.rangeList) { + this.toSingleRange(data[0]); + for (var i = data.length; i--; ) { + var r = Range.fromPoints(data[i].start, data[i].end); + if (data[i].isBackwards) + r.cursor = r.start; + this.addRange(r, true); + } + return; + } else + data = data[0]; + } + if (this.rangeList) + this.toSingleRange(data); + this.setSelectionRange(data, data.isBackwards); + }; + + this.isEqual = function(data) { + if ((data.length || this.rangeCount) && data.length != this.rangeCount) + return false; + if (!data.length || !this.ranges) + return this.getRange().isEqual(data); + + for (var i = this.ranges.length; i--; ) { + if (!this.ranges[i].isEqual(data[i])) + return false; + } + return true; + }; + + }).call(Selection.prototype); + + exports.Selection = Selection; + }); + + ace.define("ace/tokenizer",["require","exports","module","ace/config"], function(acequire, exports, module) { + "use strict"; + + var config = acequire("./config"); + var MAX_TOKEN_COUNT = 2000; + var Tokenizer = function(rules) { + this.states = rules; + + this.regExps = {}; + this.matchMappings = {}; + for (var key in this.states) { + var state = this.states[key]; + var ruleRegExps = []; + var matchTotal = 0; + var mapping = this.matchMappings[key] = {defaultToken: "text"}; + var flag = "g"; + + var splitterRurles = []; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.defaultToken) + mapping.defaultToken = rule.defaultToken; + if (rule.caseInsensitive) + flag = "gi"; + if (rule.regex == null) + continue; + + if (rule.regex instanceof RegExp) + rule.regex = rule.regex.toString().slice(1, -1); + var adjustedregex = rule.regex; + var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; + if (Array.isArray(rule.token)) { + if (rule.token.length == 1 || matchcount == 1) { + rule.token = rule.token[0]; + } else if (matchcount - 1 != rule.token.length) { + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; + } else { + rule.tokenArray = rule.token; + rule.token = null; + rule.onMatch = this.$arrayTokens; + } + } else if (typeof rule.token == "function" && !rule.onMatch) { + if (matchcount > 1) + rule.onMatch = this.$applyToken; + else + rule.onMatch = rule.token; + } + + if (matchcount > 1) { + if (/\\\d/.test(rule.regex)) { + adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) { + return "\\" + (parseInt(digit, 10) + matchTotal + 1); + }); + } else { + matchcount = 1; + adjustedregex = this.removeCapturingGroups(rule.regex); + } + if (!rule.splitRegex && typeof rule.token != "string") + splitterRurles.push(rule); // flag will be known only at the very end + } + + mapping[matchTotal] = i; + matchTotal += matchcount; + + ruleRegExps.push(adjustedregex); + if (!rule.onMatch) + rule.onMatch = null; + } + + if (!ruleRegExps.length) { + mapping[0] = 0; + ruleRegExps.push("$"); + } + + splitterRurles.forEach(function(rule) { + rule.splitRegex = this.createSplitterRegexp(rule.regex, flag); + }, this); + + this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag); + } + }; + + (function() { + this.$setMaxTokenCount = function(m) { + MAX_TOKEN_COUNT = m | 0; + }; + + this.$applyToken = function(str) { + var values = this.splitRegex.exec(str).slice(1); + var types = this.token.apply(this, values); + if (typeof types === "string") + return [{type: types, value: str}]; + + var tokens = []; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i]) + tokens[tokens.length] = { + type: types[i], + value: values[i] + }; + } + return tokens; + }; + + this.$arrayTokens = function(str) { + if (!str) + return []; + var values = this.splitRegex.exec(str); + if (!values) + return "text"; + var tokens = []; + var types = this.tokenArray; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i + 1]) + tokens[tokens.length] = { + type: types[i], + value: values[i + 1] + }; + } + return tokens; + }; + + this.removeCapturingGroups = function(src) { + var r = src.replace( + /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g, + function(x, y) {return y ? "(?:" : x;} + ); + return r; + }; + + this.createSplitterRegexp = function(src, flag) { + if (src.indexOf("(?=") != -1) { + var stack = 0; + var inChClass = false; + var lastCapture = {}; + src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function( + m, esc, parenOpen, parenClose, square, index + ) { + if (inChClass) { + inChClass = square != "]"; + } else if (square) { + inChClass = true; + } else if (parenClose) { + if (stack == lastCapture.stack) { + lastCapture.end = index+1; + lastCapture.stack = -1; + } + stack--; + } else if (parenOpen) { + stack++; + if (parenOpen.length != 1) { + lastCapture.stack = stack; + lastCapture.start = index; + } + } + return m; + }); + + if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end))) + src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end); + } + if (src.charAt(0) != "^") src = "^" + src; + if (src.charAt(src.length - 1) != "$") src += "$"; + + return new RegExp(src, (flag||"").replace("g", "")); + }; + this.getLineTokens = function(line, startState) { + if (startState && typeof startState != "string") { + var stack = startState.slice(0); + startState = stack[0]; + if (startState === "#tmp") { + stack.shift(); + startState = stack.shift(); + } + } else + var stack = []; + + var currentState = startState || "start"; + var state = this.states[currentState]; + if (!state) { + currentState = "start"; + state = this.states[currentState]; + } + var mapping = this.matchMappings[currentState]; + var re = this.regExps[currentState]; + re.lastIndex = 0; + + var match, tokens = []; + var lastIndex = 0; + var matchAttempts = 0; + + var token = {type: null, value: ""}; + + while (match = re.exec(line)) { + var type = mapping.defaultToken; + var rule = null; + var value = match[0]; + var index = re.lastIndex; + + if (index - value.length > lastIndex) { + var skipped = line.substring(lastIndex, index - value.length); + if (token.type == type) { + token.value += skipped; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: skipped}; + } + } + + for (var i = 0; i < match.length-2; i++) { + if (match[i + 1] === undefined) + continue; + + rule = state[mapping[i]]; + + if (rule.onMatch) + type = rule.onMatch(value, currentState, stack, line); + else + type = rule.token; + + if (rule.next) { + if (typeof rule.next == "string") { + currentState = rule.next; + } else { + currentState = rule.next(currentState, stack); + } + + state = this.states[currentState]; + if (!state) { + this.reportError("state doesn't exist", currentState); + currentState = "start"; + state = this.states[currentState]; + } + mapping = this.matchMappings[currentState]; + lastIndex = index; + re = this.regExps[currentState]; + re.lastIndex = index; + } + if (rule.consumeLineEnd) + lastIndex = index; + break; + } + + if (value) { + if (typeof type === "string") { + if ((!rule || rule.merge !== false) && token.type === type) { + token.value += value; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: value}; + } + } else if (type) { + if (token.type) + tokens.push(token); + token = {type: null, value: ""}; + for (var i = 0; i < type.length; i++) + tokens.push(type[i]); + } + } + + if (lastIndex == line.length) + break; + + lastIndex = index; + + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } + while (lastIndex < line.length) { + if (token.type) + tokens.push(token); + token = { + value: line.substring(lastIndex, lastIndex += 2000), + type: "overflow" + }; + } + currentState = "start"; + stack = []; + break; + } + } + + if (token.type) + tokens.push(token); + + if (stack.length > 1) { + if (stack[0] !== currentState) + stack.unshift("#tmp", currentState); + } + return { + tokens : tokens, + state : stack.length ? stack : currentState + }; + }; + + this.reportError = config.reportError; + + }).call(Tokenizer.prototype); + + exports.Tokenizer = Tokenizer; + }); + + ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("../lib/lang"); + + var TextHighlightRules = function() { + + this.$rules = { + "start" : [{ + token : "empty_line", + regex : '^$' + }, { + defaultToken : "text" + }] + }; + }; + + (function() { + + this.addRules = function(rules, prefix) { + if (!prefix) { + for (var key in rules) + this.$rules[key] = rules[key]; + return; + } + for (var key in rules) { + var state = rules[key]; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.next || rule.onMatch) { + if (typeof rule.next == "string") { + if (rule.next.indexOf(prefix) !== 0) + rule.next = prefix + rule.next; + } + if (rule.nextState && rule.nextState.indexOf(prefix) !== 0) + rule.nextState = prefix + rule.nextState; + } + } + this.$rules[prefix + key] = state; + } + }; + + this.getRules = function() { + return this.$rules; + }; + + this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) { + var embedRules = typeof HighlightRules == "function" + ? new HighlightRules().getRules() + : HighlightRules; + if (states) { + for (var i = 0; i < states.length; i++) + states[i] = prefix + states[i]; + } else { + states = []; + for (var key in embedRules) + states.push(prefix + key); + } + + this.addRules(embedRules, prefix); + + if (escapeRules) { + var addRules = Array.prototype[append ? "push" : "unshift"]; + for (var i = 0; i < states.length; i++) + addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules)); + } + + if (!this.$embeds) + this.$embeds = []; + this.$embeds.push(prefix); + }; + + this.getEmbeds = function() { + return this.$embeds; + }; + + var pushState = function(currentState, stack) { + if (currentState != "start" || stack.length) + stack.unshift(this.nextState, currentState); + return this.nextState; + }; + var popState = function(currentState, stack) { + stack.shift(); + return stack.shift() || "start"; + }; + + this.normalizeRules = function() { + var id = 0; + var rules = this.$rules; + function processState(key) { + var state = rules[key]; + state.processed = true; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + var toInsert = null; + if (Array.isArray(rule)) { + toInsert = rule; + rule = {}; + } + if (!rule.regex && rule.start) { + rule.regex = rule.start; + if (!rule.next) + rule.next = []; + rule.next.push({ + defaultToken: rule.token + }, { + token: rule.token + ".end", + regex: rule.end || rule.start, + next: "pop" + }); + rule.token = rule.token + ".start"; + rule.push = true; + } + var next = rule.next || rule.push; + if (next && Array.isArray(next)) { + var stateName = rule.stateName; + if (!stateName) { + stateName = rule.token; + if (typeof stateName != "string") + stateName = stateName[0] || ""; + if (rules[stateName]) + stateName += id++; + } + rules[stateName] = next; + rule.next = stateName; + processState(stateName); + } else if (next == "pop") { + rule.next = popState; + } + + if (rule.push) { + rule.nextState = rule.next || rule.push; + rule.next = pushState; + delete rule.push; + } + + if (rule.rules) { + for (var r in rule.rules) { + if (rules[r]) { + if (rules[r].push) + rules[r].push.apply(rules[r], rule.rules[r]); + } else { + rules[r] = rule.rules[r]; + } + } + } + var includeName = typeof rule == "string" ? rule : rule.include; + if (includeName) { + if (Array.isArray(includeName)) + toInsert = includeName.map(function(x) { return rules[x]; }); + else + toInsert = rules[includeName]; + } + + if (toInsert) { + var args = [i, 1].concat(toInsert); + if (rule.noEscape) + args = args.filter(function(x) {return !x.next;}); + state.splice.apply(state, args); + i--; + } + + if (rule.keywordMap) { + rule.token = this.createKeywordMapper( + rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive + ); + delete rule.defaultToken; + } + } + } + Object.keys(rules).forEach(processState, this); + }; + + this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) { + var keywords = Object.create(null); + Object.keys(map).forEach(function(className) { + var a = map[className]; + if (ignoreCase) + a = a.toLowerCase(); + var list = a.split(splitChar || "|"); + for (var i = list.length; i--; ) + keywords[list[i]] = className; + }); + if (Object.getPrototypeOf(keywords)) { + keywords.__proto__ = null; + } + this.$keywordList = Object.keys(keywords); + map = null; + return ignoreCase + ? function(value) {return keywords[value.toLowerCase()] || defaultToken; } + : function(value) {return keywords[value] || defaultToken; }; + }; + + this.getKeywords = function() { + return this.$keywords; + }; + + }).call(TextHighlightRules.prototype); + + exports.TextHighlightRules = TextHighlightRules; + }); + + ace.define("ace/mode/behaviour",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + var Behaviour = function() { + this.$behaviours = {}; + }; + + (function () { + + this.add = function (name, action, callback) { + switch (undefined) { + case this.$behaviours: + this.$behaviours = {}; + case this.$behaviours[name]: + this.$behaviours[name] = {}; + } + this.$behaviours[name][action] = callback; + }; + + this.addBehaviours = function (behaviours) { + for (var key in behaviours) { + for (var action in behaviours[key]) { + this.add(key, action, behaviours[key][action]); + } + } + }; + + this.remove = function (name) { + if (this.$behaviours && this.$behaviours[name]) { + delete this.$behaviours[name]; + } + }; + + this.inherit = function (mode, filter) { + if (typeof mode === "function") { + var behaviours = new mode().getBehaviours(filter); + } else { + var behaviours = mode.getBehaviours(filter); + } + this.addBehaviours(behaviours); + }; + + this.getBehaviours = function (filter) { + if (!filter) { + return this.$behaviours; + } else { + var ret = {}; + for (var i = 0; i < filter.length; i++) { + if (this.$behaviours[filter[i]]) { + ret[filter[i]] = this.$behaviours[filter[i]]; + } + } + return ret; + } + }; + + }).call(Behaviour.prototype); + + exports.Behaviour = Behaviour; + }); + + ace.define("ace/token_iterator",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("./range").Range; + var TokenIterator = function(session, initialRow, initialColumn) { + this.$session = session; + this.$row = initialRow; + this.$rowTokens = session.getTokens(initialRow); + + var token = session.getTokenAt(initialRow, initialColumn); + this.$tokenIndex = token ? token.index : -1; + }; + + (function() { + this.stepBackward = function() { + this.$tokenIndex -= 1; + + while (this.$tokenIndex < 0) { + this.$row -= 1; + if (this.$row < 0) { + this.$row = 0; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = this.$rowTokens.length - 1; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.stepForward = function() { + this.$tokenIndex += 1; + var rowCount; + while (this.$tokenIndex >= this.$rowTokens.length) { + this.$row += 1; + if (!rowCount) + rowCount = this.$session.getLength(); + if (this.$row >= rowCount) { + this.$row = rowCount - 1; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = 0; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentToken = function () { + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentTokenRow = function () { + return this.$row; + }; + this.getCurrentTokenColumn = function() { + var rowTokens = this.$rowTokens; + var tokenIndex = this.$tokenIndex; + var column = rowTokens[tokenIndex].start; + if (column !== undefined) + return column; + + column = 0; + while (tokenIndex > 0) { + tokenIndex -= 1; + column += rowTokens[tokenIndex].value.length; + } + + return column; + }; + this.getCurrentTokenPosition = function() { + return {row: this.$row, column: this.getCurrentTokenColumn()}; + }; + this.getCurrentTokenRange = function() { + var token = this.$rowTokens[this.$tokenIndex]; + var column = this.getCurrentTokenColumn(); + return new Range(this.$row, column, this.$row, column + token.value.length); + }; + + }).call(TokenIterator.prototype); + + exports.TokenIterator = TokenIterator; + }); + + ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Behaviour = acequire("../behaviour").Behaviour; + var TokenIterator = acequire("../../token_iterator").TokenIterator; + var lang = acequire("../../lib/lang"); + + var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; + var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + + var context; + var contextCache = {}; + var defaultQuotes = {'"' : '"', "'" : "'"}; + + var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; + }; + + var getWrapped = function(selection, selected, opening, closing) { + var rowDiff = selection.end.row - selection.start.row; + return { + text: opening + selected + closing, + selection: [ + 0, + selection.start.column + 1, + rowDiff, + selection.end.column + (rowDiff ? 0 : 1) + ] + }; + }; + + var CstyleBehaviour = function(options) { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '{', '}'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode || options && options.braces) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '(', ')'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, '[', ']'); + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + var quotes = session.$mode.$quotes || defaultQuotes; + if (text.length == 1 && quotes[text]) { + if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1) + return; + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && (selected.length != 1 || !quotes[selected]) && editor.getWrapBehavioursEnabled()) { + return getWrapped(selection, selected, quote, quote); + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string|escape/.test(token.type); + var stringAfter = !rightToken || /string|escape/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + if (pair && /string\.end/.test(rightToken.type)) + pair = false; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + }; + + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } + }; + + + + oop.inherits(CstyleBehaviour, Behaviour); + + exports.CstyleBehaviour = CstyleBehaviour; + }); + + ace.define("ace/unicode",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + exports.packages = {}; + + addUnicodePackage({ + L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", + Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", + Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", + Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", + Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", + Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", + Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", + Me: "0488048906DE20DD-20E020E2-20E4A670-A672", + N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", + No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", + P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", + Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", + Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", + Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", + Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", + Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", + Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", + Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", + S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", + Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", + Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", + Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", + So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", + Z: "002000A01680180E2000-200A20282029202F205F3000", + Zs: "002000A01680180E2000-200A202F205F3000", + Zl: "2028", + Zp: "2029", + C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", + Cc: "0000-001F007F-009F", + Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", + Co: "E000-F8FF", + Cs: "D800-DFFF", + Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF" + }); + + function addUnicodePackage (pack) { + var codePoint = /\w{4}/g; + for (var name in pack) + exports.packages[name] = pack[name].replace(codePoint, "\\u$&"); + } + + }); + + ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour/cstyle","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Tokenizer = acequire("../tokenizer").Tokenizer; + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; + var unicode = acequire("../unicode"); + var lang = acequire("../lib/lang"); + var TokenIterator = acequire("../token_iterator").TokenIterator; + var Range = acequire("../range").Range; + + var Mode = function() { + this.HighlightRules = TextHighlightRules; + }; + + (function() { + this.$defaultBehaviour = new CstyleBehaviour(); + + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]|\\s])+", "g" + ); + + this.getTokenizer = function() { + if (!this.$tokenizer) { + this.$highlightRules = this.$highlightRules || new this.HighlightRules(this.$highlightRuleConfig); + this.$tokenizer = new Tokenizer(this.$highlightRules.getRules()); + } + return this.$tokenizer; + }; + + this.lineCommentStart = ""; + this.blockComment = ""; + + this.toggleCommentLines = function(state, session, startRow, endRow) { + var doc = session.doc; + + var ignoreBlankLines = true; + var shouldRemove = true; + var minIndent = Infinity; + var tabSize = session.getTabSize(); + var insertAtTabStop = false; + + if (!this.lineCommentStart) { + if (!this.blockComment) + return false; + var lineCommentStart = this.blockComment.start; + var lineCommentEnd = this.blockComment.end; + var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")"); + var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$"); + + var comment = function(line, i) { + if (testRemove(line, i)) + return; + if (!ignoreBlankLines || /\S/.test(line)) { + doc.insertInLine({row: i, column: line.length}, lineCommentEnd); + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + + var uncomment = function(line, i) { + var m; + if (m = line.match(regexpEnd)) + doc.removeInLine(i, line.length - m[0].length, line.length); + if (m = line.match(regexpStart)) + doc.removeInLine(i, m[1].length, m[0].length); + }; + + var testRemove = function(line, row) { + if (regexpStart.test(line)) + return true; + var tokens = session.getTokens(row); + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].type === "comment") + return true; + } + }; + } else { + if (Array.isArray(this.lineCommentStart)) { + var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|"); + var lineCommentStart = this.lineCommentStart[0]; + } else { + var regexpStart = lang.escapeRegExp(this.lineCommentStart); + var lineCommentStart = this.lineCommentStart; + } + regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?"); + + insertAtTabStop = session.getUseSoftTabs(); + + var uncomment = function(line, i) { + var m = line.match(regexpStart); + if (!m) return; + var start = m[1].length, end = m[0].length; + if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") + end--; + doc.removeInLine(i, start, end); + }; + var commentWithSpace = lineCommentStart + " "; + var comment = function(line, i) { + if (!ignoreBlankLines || /\S/.test(line)) { + if (shouldInsertSpace(line, minIndent, minIndent)) + doc.insertInLine({row: i, column: minIndent}, commentWithSpace); + else + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + var testRemove = function(line, i) { + return regexpStart.test(line); + }; + + var shouldInsertSpace = function(line, before, after) { + var spaces = 0; + while (before-- && line.charAt(before) == " ") + spaces++; + if (spaces % tabSize != 0) + return false; + var spaces = 0; + while (line.charAt(after++) == " ") + spaces++; + if (tabSize > 2) + return spaces % tabSize != tabSize - 1; + else + return spaces % tabSize == 0; + return true; + }; + } + + function iter(fun) { + for (var i = startRow; i <= endRow; i++) + fun(doc.getLine(i), i); + } + + + var minEmptyLength = Infinity; + iter(function(line, i) { + var indent = line.search(/\S/); + if (indent !== -1) { + if (indent < minIndent) + minIndent = indent; + if (shouldRemove && !testRemove(line, i)) + shouldRemove = false; + } else if (minEmptyLength > line.length) { + minEmptyLength = line.length; + } + }); + + if (minIndent == Infinity) { + minIndent = minEmptyLength; + ignoreBlankLines = false; + shouldRemove = false; + } + + if (insertAtTabStop && minIndent % tabSize != 0) + minIndent = Math.floor(minIndent / tabSize) * tabSize; + + iter(shouldRemove ? uncomment : comment); + }; + + this.toggleBlockComment = function(state, session, range, cursor) { + var comment = this.blockComment; + if (!comment) + return; + if (!comment.start && comment[0]) + comment = comment[0]; + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + var sel = session.selection; + var initialRange = session.selection.toOrientedRange(); + var startRow, colDiff; + + if (token && /comment/.test(token.type)) { + var startRange, endRange; + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.start); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + startRange = new Range(row, column, row, column + comment.start.length); + break; + } + token = iterator.stepBackward(); + } + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.end); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + endRange = new Range(row, column, row, column + comment.end.length); + break; + } + token = iterator.stepForward(); + } + if (endRange) + session.remove(endRange); + if (startRange) { + session.remove(startRange); + startRow = startRange.start.row; + colDiff = -comment.start.length; + } + } else { + colDiff = comment.start.length; + startRow = range.start.row; + session.insert(range.end, comment.end); + session.insert(range.start, comment.start); + } + if (initialRange.start.row == startRow) + initialRange.start.column += colDiff; + if (initialRange.end.row == startRow) + initialRange.end.column += colDiff; + session.selection.fromOrientedRange(initialRange); + }; + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.autoOutdent = function(state, doc, row) { + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + this.createWorker = function(session) { + return null; + }; + + this.createModeDelegates = function (mapping) { + this.$embeds = []; + this.$modes = {}; + for (var i in mapping) { + if (mapping[i]) { + this.$embeds.push(i); + this.$modes[i] = new mapping[i](); + } + } + + var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", + "checkOutdent", "autoOutdent", "transformAction", "getCompletions"]; + + for (var i = 0; i < delegations.length; i++) { + (function(scope) { + var functionName = delegations[i]; + var defaultHandler = scope[functionName]; + scope[delegations[i]] = function() { + return this.$delegator(functionName, arguments, defaultHandler); + }; + }(this)); + } + }; + + this.$delegator = function(method, args, defaultHandler) { + var state = args[0]; + if (typeof state != "string") + state = state[0]; + for (var i = 0; i < this.$embeds.length; i++) { + if (!this.$modes[this.$embeds[i]]) continue; + + var split = state.split(this.$embeds[i]); + if (!split[0] && split[1]) { + args[0] = split[1]; + var mode = this.$modes[this.$embeds[i]]; + return mode[method].apply(mode, args); + } + } + var ret = defaultHandler.apply(this, args); + return defaultHandler ? ret : undefined; + }; + + this.transformAction = function(state, action, editor, session, param) { + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours[key][action]) { + var ret = behaviours[key][action].apply(this, arguments); + if (ret) { + return ret; + } + } + } + } + }; + + this.getKeywords = function(append) { + if (!this.completionKeywords) { + var rules = this.$tokenizer.rules; + var completionKeywords = []; + for (var rule in rules) { + var ruleItr = rules[rule]; + for (var r = 0, l = ruleItr.length; r < l; r++) { + if (typeof ruleItr[r].token === "string") { + if (/keyword|support|storage/.test(ruleItr[r].token)) + completionKeywords.push(ruleItr[r].regex); + } + else if (typeof ruleItr[r].token === "object") { + for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { + if (/keyword|support|storage/.test(ruleItr[r].token[a])) { + var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a]; + completionKeywords.push(rule.substr(1, rule.length - 2)); + } + } + } + } + } + this.completionKeywords = completionKeywords; + } + if (!append) + return this.$keywordList; + return completionKeywords.concat(this.$keywordList || []); + }; + + this.$createKeywordList = function() { + if (!this.$highlightRules) + this.getTokenizer(); + return this.$keywordList = this.$highlightRules.$keywordList || []; + }; + + this.getCompletions = function(state, session, pos, prefix) { + var keywords = this.$keywordList || this.$createKeywordList(); + return keywords.map(function(word) { + return { + name: word, + value: word, + score: 0, + meta: "keyword" + }; + }); + }; + + this.$id = "ace/mode/text"; + }).call(Mode.prototype); + + exports.Mode = Mode; + }); + + ace.define("ace/apply_delta",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + + function throwDeltaError(delta, errorText){ + console.log("Invalid Delta:", delta); + throw "Invalid Delta: " + errorText; + } + + function positionInDocument(docLines, position) { + return position.row >= 0 && position.row < docLines.length && + position.column >= 0 && position.column <= docLines[position.row].length; + } + + function validateDelta(docLines, delta) { + if (delta.action != "insert" && delta.action != "remove") + throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); + if (!(delta.lines instanceof Array)) + throwDeltaError(delta, "delta.lines must be an Array"); + if (!delta.start || !delta.end) + throwDeltaError(delta, "delta.start/end must be an present"); + var start = delta.start; + if (!positionInDocument(docLines, delta.start)) + throwDeltaError(delta, "delta.start must be contained in document"); + var end = delta.end; + if (delta.action == "remove" && !positionInDocument(docLines, end)) + throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); + var numRangeRows = end.row - start.row; + var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); + if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) + throwDeltaError(delta, "delta.range must match delta lines"); + } + + exports.applyDelta = function(docLines, delta, doNotValidate) { + + var row = delta.start.row; + var startColumn = delta.start.column; + var line = docLines[row] || ""; + switch (delta.action) { + case "insert": + var lines = delta.lines; + if (lines.length === 1) { + docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + } else { + var args = [row, 1].concat(delta.lines); + docLines.splice.apply(docLines, args); + docLines[row] = line.substring(0, startColumn) + docLines[row]; + docLines[row + delta.lines.length - 1] += line.substring(startColumn); + } + break; + case "remove": + var endColumn = delta.end.column; + var endRow = delta.end.row; + if (row === endRow) { + docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); + } else { + docLines.splice( + row, endRow - row + 1, + line.substring(0, startColumn) + docLines[endRow].substring(endColumn) + ); + } + break; + } + }; + }); + + ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + + var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(delta) { + if (delta.start.row == delta.end.row && delta.start.row != this.row) + return; + + if (delta.start.row > this.row) + return; + + var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); + this.setPosition(point.row, point.column, true); + }; + + function $pointsInOrder(point1, point2, equalPointsInOrder) { + var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; + return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); + } + + function $getTransformedPoint(delta, point, moveIfEqual) { + var deltaIsInsert = delta.action == "insert"; + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); + var deltaStart = delta.start; + var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. + if ($pointsInOrder(point, deltaStart, moveIfEqual)) { + return { + row: point.row, + column: point.column + }; + } + if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { + return { + row: point.row + deltaRowShift, + column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) + }; + } + + return { + row: deltaStart.row, + column: deltaStart.column + }; + } + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + + }).call(Anchor.prototype); + + }); + + ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var applyDelta = acequire("./apply_delta").applyDelta; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Range = acequire("./range").Range; + var Anchor = acequire("./anchor").Anchor; + + var Document = function(textOrLines) { + this.$lines = [""]; + if (textOrLines.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(textOrLines)) { + this.insertMergedLines({row: 0, column: 0}, textOrLines); + } else { + this.insert({row: 0, column:0}, textOrLines); + } + }; + + (function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength() - 1; + this.remove(new Range(0, 0, len, this.getLine(len).length)); + this.insert({row: 0, column: 0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) { + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + } else { + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + } + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + return this.getLinesForRange(range).join(this.getNewLineCharacter()); + }; + this.getLinesForRange = function(range) { + var lines; + if (range.start.row === range.end.row) { + lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; + } else { + lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + } + return lines; + }; + this.insertLines = function(row, lines) { + console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); + return this.insertFullLines(row, lines); + }; + this.removeLines = function(firstRow, lastRow) { + console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); + return this.removeFullLines(firstRow, lastRow); + }; + this.insertNewLine = function(position) { + console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."); + return this.insertMergedLines(position, ["", ""]); + }; + this.insert = function(position, text) { + if (this.getLength() <= 1) + this.$detectNewLine(text); + + return this.insertMergedLines(position, this.$split(text)); + }; + this.insertInLine = function(position, text) { + var start = this.clippedPos(position.row, position.column); + var end = this.pos(position.row, position.column + text.length); + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: [text] + }, true); + + return this.clonePos(end); + }; + + this.clippedPos = function(row, column) { + var length = this.getLength(); + if (row === undefined) { + row = length; + } else if (row < 0) { + row = 0; + } else if (row >= length) { + row = length - 1; + column = undefined; + } + var line = this.getLine(row); + if (column == undefined) + column = line.length; + column = Math.min(Math.max(column, 0), line.length); + return {row: row, column: column}; + }; + + this.clonePos = function(pos) { + return {row: pos.row, column: pos.column}; + }; + + this.pos = function(row, column) { + return {row: row, column: column}; + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length - 1).length; + } else { + position.row = Math.max(0, position.row); + position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); + } + return position; + }; + this.insertFullLines = function(row, lines) { + row = Math.min(Math.max(row, 0), this.getLength()); + var column = 0; + if (row < this.getLength()) { + lines = lines.concat([""]); + column = 0; + } else { + lines = [""].concat(lines); + row--; + column = this.$lines[row].length; + } + this.insertMergedLines({row: row, column: column}, lines); + }; + this.insertMergedLines = function(position, lines) { + var start = this.clippedPos(position.row, position.column); + var end = { + row: start.row + lines.length - 1, + column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length + }; + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: lines + }); + + return this.clonePos(end); + }; + this.remove = function(range) { + var start = this.clippedPos(range.start.row, range.start.column); + var end = this.clippedPos(range.end.row, range.end.column); + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }); + return this.clonePos(start); + }; + this.removeInLine = function(row, startColumn, endColumn) { + var start = this.clippedPos(row, startColumn); + var end = this.clippedPos(row, endColumn); + + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }, true); + + return this.clonePos(start); + }; + this.removeFullLines = function(firstRow, lastRow) { + firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); + lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); + var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; + var deleteLastNewLine = lastRow < this.getLength() - 1; + var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); + var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); + var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); + var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); + var range = new Range(startRow, startCol, endRow, endCol); + var deletedLines = this.$lines.slice(firstRow, lastRow + 1); + + this.applyDelta({ + start: range.start, + end: range.end, + action: "remove", + lines: this.getLinesForRange(range) + }); + return deletedLines; + }; + this.removeNewLine = function(row) { + if (row < this.getLength() - 1 && row >= 0) { + this.applyDelta({ + start: this.pos(row, this.getLine(row).length), + end: this.pos(row + 1, 0), + action: "remove", + lines: ["", ""] + }); + } + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length === 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + var end; + if (text) { + end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + this.revertDelta(deltas[i]); + } + }; + this.applyDelta = function(delta, doNotValidate) { + var isInsert = delta.action == "insert"; + if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] + : !Range.comparePoints(delta.start, delta.end)) { + return; + } + + if (isInsert && delta.lines.length > 20000) + this.$splitAndapplyLargeDelta(delta, 20000); + applyDelta(this.$lines, delta, doNotValidate); + this._signal("change", delta); + }; + + this.$splitAndapplyLargeDelta = function(delta, MAX) { + var lines = delta.lines; + var l = lines.length; + var row = delta.start.row; + var column = delta.start.column; + var from = 0, to = 0; + do { + from = to; + to += MAX - 1; + var chunk = lines.slice(from, to); + if (to > l) { + delta.lines = chunk; + delta.start.row = row + from; + delta.start.column = column; + break; + } + chunk.push(""); + this.applyDelta({ + start: this.pos(row + from, column), + end: this.pos(row + to, column = 0), + action: delta.action, + lines: chunk + }, true); + } while(true); + }; + this.revertDelta = function(delta) { + this.applyDelta({ + start: this.clonePos(delta.start), + end: this.clonePos(delta.end), + action: (delta.action == "insert" ? "remove" : "insert"), + lines: delta.lines.slice() + }); + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + + }).call(Document.prototype); + + exports.Document = Document; + }); + + ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + + var BackgroundTokenizer = function(tokenizer, editor) { + this.running = false; + this.lines = []; + this.states = []; + this.currentLine = 0; + this.tokenizer = tokenizer; + + var self = this; + + this.$worker = function() { + if (!self.running) { return; } + + var workerStart = new Date(); + var currentLine = self.currentLine; + var endLine = -1; + var doc = self.doc; + + var startLine = currentLine; + while (self.lines[currentLine]) + currentLine++; + + var len = doc.getLength(); + var processedLines = 0; + self.running = false; + while (currentLine < len) { + self.$tokenizeRow(currentLine); + endLine = currentLine; + do { + currentLine++; + } while (self.lines[currentLine]); + processedLines ++; + if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { + self.running = setTimeout(self.$worker, 20); + break; + } + } + self.currentLine = currentLine; + + if (endLine == -1) + endLine = currentLine; + + if (startLine <= endLine) + self.fireUpdateEvent(startLine, endLine); + }; + }; + + (function(){ + + oop.implement(this, EventEmitter); + this.setTokenizer = function(tokenizer) { + this.tokenizer = tokenizer; + this.lines = []; + this.states = []; + + this.start(0); + }; + this.setDocument = function(doc) { + this.doc = doc; + this.lines = []; + this.states = []; + + this.stop(); + }; + this.fireUpdateEvent = function(firstRow, lastRow) { + var data = { + first: firstRow, + last: lastRow + }; + this._signal("update", {data: data}); + }; + this.start = function(startRow) { + this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength()); + this.lines.splice(this.currentLine, this.lines.length); + this.states.splice(this.currentLine, this.states.length); + + this.stop(); + this.running = setTimeout(this.$worker, 700); + }; + + this.scheduleStart = function() { + if (!this.running) + this.running = setTimeout(this.$worker, 700); + }; + + this.$updateOnChange = function(delta) { + var startRow = delta.start.row; + var len = delta.end.row - startRow; + + if (len === 0) { + this.lines[startRow] = null; + } else if (delta.action == "remove") { + this.lines.splice(startRow, len + 1, null); + this.states.splice(startRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(startRow, 1); + this.lines.splice.apply(this.lines, args); + this.states.splice.apply(this.states, args); + } + + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); + + this.stop(); + }; + this.stop = function() { + if (this.running) + clearTimeout(this.running); + this.running = false; + }; + this.getTokens = function(row) { + return this.lines[row] || this.$tokenizeRow(row); + }; + this.getState = function(row) { + if (this.currentLine == row) + this.$tokenizeRow(row); + return this.states[row] || "start"; + }; + + this.$tokenizeRow = function(row) { + var line = this.doc.getLine(row); + var state = this.states[row - 1]; + + var data = this.tokenizer.getLineTokens(line, state, row); + + if (this.states[row] + "" !== data.state + "") { + this.states[row] = data.state; + this.lines[row + 1] = null; + if (this.currentLine > row + 1) + this.currentLine = row + 1; + } else if (this.currentLine == row) { + this.currentLine = row + 1; + } + + return this.lines[row] = data.tokens; + }; + + }).call(BackgroundTokenizer.prototype); + + exports.BackgroundTokenizer = BackgroundTokenizer; + }); + + ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("./lib/lang"); + var oop = acequire("./lib/oop"); + var Range = acequire("./range").Range; + + var SearchHighlight = function(regExp, clazz, type) { + this.setRegexp(regExp); + this.clazz = clazz; + this.type = type || "text"; + }; + + (function() { + this.MAX_RANGES = 500; + + this.setRegexp = function(regExp) { + if (this.regExp+"" == regExp+"") + return; + this.regExp = regExp; + this.cache = []; + }; + + this.update = function(html, markerLayer, session, config) { + if (!this.regExp) + return; + var start = config.firstRow, end = config.lastRow; + + for (var i = start; i <= end; i++) { + var ranges = this.cache[i]; + if (ranges == null) { + ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); + if (ranges.length > this.MAX_RANGES) + ranges = ranges.slice(0, this.MAX_RANGES); + ranges = ranges.map(function(match) { + return new Range(i, match.offset, i, match.offset + match.length); + }); + this.cache[i] = ranges.length ? ranges : ""; + } + + for (var j = ranges.length; j --; ) { + markerLayer.drawSingleLineMarker( + html, ranges[j].toScreenRange(session), this.clazz, config); + } + } + }; + + }).call(SearchHighlight.prototype); + + exports.SearchHighlight = SearchHighlight; + }); + + ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + function FoldLine(foldData, folds) { + this.foldData = foldData; + if (Array.isArray(folds)) { + this.folds = folds; + } else { + folds = this.folds = [ folds ]; + } + + var last = folds[folds.length - 1]; + this.range = new Range(folds[0].start.row, folds[0].start.column, + last.end.row, last.end.column); + this.start = this.range.start; + this.end = this.range.end; + + this.folds.forEach(function(fold) { + fold.setFoldLine(this); + }, this); + } + + (function() { + this.shiftRow = function(shift) { + this.start.row += shift; + this.end.row += shift; + this.folds.forEach(function(fold) { + fold.start.row += shift; + fold.end.row += shift; + }); + }; + + this.addFold = function(fold) { + if (fold.sameRow) { + if (fold.start.row < this.startRow || fold.endRow > this.endRow) { + throw new Error("Can't add a fold to this FoldLine as it has no connection"); + } + this.folds.push(fold); + this.folds.sort(function(a, b) { + return -a.range.compareEnd(b.start.row, b.start.column); + }); + if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) { + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) { + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } + } else if (fold.start.row == this.end.row) { + this.folds.push(fold); + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (fold.end.row == this.start.row) { + this.folds.unshift(fold); + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } else { + throw new Error("Trying to add fold to FoldRow that doesn't have a matching row"); + } + fold.foldLine = this; + }; + + this.containsRow = function(row) { + return row >= this.start.row && row <= this.end.row; + }; + + this.walk = function(callback, endRow, endColumn) { + var lastEnd = 0, + folds = this.folds, + fold, + cmp, stop, isNewRow = true; + + if (endRow == null) { + endRow = this.end.row; + endColumn = this.end.column; + } + + for (var i = 0; i < folds.length; i++) { + fold = folds[i]; + + cmp = fold.range.compareStart(endRow, endColumn); + if (cmp == -1) { + callback(null, endRow, endColumn, lastEnd, isNewRow); + return; + } + + stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); + stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); + if (stop || cmp === 0) { + return; + } + isNewRow = !fold.sameRow; + lastEnd = fold.end.column; + } + callback(null, endRow, endColumn, lastEnd, isNewRow); + }; + + this.getNextFoldTo = function(row, column) { + var fold, cmp; + for (var i = 0; i < this.folds.length; i++) { + fold = this.folds[i]; + cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + return { + fold: fold, + kind: "after" + }; + } else if (cmp === 0) { + return { + fold: fold, + kind: "inside" + }; + } + } + return null; + }; + + this.addRemoveChars = function(row, column, len) { + var ret = this.getNextFoldTo(row, column), + fold, folds; + if (ret) { + fold = ret.fold; + if (ret.kind == "inside" + && fold.start.column != column + && fold.start.row != row) + { + window.console && window.console.log(row, column, fold); + } else if (fold.start.row == row) { + folds = this.folds; + var i = folds.indexOf(fold); + if (i === 0) { + this.start.column += len; + } + for (i; i < folds.length; i++) { + fold = folds[i]; + fold.start.column += len; + if (!fold.sameRow) { + return; + } + fold.end.column += len; + } + this.end.column += len; + } + } + }; + + this.split = function(row, column) { + var pos = this.getNextFoldTo(row, column); + + if (!pos || pos.kind == "inside") + return null; + + var fold = pos.fold; + var folds = this.folds; + var foldData = this.foldData; + + var i = folds.indexOf(fold); + var foldBefore = folds[i - 1]; + this.end.row = foldBefore.end.row; + this.end.column = foldBefore.end.column; + folds = folds.splice(i, folds.length - i); + + var newFoldLine = new FoldLine(foldData, folds); + foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); + return newFoldLine; + }; + + this.merge = function(foldLineNext) { + var folds = foldLineNext.folds; + for (var i = 0; i < folds.length; i++) { + this.addFold(folds[i]); + } + var foldData = this.foldData; + foldData.splice(foldData.indexOf(foldLineNext), 1); + }; + + this.toString = function() { + var ret = [this.range.toString() + ": [" ]; + + this.folds.forEach(function(fold) { + ret.push(" " + fold.toString()); + }); + ret.push("]"); + return ret.join("\n"); + }; + + this.idxToPosition = function(idx) { + var lastFoldEndColumn = 0; + + for (var i = 0; i < this.folds.length; i++) { + var fold = this.folds[i]; + + idx -= fold.start.column - lastFoldEndColumn; + if (idx < 0) { + return { + row: fold.start.row, + column: fold.start.column + idx + }; + } + + idx -= fold.placeholder.length; + if (idx < 0) { + return fold.start; + } + + lastFoldEndColumn = fold.end.column; + } + + return { + row: this.end.row, + column: this.end.column + idx + }; + }; + }).call(FoldLine.prototype); + + exports.FoldLine = FoldLine; + }); + + ace.define("ace/range_list",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + var Range = acequire("./range").Range; + var comparePoints = Range.comparePoints; + + var RangeList = function() { + this.ranges = []; + }; + + (function() { + this.comparePoints = comparePoints; + + this.pointIndex = function(pos, excludeEdges, startIndex) { + var list = this.ranges; + + for (var i = startIndex || 0; i < list.length; i++) { + var range = list[i]; + var cmpEnd = comparePoints(pos, range.end); + if (cmpEnd > 0) + continue; + var cmpStart = comparePoints(pos, range.start); + if (cmpEnd === 0) + return excludeEdges && cmpStart !== 0 ? -i-2 : i; + if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) + return i; + + return -i-1; + } + return -i - 1; + }; + + this.add = function(range) { + var excludeEdges = !range.isEmpty(); + var startIndex = this.pointIndex(range.start, excludeEdges); + if (startIndex < 0) + startIndex = -startIndex - 1; + + var endIndex = this.pointIndex(range.end, excludeEdges, startIndex); + + if (endIndex < 0) + endIndex = -endIndex - 1; + else + endIndex++; + return this.ranges.splice(startIndex, endIndex - startIndex, range); + }; + + this.addList = function(list) { + var removed = []; + for (var i = list.length; i--; ) { + removed.push.apply(removed, this.add(list[i])); + } + return removed; + }; + + this.substractPoint = function(pos) { + var i = this.pointIndex(pos); + + if (i >= 0) + return this.ranges.splice(i, 1); + }; + this.merge = function() { + var removed = []; + var list = this.ranges; + + list = list.sort(function(a, b) { + return comparePoints(a.start, b.start); + }); + + var next = list[0], range; + for (var i = 1; i < list.length; i++) { + range = next; + next = list[i]; + var cmp = comparePoints(range.end, next.start); + if (cmp < 0) + continue; + + if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) + continue; + + if (comparePoints(range.end, next.end) < 0) { + range.end.row = next.end.row; + range.end.column = next.end.column; + } + + list.splice(i, 1); + removed.push(next); + next = range; + i--; + } + + this.ranges = list; + + return removed; + }; + + this.contains = function(row, column) { + return this.pointIndex({row: row, column: column}) >= 0; + }; + + this.containsPoint = function(pos) { + return this.pointIndex(pos) >= 0; + }; + + this.rangeAtPoint = function(pos) { + var i = this.pointIndex(pos); + if (i >= 0) + return this.ranges[i]; + }; + + + this.clipRows = function(startRow, endRow) { + var list = this.ranges; + if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow) + return []; + + var startIndex = this.pointIndex({row: startRow, column: 0}); + if (startIndex < 0) + startIndex = -startIndex - 1; + var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex); + if (endIndex < 0) + endIndex = -endIndex - 1; + + var clipped = []; + for (var i = startIndex; i < endIndex; i++) { + clipped.push(list[i]); + } + return clipped; + }; + + this.removeAll = function() { + return this.ranges.splice(0, this.ranges.length); + }; + + this.attach = function(session) { + if (this.session) + this.detach(); + + this.session = session; + this.onChange = this.$onChange.bind(this); + + this.session.on('change', this.onChange); + }; + + this.detach = function() { + if (!this.session) + return; + this.session.removeListener('change', this.onChange); + this.session = null; + }; + + this.$onChange = function(delta) { + if (delta.action == "insert"){ + var start = delta.start; + var end = delta.end; + } else { + var end = delta.start; + var start = delta.end; + } + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + + var colDiff = -start.column + end.column; + var ranges = this.ranges; + + for (var i = 0, n = ranges.length; i < n; i++) { + var r = ranges[i]; + if (r.end.row < startRow) + continue; + if (r.start.row > startRow) + break; + + if (r.start.row == startRow && r.start.column >= start.column ) { + if (r.start.column == start.column && this.$insertRight) { + } else { + r.start.column += colDiff; + r.start.row += lineDif; + } + } + if (r.end.row == startRow && r.end.column >= start.column) { + if (r.end.column == start.column && this.$insertRight) { + continue; + } + if (r.end.column == start.column && colDiff > 0 && i < n - 1) { + if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) + r.end.column -= colDiff; + } + r.end.column += colDiff; + r.end.row += lineDif; + } + } + + if (lineDif != 0 && i < n) { + for (; i < n; i++) { + var r = ranges[i]; + r.start.row += lineDif; + r.end.row += lineDif; + } + } + }; + + }).call(RangeList.prototype); + + exports.RangeList = RangeList; + }); + + ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var RangeList = acequire("../range_list").RangeList; + var oop = acequire("../lib/oop"); + var Fold = exports.Fold = function(range, placeholder) { + this.foldLine = null; + this.placeholder = placeholder; + this.range = range; + this.start = range.start; + this.end = range.end; + + this.sameRow = range.start.row == range.end.row; + this.subFolds = this.ranges = []; + }; + + oop.inherits(Fold, RangeList); + + (function() { + + this.toString = function() { + return '"' + this.placeholder + '" ' + this.range.toString(); + }; + + this.setFoldLine = function(foldLine) { + this.foldLine = foldLine; + this.subFolds.forEach(function(fold) { + fold.setFoldLine(foldLine); + }); + }; + + this.clone = function() { + var range = this.range.clone(); + var fold = new Fold(range, this.placeholder); + this.subFolds.forEach(function(subFold) { + fold.subFolds.push(subFold.clone()); + }); + fold.collapseChildren = this.collapseChildren; + return fold; + }; + + this.addSubFold = function(fold) { + if (this.range.isEqual(fold)) + return; + + if (!this.range.containsRange(fold)) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + consumeRange(fold, this.start); + + var row = fold.start.row, column = fold.start.column; + for (var i = 0, cmp = -1; i < this.subFolds.length; i++) { + cmp = this.subFolds[i].range.compare(row, column); + if (cmp != 1) + break; + } + var afterStart = this.subFolds[i]; + + if (cmp == 0) + return afterStart.addSubFold(fold); + var row = fold.range.end.row, column = fold.range.end.column; + for (var j = i, cmp = -1; j < this.subFolds.length; j++) { + cmp = this.subFolds[j].range.compare(row, column); + if (cmp != 1) + break; + } + var afterEnd = this.subFolds[j]; + + if (cmp == 0) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + + var consumedFolds = this.subFolds.splice(i, j - i, fold); + fold.setFoldLine(this.foldLine); + + return fold; + }; + + this.restoreRange = function(range) { + return restoreRange(range, this.start); + }; + + }).call(Fold.prototype); + + function consumePoint(point, anchor) { + point.row -= anchor.row; + if (point.row == 0) + point.column -= anchor.column; + } + function consumeRange(range, anchor) { + consumePoint(range.start, anchor); + consumePoint(range.end, anchor); + } + function restorePoint(point, anchor) { + if (point.row == 0) + point.column += anchor.column; + point.row += anchor.row; + } + function restoreRange(range, anchor) { + restorePoint(range.start, anchor); + restorePoint(range.end, anchor); + } + + }); + + ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var FoldLine = acequire("./fold_line").FoldLine; + var Fold = acequire("./fold").Fold; + var TokenIterator = acequire("../token_iterator").TokenIterator; + + function Folding() { + this.getFoldAt = function(row, column, side) { + var foldLine = this.getFoldLine(row); + if (!foldLine) + return null; + + var folds = foldLine.folds; + for (var i = 0; i < folds.length; i++) { + var fold = folds[i]; + if (fold.range.contains(row, column)) { + if (side == 1 && fold.range.isEnd(row, column)) { + continue; + } else if (side == -1 && fold.range.isStart(row, column)) { + continue; + } + return fold; + } + } + }; + this.getFoldsInRange = function(range) { + var start = range.start; + var end = range.end; + var foldLines = this.$foldData; + var foundFolds = []; + + start.column += 1; + end.column -= 1; + + for (var i = 0; i < foldLines.length; i++) { + var cmp = foldLines[i].range.compareRange(range); + if (cmp == 2) { + continue; + } + else if (cmp == -2) { + break; + } + + var folds = foldLines[i].folds; + for (var j = 0; j < folds.length; j++) { + var fold = folds[j]; + cmp = fold.range.compareRange(range); + if (cmp == -2) { + break; + } else if (cmp == 2) { + continue; + } else + if (cmp == 42) { + break; + } + foundFolds.push(fold); + } + } + start.column -= 1; + end.column += 1; + + return foundFolds; + }; + + this.getFoldsInRangeList = function(ranges) { + if (Array.isArray(ranges)) { + var folds = []; + ranges.forEach(function(range) { + folds = folds.concat(this.getFoldsInRange(range)); + }, this); + } else { + var folds = this.getFoldsInRange(ranges); + } + return folds; + }; + this.getAllFolds = function() { + var folds = []; + var foldLines = this.$foldData; + + for (var i = 0; i < foldLines.length; i++) + for (var j = 0; j < foldLines[i].folds.length; j++) + folds.push(foldLines[i].folds[j]); + + return folds; + }; + this.getFoldStringAt = function(row, column, trim, foldLine) { + foldLine = foldLine || this.getFoldLine(row); + if (!foldLine) + return null; + + var lastFold = { + end: { column: 0 } + }; + var str, fold; + for (var i = 0; i < foldLine.folds.length; i++) { + fold = foldLine.folds[i]; + var cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + str = this + .getLine(fold.start.row) + .substring(lastFold.end.column, fold.start.column); + break; + } + else if (cmp === 0) { + return null; + } + lastFold = fold; + } + if (!str) + str = this.getLine(fold.start.row).substring(lastFold.end.column); + + if (trim == -1) + return str.substring(0, column - lastFold.end.column); + else if (trim == 1) + return str.substring(column - lastFold.end.column); + else + return str; + }; + + this.getFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { + return foldLine; + } else if (foldLine.end.row > docRow) { + return null; + } + } + return null; + }; + this.getNextFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.end.row >= docRow) { + return foldLine; + } + } + return null; + }; + + this.getFoldedRowCount = function(first, last) { + var foldData = this.$foldData, rowCount = last-first+1; + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i], + end = foldLine.end.row, + start = foldLine.start.row; + if (end >= last) { + if (start < last) { + if (start >= first) + rowCount -= last-start; + else + rowCount = 0; // in one fold + } + break; + } else if (end >= first){ + if (start >= first) // fold inside range + rowCount -= end-start; + else + rowCount -= end-first+1; + } + } + return rowCount; + }; + + this.$addFoldLine = function(foldLine) { + this.$foldData.push(foldLine); + this.$foldData.sort(function(a, b) { + return a.start.row - b.start.row; + }); + return foldLine; + }; + this.addFold = function(placeholder, range) { + var foldData = this.$foldData; + var added = false; + var fold; + + if (placeholder instanceof Fold) + fold = placeholder; + else { + fold = new Fold(range, placeholder); + fold.collapseChildren = range.collapseChildren; + } + this.$clipRangeToDocument(fold.range); + + var startRow = fold.start.row; + var startColumn = fold.start.column; + var endRow = fold.end.row; + var endColumn = fold.end.column; + if (!(startRow < endRow || + startRow == endRow && startColumn <= endColumn - 2)) + throw new Error("The range has to be at least 2 characters width"); + + var startFold = this.getFoldAt(startRow, startColumn, 1); + var endFold = this.getFoldAt(endRow, endColumn, -1); + if (startFold && endFold == startFold) + return startFold.addSubFold(fold); + + if (startFold && !startFold.range.isStart(startRow, startColumn)) + this.removeFold(startFold); + + if (endFold && !endFold.range.isEnd(endRow, endColumn)) + this.removeFold(endFold); + var folds = this.getFoldsInRange(fold.range); + if (folds.length > 0) { + this.removeFolds(folds); + folds.forEach(function(subFold) { + fold.addSubFold(subFold); + }); + } + + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (endRow == foldLine.start.row) { + foldLine.addFold(fold); + added = true; + break; + } else if (startRow == foldLine.end.row) { + foldLine.addFold(fold); + added = true; + if (!fold.sameRow) { + var foldLineNext = foldData[i + 1]; + if (foldLineNext && foldLineNext.start.row == endRow) { + foldLine.merge(foldLineNext); + break; + } + } + break; + } else if (endRow <= foldLine.start.row) { + break; + } + } + + if (!added) + foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); + + if (this.$useWrapMode) + this.$updateWrapData(foldLine.start.row, foldLine.start.row); + else + this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row); + this.$modified = true; + this._signal("changeFold", { data: fold, action: "add" }); + + return fold; + }; + + this.addFolds = function(folds) { + folds.forEach(function(fold) { + this.addFold(fold); + }, this); + }; + + this.removeFold = function(fold) { + var foldLine = fold.foldLine; + var startRow = foldLine.start.row; + var endRow = foldLine.end.row; + + var foldLines = this.$foldData; + var folds = foldLine.folds; + if (folds.length == 1) { + foldLines.splice(foldLines.indexOf(foldLine), 1); + } else + if (foldLine.range.isEnd(fold.end.row, fold.end.column)) { + folds.pop(); + foldLine.end.row = folds[folds.length - 1].end.row; + foldLine.end.column = folds[folds.length - 1].end.column; + } else + if (foldLine.range.isStart(fold.start.row, fold.start.column)) { + folds.shift(); + foldLine.start.row = folds[0].start.row; + foldLine.start.column = folds[0].start.column; + } else + if (fold.sameRow) { + folds.splice(folds.indexOf(fold), 1); + } else + { + var newFoldLine = foldLine.split(fold.start.row, fold.start.column); + folds = newFoldLine.folds; + folds.shift(); + newFoldLine.start.row = folds[0].start.row; + newFoldLine.start.column = folds[0].start.column; + } + + if (!this.$updating) { + if (this.$useWrapMode) + this.$updateWrapData(startRow, endRow); + else + this.$updateRowLengthCache(startRow, endRow); + } + this.$modified = true; + this._signal("changeFold", { data: fold, action: "remove" }); + }; + + this.removeFolds = function(folds) { + var cloneFolds = []; + for (var i = 0; i < folds.length; i++) { + cloneFolds.push(folds[i]); + } + + cloneFolds.forEach(function(fold) { + this.removeFold(fold); + }, this); + this.$modified = true; + }; + + this.expandFold = function(fold) { + this.removeFold(fold); + fold.subFolds.forEach(function(subFold) { + fold.restoreRange(subFold); + this.addFold(subFold); + }, this); + if (fold.collapseChildren > 0) { + this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1); + } + fold.subFolds = []; + }; + + this.expandFolds = function(folds) { + folds.forEach(function(fold) { + this.expandFold(fold); + }, this); + }; + + this.unfold = function(location, expandInner) { + var range, folds; + if (location == null) { + range = new Range(0, 0, this.getLength(), 0); + expandInner = true; + } else if (typeof location == "number") + range = new Range(location, 0, location, this.getLine(location).length); + else if ("row" in location) + range = Range.fromPoints(location, location); + else + range = location; + + folds = this.getFoldsInRangeList(range); + if (expandInner) { + this.removeFolds(folds); + } else { + var subFolds = folds; + while (subFolds.length) { + this.expandFolds(subFolds); + subFolds = this.getFoldsInRangeList(range); + } + } + if (folds.length) + return folds; + }; + this.isRowFolded = function(docRow, startFoldRow) { + return !!this.getFoldLine(docRow, startFoldRow); + }; + + this.getRowFoldEnd = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.end.row : docRow; + }; + + this.getRowFoldStart = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.start.row : docRow; + }; + + this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { + if (startRow == null) + startRow = foldLine.start.row; + if (startColumn == null) + startColumn = 0; + if (endRow == null) + endRow = foldLine.end.row; + if (endColumn == null) + endColumn = this.getLine(endRow).length; + var doc = this.doc; + var textLine = ""; + + foldLine.walk(function(placeholder, row, column, lastColumn) { + if (row < startRow) + return; + if (row == startRow) { + if (column < startColumn) + return; + lastColumn = Math.max(startColumn, lastColumn); + } + + if (placeholder != null) { + textLine += placeholder; + } else { + textLine += doc.getLine(row).substring(lastColumn, column); + } + }, endRow, endColumn); + return textLine; + }; + + this.getDisplayLine = function(row, endColumn, startRow, startColumn) { + var foldLine = this.getFoldLine(row); + + if (!foldLine) { + var line; + line = this.doc.getLine(row); + return line.substring(startColumn || 0, endColumn || line.length); + } else { + return this.getFoldDisplayLine( + foldLine, row, endColumn, startRow, startColumn); + } + }; + + this.$cloneFoldData = function() { + var fd = []; + fd = this.$foldData.map(function(foldLine) { + var folds = foldLine.folds.map(function(fold) { + return fold.clone(); + }); + return new FoldLine(fd, folds); + }); + + return fd; + }; + + this.toggleFold = function(tryToUnfold) { + var selection = this.selection; + var range = selection.getRange(); + var fold; + var bracketPos; + + if (range.isEmpty()) { + var cursor = range.start; + fold = this.getFoldAt(cursor.row, cursor.column); + + if (fold) { + this.expandFold(fold); + return; + } else if (bracketPos = this.findMatchingBracket(cursor)) { + if (range.comparePoint(bracketPos) == 1) { + range.end = bracketPos; + } else { + range.start = bracketPos; + range.start.column++; + range.end.column--; + } + } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) { + if (range.comparePoint(bracketPos) == 1) + range.end = bracketPos; + else + range.start = bracketPos; + + range.start.column++; + } else { + range = this.getCommentFoldRange(cursor.row, cursor.column) || range; + } + } else { + var folds = this.getFoldsInRange(range); + if (tryToUnfold && folds.length) { + this.expandFolds(folds); + return; + } else if (folds.length == 1 ) { + fold = folds[0]; + } + } + + if (!fold) + fold = this.getFoldAt(range.start.row, range.start.column); + + if (fold && fold.range.toString() == range.toString()) { + this.expandFold(fold); + return; + } + + var placeholder = "..."; + if (!range.isMultiLine()) { + placeholder = this.getTextRange(range); + if (placeholder.length < 4) + return; + placeholder = placeholder.trim().substring(0, 2) + ".."; + } + + this.addFold(placeholder, range); + }; + + this.getCommentFoldRange = function(row, column, dir) { + var iterator = new TokenIterator(this, row, column); + var token = iterator.getCurrentToken(); + var type = token.type; + if (token && /^comment|string/.test(type)) { + type = type.match(/comment|string/)[0]; + if (type == "comment") + type += "|doc-start"; + var re = new RegExp(type); + var range = new Range(); + if (dir != 1) { + do { + token = iterator.stepBackward(); + } while (token && re.test(token.type)); + iterator.stepForward(); + } + + range.start.row = iterator.getCurrentTokenRow(); + range.start.column = iterator.getCurrentTokenColumn() + 2; + + iterator = new TokenIterator(this, row, column); + + if (dir != -1) { + var lastRow = -1; + do { + token = iterator.stepForward(); + if (lastRow == -1) { + var state = this.getState(iterator.$row); + if (!re.test(state)) + lastRow = iterator.$row; + } else if (iterator.$row > lastRow) { + break; + } + } while (token && re.test(token.type)); + token = iterator.stepBackward(); + } else + token = iterator.getCurrentToken(); + + range.end.row = iterator.getCurrentTokenRow(); + range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2; + return range; + } + }; + + this.foldAll = function(startRow, endRow, depth) { + if (depth == undefined) + depth = 100000; // JSON.stringify doesn't hanle Infinity + var foldWidgets = this.foldWidgets; + if (!foldWidgets) + return; // mode doesn't support folding + endRow = endRow || this.getLength(); + startRow = startRow || 0; + for (var row = startRow; row < endRow; row++) { + if (foldWidgets[row] == null) + foldWidgets[row] = this.getFoldWidget(row); + if (foldWidgets[row] != "start") + continue; + + var range = this.getFoldWidgetRange(row); + if (range && range.isMultiLine() + && range.end.row <= endRow + && range.start.row >= startRow + ) { + row = range.end.row; + try { + var fold = this.addFold("...", range); + if (fold) + fold.collapseChildren = depth; + } catch(e) {} + } + } + }; + this.$foldStyles = { + "manual": 1, + "markbegin": 1, + "markbeginend": 1 + }; + this.$foldStyle = "markbegin"; + this.setFoldStyle = function(style) { + if (!this.$foldStyles[style]) + throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]"); + + if (this.$foldStyle == style) + return; + + this.$foldStyle = style; + + if (style == "manual") + this.unfold(); + var mode = this.$foldMode; + this.$setFolding(null); + this.$setFolding(mode); + }; + + this.$setFolding = function(foldMode) { + if (this.$foldMode == foldMode) + return; + + this.$foldMode = foldMode; + + this.off('change', this.$updateFoldWidgets); + this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + this._signal("changeAnnotation"); + + if (!foldMode || this.$foldStyle == "manual") { + this.foldWidgets = null; + return; + } + + this.foldWidgets = []; + this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle); + this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); + + this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); + this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this); + this.on('change', this.$updateFoldWidgets); + this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + }; + + this.getParentFoldRangeData = function (row, ignoreCurrent) { + var fw = this.foldWidgets; + if (!fw || (ignoreCurrent && fw[row])) + return {}; + + var i = row - 1, firstRange; + while (i >= 0) { + var c = fw[i]; + if (c == null) + c = fw[i] = this.getFoldWidget(i); + + if (c == "start") { + var range = this.getFoldWidgetRange(i); + if (!firstRange) + firstRange = range; + if (range && range.end.row >= row) + break; + } + i--; + } + + return { + range: i !== -1 && range, + firstRange: firstRange + }; + }; + + this.onFoldWidgetClick = function(row, e) { + e = e.domEvent; + var options = { + children: e.shiftKey, + all: e.ctrlKey || e.metaKey, + siblings: e.altKey + }; + + var range = this.$toggleFoldWidget(row, options); + if (!range) { + var el = (e.target || e.srcElement); + if (el && /ace_fold-widget/.test(el.className)) + el.className += " ace_invalid"; + } + }; + + this.$toggleFoldWidget = function(row, options) { + if (!this.getFoldWidget) + return; + var type = this.getFoldWidget(row); + var line = this.getLine(row); + + var dir = type === "end" ? -1 : 1; + var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir); + + if (fold) { + if (options.children || options.all) + this.removeFold(fold); + else + this.expandFold(fold); + return fold; + } + + var range = this.getFoldWidgetRange(row, true); + if (range && !range.isMultiLine()) { + fold = this.getFoldAt(range.start.row, range.start.column, 1); + if (fold && range.isEqual(fold.range)) { + this.removeFold(fold); + return fold; + } + } + + if (options.siblings) { + var data = this.getParentFoldRangeData(row); + if (data.range) { + var startRow = data.range.start.row + 1; + var endRow = data.range.end.row; + } + this.foldAll(startRow, endRow, options.all ? 10000 : 0); + } else if (options.children) { + endRow = range ? range.end.row : this.getLength(); + this.foldAll(row + 1, endRow, options.all ? 10000 : 0); + } else if (range) { + if (options.all) + range.collapseChildren = 10000; + this.addFold("...", range); + } + + return range; + }; + + + + this.toggleFoldWidget = function(toggleParent) { + var row = this.selection.getCursor().row; + row = this.getRowFoldStart(row); + var range = this.$toggleFoldWidget(row, {}); + + if (range) + return; + var data = this.getParentFoldRangeData(row, true); + range = data.range || data.firstRange; + + if (range) { + row = range.start.row; + var fold = this.getFoldAt(row, this.getLine(row).length, 1); + + if (fold) { + this.removeFold(fold); + } else { + this.addFold("...", range); + } + } + }; + + this.updateFoldWidgets = function(delta) { + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; + + if (len === 0) { + this.foldWidgets[firstRow] = null; + } else if (delta.action == 'remove') { + this.foldWidgets.splice(firstRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(firstRow, 1); + this.foldWidgets.splice.apply(this.foldWidgets, args); + } + }; + this.tokenizerUpdateFoldWidgets = function(e) { + var rows = e.data; + if (rows.first != rows.last) { + if (this.foldWidgets.length > rows.first) + this.foldWidgets.splice(rows.first, this.foldWidgets.length); + } + }; + } + + exports.Folding = Folding; + + }); + + ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(acequire, exports, module) { + "use strict"; + + var TokenIterator = acequire("../token_iterator").TokenIterator; + var Range = acequire("../range").Range; + + + function BracketMatch() { + + this.findMatchingBracket = function(position, chr) { + if (position.column == 0) return null; + + var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1); + if (charBeforeCursor == "") return null; + + var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); + if (!match) + return null; + + if (match[1]) + return this.$findClosingBracket(match[1], position); + else + return this.$findOpeningBracket(match[2], position); + }; + + this.getBracketRange = function(pos) { + var line = this.getLine(pos.row); + var before = true, range; + + var chr = line.charAt(pos.column-1); + var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + if (!match) { + chr = line.charAt(pos.column); + pos = {row: pos.row, column: pos.column + 1}; + match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + before = false; + } + if (!match) + return null; + + if (match[1]) { + var bracketPos = this.$findClosingBracket(match[1], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(pos, bracketPos); + if (!before) { + range.end.column++; + range.start.column--; + } + range.cursor = range.end; + } else { + var bracketPos = this.$findOpeningBracket(match[2], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(bracketPos, pos); + if (!before) { + range.start.column++; + range.end.column--; + } + range.cursor = range.start; + } + + return range; + }; + + this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{" + }; + + this.$findOpeningBracket = function(bracket, position, typeRe) { + var openBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("rparen", ".paren") + .replace(/\b(?:end)\b/, "(?:start|begin|end)") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; + var value = token.value; + + while (true) { + + while (valueIndex >= 0) { + var chr = value.charAt(valueIndex); + if (chr == openBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex -= 1; + } + do { + token = iterator.stepBackward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + value = token.value; + valueIndex = value.length - 1; + } + + return null; + }; + + this.$findClosingBracket = function(bracket, position, typeRe) { + var closingBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("lparen", ".paren") + .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn(); + + while (true) { + + var value = token.value; + var valueLength = value.length; + while (valueIndex < valueLength) { + var chr = value.charAt(valueIndex); + if (chr == closingBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex += 1; + } + do { + token = iterator.stepForward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + valueIndex = 0; + } + + return null; + }; + } + exports.BracketMatch = BracketMatch; + + }); + + ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/bidihandler","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var lang = acequire("./lib/lang"); + var BidiHandler = acequire("./bidihandler").BidiHandler; + var config = acequire("./config"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var Selection = acequire("./selection").Selection; + var TextMode = acequire("./mode/text").Mode; + var Range = acequire("./range").Range; + var Document = acequire("./document").Document; + var BackgroundTokenizer = acequire("./background_tokenizer").BackgroundTokenizer; + var SearchHighlight = acequire("./search_highlight").SearchHighlight; + + var EditSession = function(text, mode) { + this.$breakpoints = []; + this.$decorations = []; + this.$frontMarkers = {}; + this.$backMarkers = {}; + this.$markerId = 1; + this.$undoSelect = true; + + this.$foldData = []; + this.id = "session" + (++EditSession.$uid); + this.$foldData.toString = function() { + return this.join("\n"); + }; + this.on("changeFold", this.onChangeFold.bind(this)); + this.$onChange = this.onChange.bind(this); + + if (typeof text != "object" || !text.getLine) + text = new Document(text); + + this.$bidiHandler = new BidiHandler(this); + this.setDocument(text); + this.selection = new Selection(this); + + config.resetOptions(this); + this.setMode(mode); + config._signal("session", this); + }; + + + EditSession.$uid = 0; + + (function() { + + oop.implement(this, EventEmitter); + this.setDocument = function(doc) { + if (this.doc) + this.doc.removeListener("change", this.$onChange); + + this.doc = doc; + doc.on("change", this.$onChange); + + if (this.bgTokenizer) + this.bgTokenizer.setDocument(this.getDocument()); + + this.resetCaches(); + }; + this.getDocument = function() { + return this.doc; + }; + this.$resetRowCache = function(docRow) { + if (!docRow) { + this.$docRowCache = []; + this.$screenRowCache = []; + return; + } + var l = this.$docRowCache.length; + var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1; + if (l > i) { + this.$docRowCache.splice(i, l); + this.$screenRowCache.splice(i, l); + } + }; + + this.$getRowCacheIndex = function(cacheArray, val) { + var low = 0; + var hi = cacheArray.length - 1; + + while (low <= hi) { + var mid = (low + hi) >> 1; + var c = cacheArray[mid]; + + if (val > c) + low = mid + 1; + else if (val < c) + hi = mid - 1; + else + return mid; + } + + return low -1; + }; + + this.resetCaches = function() { + this.$modified = true; + this.$wrapData = []; + this.$rowLengthCache = []; + this.$resetRowCache(0); + if (this.bgTokenizer) + this.bgTokenizer.start(0); + }; + + this.onChangeFold = function(e) { + var fold = e.data; + this.$resetRowCache(fold.start.row); + }; + + this.onChange = function(delta) { + this.$modified = true; + this.$bidiHandler.onChange(delta); + this.$resetRowCache(delta.start.row); + + var removedFolds = this.$updateInternalDataOnChange(delta); + if (!this.$fromUndo && this.$undoManager && !delta.ignore) { + this.$deltasDoc.push(delta); + if (removedFolds && removedFolds.length != 0) { + this.$deltasFold.push({ + action: "removeFolds", + folds: removedFolds + }); + } + + this.$informUndoManager.schedule(); + } + + this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); + this._signal("change", delta); + }; + this.setValue = function(text) { + this.doc.setValue(text); + this.selection.moveTo(0, 0); + + this.$resetRowCache(0); + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + this.setUndoManager(this.$undoManager); + this.getUndoManager().reset(); + }; + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.getState = function(row) { + return this.bgTokenizer.getState(row); + }; + this.getTokens = function(row) { + return this.bgTokenizer.getTokens(row); + }; + this.getTokenAt = function(row, column) { + var tokens = this.bgTokenizer.getTokens(row); + var token, c = 0; + if (column == null) { + var i = tokens.length - 1; + c = this.getLine(row).length; + } else { + for (var i = 0; i < tokens.length; i++) { + c += tokens[i].value.length; + if (c >= column) + break; + } + } + token = tokens[i]; + if (!token) + return null; + token.index = i; + token.start = c - token.value.length; + return token; + }; + this.setUndoManager = function(undoManager) { + this.$undoManager = undoManager; + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + + if (this.$informUndoManager) + this.$informUndoManager.cancel(); + + if (undoManager) { + var self = this; + + this.$syncInformUndoManager = function() { + self.$informUndoManager.cancel(); + + if (self.$deltasFold.length) { + self.$deltas.push({ + group: "fold", + deltas: self.$deltasFold + }); + self.$deltasFold = []; + } + + if (self.$deltasDoc.length) { + self.$deltas.push({ + group: "doc", + deltas: self.$deltasDoc + }); + self.$deltasDoc = []; + } + + if (self.$deltas.length > 0) { + undoManager.execute({ + action: "aceupdate", + args: [self.$deltas, self], + merge: self.mergeUndoDeltas + }); + } + self.mergeUndoDeltas = false; + self.$deltas = []; + }; + this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); + } + }; + this.markUndoGroup = function() { + if (this.$syncInformUndoManager) + this.$syncInformUndoManager(); + }; + + this.$defaultUndoManager = { + undo: function() {}, + redo: function() {}, + reset: function() {} + }; + this.getUndoManager = function() { + return this.$undoManager || this.$defaultUndoManager; + }; + this.getTabString = function() { + if (this.getUseSoftTabs()) { + return lang.stringRepeat(" ", this.getTabSize()); + } else { + return "\t"; + } + }; + this.setUseSoftTabs = function(val) { + this.setOption("useSoftTabs", val); + }; + this.getUseSoftTabs = function() { + return this.$useSoftTabs && !this.$mode.$indentWithTabs; + }; + this.setTabSize = function(tabSize) { + this.setOption("tabSize", tabSize); + }; + this.getTabSize = function() { + return this.$tabSize; + }; + this.isTabStop = function(position) { + return this.$useSoftTabs && (position.column % this.$tabSize === 0); + }; + this.setNavigateWithinSoftTabs = function (navigateWithinSoftTabs) { + this.setOption("navigateWithinSoftTabs", navigateWithinSoftTabs); + }; + this.getNavigateWithinSoftTabs = function() { + return this.$navigateWithinSoftTabs; + }; + + this.$overwrite = false; + this.setOverwrite = function(overwrite) { + this.setOption("overwrite", overwrite); + }; + this.getOverwrite = function() { + return this.$overwrite; + }; + this.toggleOverwrite = function() { + this.setOverwrite(!this.$overwrite); + }; + this.addGutterDecoration = function(row, className) { + if (!this.$decorations[row]) + this.$decorations[row] = ""; + this.$decorations[row] += " " + className; + this._signal("changeBreakpoint", {}); + }; + this.removeGutterDecoration = function(row, className) { + this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); + this._signal("changeBreakpoint", {}); + }; + this.getBreakpoints = function() { + return this.$breakpoints; + }; + this.setBreakpoints = function(rows) { + this.$breakpoints = []; + for (var i=0; i 0) + inToken = !!line.charAt(column - 1).match(this.tokenRe); + + if (!inToken) + inToken = !!line.charAt(column).match(this.tokenRe); + + if (inToken) + var re = this.tokenRe; + else if (/^\s+$/.test(line.slice(column-1, column+1))) + var re = /\s/; + else + var re = this.nonTokenRe; + + var start = column; + if (start > 0) { + do { + start--; + } + while (start >= 0 && line.charAt(start).match(re)); + start++; + } + + var end = column; + while (end < line.length && line.charAt(end).match(re)) { + end++; + } + + return new Range(row, start, row, end); + }; + this.getAWordRange = function(row, column) { + var wordRange = this.getWordRange(row, column); + var line = this.getLine(wordRange.end.row); + + while (line.charAt(wordRange.end.column).match(/[ \t]/)) { + wordRange.end.column += 1; + } + return wordRange; + }; + this.setNewLineMode = function(newLineMode) { + this.doc.setNewLineMode(newLineMode); + }; + this.getNewLineMode = function() { + return this.doc.getNewLineMode(); + }; + this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); }; + this.getUseWorker = function() { return this.$useWorker; }; + this.onReloadTokenizer = function(e) { + var rows = e.data; + this.bgTokenizer.start(rows.first); + this._signal("tokenizerUpdate", e); + }; + + this.$modes = {}; + this.$mode = null; + this.$modeId = null; + this.setMode = function(mode, cb) { + if (mode && typeof mode === "object") { + if (mode.getTokenizer) + return this.$onChangeMode(mode); + var options = mode; + var path = options.path; + } else { + path = mode || "ace/mode/text"; + } + if (!this.$modes["ace/mode/text"]) + this.$modes["ace/mode/text"] = new TextMode(); + + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + cb && cb(); + return; + } + this.$modeId = path; + config.loadModule(["mode", path], function(m) { + if (this.$modeId !== path) + return cb && cb(); + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + } else if (m && m.Mode) { + m = new m.Mode(options); + if (!options) { + this.$modes[path] = m; + m.$id = path; + } + this.$onChangeMode(m); + } + cb && cb(); + }.bind(this)); + if (!this.$mode) + this.$onChangeMode(this.$modes["ace/mode/text"], true); + }; + + this.$onChangeMode = function(mode, $isPlaceholder) { + if (!$isPlaceholder) + this.$modeId = mode.$id; + if (this.$mode === mode) + return; + + this.$mode = mode; + + this.$stopWorker(); + + if (this.$useWorker) + this.$startWorker(); + + var tokenizer = mode.getTokenizer(); + + if(tokenizer.addEventListener !== undefined) { + var onReloadTokenizer = this.onReloadTokenizer.bind(this); + tokenizer.addEventListener("update", onReloadTokenizer); + } + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._signal("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + + this.bgTokenizer.setDocument(this.getDocument()); + + this.tokenRe = mode.tokenRe; + this.nonTokenRe = mode.nonTokenRe; + + + if (!$isPlaceholder) { + if (mode.attachToSession) + mode.attachToSession(this); + this.$options.wrapMethod.set.call(this, this.$wrapMethod); + this.$setFolding(mode.foldingRules); + this.bgTokenizer.start(0); + this._emit("changeMode"); + } + }; + + this.$stopWorker = function() { + if (this.$worker) { + this.$worker.terminate(); + this.$worker = null; + } + }; + + this.$startWorker = function() { + try { + this.$worker = this.$mode.createWorker(this); + } catch (e) { + config.warn("Could not load worker", e); + this.$worker = null; + } + }; + this.getMode = function() { + return this.$mode; + }; + + this.$scrollTop = 0; + this.setScrollTop = function(scrollTop) { + if (this.$scrollTop === scrollTop || isNaN(scrollTop)) + return; + + this.$scrollTop = scrollTop; + this._signal("changeScrollTop", scrollTop); + }; + this.getScrollTop = function() { + return this.$scrollTop; + }; + + this.$scrollLeft = 0; + this.setScrollLeft = function(scrollLeft) { + if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) + return; + + this.$scrollLeft = scrollLeft; + this._signal("changeScrollLeft", scrollLeft); + }; + this.getScrollLeft = function() { + return this.$scrollLeft; + }; + this.getScreenWidth = function() { + this.$computeWidth(); + if (this.lineWidgets) + return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth); + return this.screenWidth; + }; + + this.getLineWidgetMaxWidth = function() { + if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth; + var width = 0; + this.lineWidgets.forEach(function(w) { + if (w && w.screenWidth > width) + width = w.screenWidth; + }); + return this.lineWidgetWidth = width; + }; + + this.$computeWidth = function(force) { + if (this.$modified || force) { + this.$modified = false; + + if (this.$useWrapMode) + return this.screenWidth = this.$wrapLimit; + + var lines = this.doc.getAllLines(); + var cache = this.$rowLengthCache; + var longestScreenLine = 0; + var foldIndex = 0; + var foldLine = this.$foldData[foldIndex]; + var foldStart = foldLine ? foldLine.start.row : Infinity; + var len = lines.length; + + for (var i = 0; i < len; i++) { + if (i > foldStart) { + i = foldLine.end.row + 1; + if (i >= len) + break; + foldLine = this.$foldData[foldIndex++]; + foldStart = foldLine ? foldLine.start.row : Infinity; + } + + if (cache[i] == null) + cache[i] = this.$getStringScreenWidth(lines[i])[0]; + + if (cache[i] > longestScreenLine) + longestScreenLine = cache[i]; + } + this.screenWidth = longestScreenLine; + } + }; + this.getLine = function(row) { + return this.doc.getLine(row); + }; + this.getLines = function(firstRow, lastRow) { + return this.doc.getLines(firstRow, lastRow); + }; + this.getLength = function() { + return this.doc.getLength(); + }; + this.getTextRange = function(range) { + return this.doc.getTextRange(range || this.selection.getRange()); + }; + this.insert = function(position, text) { + return this.doc.insert(position, text); + }; + this.remove = function(range) { + return this.doc.remove(range); + }; + this.removeFullLines = function(firstRow, lastRow){ + return this.doc.removeFullLines(firstRow, lastRow); + }; + this.undoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = deltas.length - 1; i != -1; i--) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.revertDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, true, lastUndoRange); + } else { + delta.deltas.forEach(function(foldDelta) { + this.addFolds(foldDelta.folds); + }, this); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.redoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = 0; i < deltas.length; i++) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.applyDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, false, lastUndoRange); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.setUndoSelect = function(enable) { + this.$undoSelect = enable; + }; + + this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { + function isInsert(delta) { + return isUndo ? delta.action !== "insert" : delta.action === "insert"; + } + + var delta = deltas[0]; + var range, point; + var lastDeltaIsInsert = false; + if (isInsert(delta)) { + range = Range.fromPoints(delta.start, delta.end); + lastDeltaIsInsert = true; + } else { + range = Range.fromPoints(delta.start, delta.start); + lastDeltaIsInsert = false; + } + + for (var i = 1; i < deltas.length; i++) { + delta = deltas[i]; + if (isInsert(delta)) { + point = delta.start; + if (range.compare(point.row, point.column) == -1) { + range.setStart(point); + } + point = delta.end; + if (range.compare(point.row, point.column) == 1) { + range.setEnd(point); + } + lastDeltaIsInsert = true; + } else { + point = delta.start; + if (range.compare(point.row, point.column) == -1) { + range = Range.fromPoints(delta.start, delta.start); + } + lastDeltaIsInsert = false; + } + } + if (lastUndoRange != null) { + if (Range.comparePoints(lastUndoRange.start, range.start) === 0) { + lastUndoRange.start.column += range.end.column - range.start.column; + lastUndoRange.end.column += range.end.column - range.start.column; + } + + var cmp = lastUndoRange.compareRange(range); + if (cmp == 1) { + range.setStart(lastUndoRange.start); + } else if (cmp == -1) { + range.setEnd(lastUndoRange.end); + } + } + + return range; + }; + this.replace = function(range, text) { + return this.doc.replace(range, text); + }; + this.moveText = function(fromRange, toPosition, copy) { + var text = this.getTextRange(fromRange); + var folds = this.getFoldsInRange(fromRange); + + var toRange = Range.fromPoints(toPosition, toPosition); + if (!copy) { + this.remove(fromRange); + var rowDiff = fromRange.start.row - fromRange.end.row; + var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column; + if (collDiff) { + if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column) + toRange.start.column += collDiff; + if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column) + toRange.end.column += collDiff; + } + if (rowDiff && toRange.start.row >= fromRange.end.row) { + toRange.start.row += rowDiff; + toRange.end.row += rowDiff; + } + } + + toRange.end = this.insert(toRange.start, text); + if (folds.length) { + var oldStart = fromRange.start; + var newStart = toRange.start; + var rowDiff = newStart.row - oldStart.row; + var collDiff = newStart.column - oldStart.column; + this.addFolds(folds.map(function(x) { + x = x.clone(); + if (x.start.row == oldStart.row) + x.start.column += collDiff; + if (x.end.row == oldStart.row) + x.end.column += collDiff; + x.start.row += rowDiff; + x.end.row += rowDiff; + return x; + })); + } + + return toRange; + }; + this.indentRows = function(startRow, endRow, indentString) { + indentString = indentString.replace(/\t/g, this.getTabString()); + for (var row=startRow; row<=endRow; row++) + this.doc.insertInLine({row: row, column: 0}, indentString); + }; + this.outdentRows = function (range) { + var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); + var size = this.getTabSize(); + + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { + var line = this.getLine(i); + + deleteRange.start.row = i; + deleteRange.end.row = i; + for (var j = 0; j < size; ++j) + if (line.charAt(j) != ' ') + break; + if (j < size && line.charAt(j) == '\t') { + deleteRange.start.column = j; + deleteRange.end.column = j + 1; + } else { + deleteRange.start.column = 0; + deleteRange.end.column = j; + } + this.remove(deleteRange); + } + }; + + this.$moveLines = function(firstRow, lastRow, dir) { + firstRow = this.getRowFoldStart(firstRow); + lastRow = this.getRowFoldEnd(lastRow); + if (dir < 0) { + var row = this.getRowFoldStart(firstRow + dir); + if (row < 0) return 0; + var diff = row-firstRow; + } else if (dir > 0) { + var row = this.getRowFoldEnd(lastRow + dir); + if (row > this.doc.getLength()-1) return 0; + var diff = row-lastRow; + } else { + firstRow = this.$clipRowToDocument(firstRow); + lastRow = this.$clipRowToDocument(lastRow); + var diff = lastRow - firstRow + 1; + } + + var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE); + var folds = this.getFoldsInRange(range).map(function(x){ + x = x.clone(); + x.start.row += diff; + x.end.row += diff; + return x; + }); + + var lines = dir == 0 + ? this.doc.getLines(firstRow, lastRow) + : this.doc.removeFullLines(firstRow, lastRow); + this.doc.insertFullLines(firstRow+diff, lines); + folds.length && this.addFolds(folds); + return diff; + }; + this.moveLinesUp = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, -1); + }; + this.moveLinesDown = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 1); + }; + this.duplicateLines = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 0); + }; + + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.doc.getLength()-1)); + }; + + this.$clipColumnToRow = function(row, column) { + if (column < 0) + return 0; + return Math.min(this.doc.getLine(row).length, column); + }; + + + this.$clipPositionToDocument = function(row, column) { + column = Math.max(0, column); + + if (row < 0) { + row = 0; + column = 0; + } else { + var len = this.doc.getLength(); + if (row >= len) { + row = len - 1; + column = this.doc.getLine(len-1).length; + } else { + column = Math.min(this.doc.getLine(row).length, column); + } + } + + return { + row: row, + column: column + }; + }; + + this.$clipRangeToDocument = function(range) { + if (range.start.row < 0) { + range.start.row = 0; + range.start.column = 0; + } else { + range.start.column = this.$clipColumnToRow( + range.start.row, + range.start.column + ); + } + + var len = this.doc.getLength() - 1; + if (range.end.row > len) { + range.end.row = len; + range.end.column = this.doc.getLine(len).length; + } else { + range.end.column = this.$clipColumnToRow( + range.end.row, + range.end.column + ); + } + return range; + }; + this.$wrapLimit = 80; + this.$useWrapMode = false; + this.$wrapLimitRange = { + min : null, + max : null + }; + this.setUseWrapMode = function(useWrapMode) { + if (useWrapMode != this.$useWrapMode) { + this.$useWrapMode = useWrapMode; + this.$modified = true; + this.$resetRowCache(0); + if (useWrapMode) { + var len = this.getLength(); + this.$wrapData = Array(len); + this.$updateWrapData(0, len - 1); + } + + this._signal("changeWrapMode"); + } + }; + this.getUseWrapMode = function() { + return this.$useWrapMode; + }; + this.setWrapLimitRange = function(min, max) { + if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) { + this.$wrapLimitRange = { min: min, max: max }; + this.$modified = true; + this.$bidiHandler.markAsDirty(); + if (this.$useWrapMode) + this._signal("changeWrapMode"); + } + }; + this.adjustWrapLimit = function(desiredLimit, $printMargin) { + var limits = this.$wrapLimitRange; + if (limits.max < 0) + limits = {min: $printMargin, max: $printMargin}; + var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); + if (wrapLimit != this.$wrapLimit && wrapLimit > 1) { + this.$wrapLimit = wrapLimit; + this.$modified = true; + if (this.$useWrapMode) { + this.$updateWrapData(0, this.getLength() - 1); + this.$resetRowCache(0); + this._signal("changeWrapLimit"); + } + return true; + } + return false; + }; + + this.$constrainWrapLimit = function(wrapLimit, min, max) { + if (min) + wrapLimit = Math.max(min, wrapLimit); + + if (max) + wrapLimit = Math.min(max, wrapLimit); + + return wrapLimit; + }; + this.getWrapLimit = function() { + return this.$wrapLimit; + }; + this.setWrapLimit = function (limit) { + this.setWrapLimitRange(limit, limit); + }; + this.getWrapLimitRange = function() { + return { + min : this.$wrapLimitRange.min, + max : this.$wrapLimitRange.max + }; + }; + + this.$updateInternalDataOnChange = function(delta) { + var useWrapMode = this.$useWrapMode; + var action = delta.action; + var start = delta.start; + var end = delta.end; + var firstRow = start.row; + var lastRow = end.row; + var len = lastRow - firstRow; + var removedFolds = null; + + this.$updating = true; + if (len != 0) { + if (action === "remove") { + this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); + + var foldLines = this.$foldData; + removedFolds = this.getFoldsInRange(delta); + this.removeFolds(removedFolds); + + var foldLine = this.getFoldLine(end.row); + var idx = 0; + if (foldLine) { + foldLine.addRemoveChars(end.row, end.column, start.column - end.column); + foldLine.shiftRow(-len); + + var foldLineBefore = this.getFoldLine(firstRow); + if (foldLineBefore && foldLineBefore !== foldLine) { + foldLineBefore.merge(foldLine); + foldLine = foldLineBefore; + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= end.row) { + foldLine.shiftRow(-len); + } + } + + lastRow = firstRow; + } else { + var args = Array(len); + args.unshift(firstRow, 0); + var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache; + arr.splice.apply(arr, args); + var foldLines = this.$foldData; + var foldLine = this.getFoldLine(firstRow); + var idx = 0; + if (foldLine) { + var cmp = foldLine.range.compareInside(start.row, start.column); + if (cmp == 0) { + foldLine = foldLine.split(start.row, start.column); + if (foldLine) { + foldLine.shiftRow(len); + foldLine.addRemoveChars(lastRow, 0, end.column - start.column); + } + } else + if (cmp == -1) { + foldLine.addRemoveChars(firstRow, 0, end.column - start.column); + foldLine.shiftRow(len); + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= firstRow) { + foldLine.shiftRow(len); + } + } + } + } else { + len = Math.abs(delta.start.column - delta.end.column); + if (action === "remove") { + removedFolds = this.getFoldsInRange(delta); + this.removeFolds(removedFolds); + + len = -len; + } + var foldLine = this.getFoldLine(firstRow); + if (foldLine) { + foldLine.addRemoveChars(firstRow, start.column, len); + } + } + + if (useWrapMode && this.$wrapData.length != this.doc.getLength()) { + console.error("doc.getLength() and $wrapData.length have to be the same!"); + } + this.$updating = false; + + if (useWrapMode) + this.$updateWrapData(firstRow, lastRow); + else + this.$updateRowLengthCache(firstRow, lastRow); + + return removedFolds; + }; + + this.$updateRowLengthCache = function(firstRow, lastRow, b) { + this.$rowLengthCache[firstRow] = null; + this.$rowLengthCache[lastRow] = null; + }; + + this.$updateWrapData = function(firstRow, lastRow) { + var lines = this.doc.getAllLines(); + var tabSize = this.getTabSize(); + var wrapData = this.$wrapData; + var wrapLimit = this.$wrapLimit; + var tokens; + var foldLine; + + var row = firstRow; + lastRow = Math.min(lastRow, lines.length - 1); + while (row <= lastRow) { + foldLine = this.getFoldLine(row, foldLine); + if (!foldLine) { + tokens = this.$getDisplayTokens(lines[row]); + wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row ++; + } else { + tokens = []; + foldLine.walk(function(placeholder, row, column, lastColumn) { + var walkTokens; + if (placeholder != null) { + walkTokens = this.$getDisplayTokens( + placeholder, tokens.length); + walkTokens[0] = PLACEHOLDER_START; + for (var i = 1; i < walkTokens.length; i++) { + walkTokens[i] = PLACEHOLDER_BODY; + } + } else { + walkTokens = this.$getDisplayTokens( + lines[row].substring(lastColumn, column), + tokens.length); + } + tokens = tokens.concat(walkTokens); + }.bind(this), + foldLine.end.row, + lines[foldLine.end.row].length + 1 + ); + + wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row = foldLine.end.row + 1; + } + } + }; + var CHAR = 1, + CHAR_EXT = 2, + PLACEHOLDER_START = 3, + PLACEHOLDER_BODY = 4, + PUNCTUATION = 9, + SPACE = 10, + TAB = 11, + TAB_SPACE = 12; + + + this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { + if (tokens.length == 0) { + return []; + } + + var splits = []; + var displayLength = tokens.length; + var lastSplit = 0, lastDocSplit = 0; + + var isCode = this.$wrapAsCode; + + var indentedSoftWrap = this.$indentedSoftWrap; + var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8) + || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2); + + function getWrapIndent() { + var indentation = 0; + if (maxIndent === 0) + return indentation; + if (indentedSoftWrap) { + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token == SPACE) + indentation += 1; + else if (token == TAB) + indentation += tabSize; + else if (token == TAB_SPACE) + continue; + else + break; + } + } + if (isCode && indentedSoftWrap !== false) + indentation += tabSize; + return Math.min(indentation, maxIndent); + } + function addSplit(screenPos) { + var displayed = tokens.slice(lastSplit, screenPos); + var len = displayed.length; + displayed.join("") + .replace(/12/g, function() { + len -= 1; + }) + .replace(/2/g, function() { + len -= 1; + }); + + if (!splits.length) { + indent = getWrapIndent(); + splits.indent = indent; + } + lastDocSplit += len; + splits.push(lastDocSplit); + lastSplit = screenPos; + } + var indent = 0; + while (displayLength - lastSplit > wrapLimit - indent) { + var split = lastSplit + wrapLimit - indent; + if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) { + addSplit(split); + continue; + } + if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) { + for (split; split != lastSplit - 1; split--) { + if (tokens[split] == PLACEHOLDER_START) { + break; + } + } + if (split > lastSplit) { + addSplit(split); + continue; + } + split = lastSplit + wrapLimit; + for (split; split < tokens.length; split++) { + if (tokens[split] != PLACEHOLDER_BODY) { + break; + } + } + if (split == tokens.length) { + break; // Breaks the while-loop. + } + addSplit(split); + continue; + } + var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1); + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + if (isCode) { + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + while (split > minSplit && tokens[split] == PUNCTUATION) { + split --; + } + } else { + while (split > minSplit && tokens[split] < SPACE) { + split --; + } + } + if (split > minSplit) { + addSplit(++split); + continue; + } + split = lastSplit + wrapLimit; + if (tokens[split] == CHAR_EXT) + split--; + addSplit(split - indent); + } + return splits; + }; + this.$getDisplayTokens = function(str, offset) { + var arr = []; + var tabSize; + offset = offset || 0; + + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + if (c == 9) { + tabSize = this.getScreenTabSize(arr.length + offset); + arr.push(TAB); + for (var n = 1; n < tabSize; n++) { + arr.push(TAB_SPACE); + } + } + else if (c == 32) { + arr.push(SPACE); + } else if((c > 39 && c < 48) || (c > 57 && c < 64)) { + arr.push(PUNCTUATION); + } + else if (c >= 0x1100 && isFullWidth(c)) { + arr.push(CHAR, CHAR_EXT); + } else { + arr.push(CHAR); + } + } + return arr; + }; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn == 0) + return [0, 0]; + if (maxScreenColumn == null) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charCodeAt(column); + if (c == 9) { + screenColumn += this.getScreenTabSize(screenColumn); + } + else if (c >= 0x1100 && isFullWidth(c)) { + screenColumn += 2; + } else { + screenColumn += 1; + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + + this.lineWidgets = null; + this.getRowLength = function(row) { + if (this.lineWidgets) + var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0; + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + this.getRowLineCount = function(row) { + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1; + } else { + return this.$wrapData[row].length + 1; + } + }; + + this.getRowWrapIndent = function(screenRow) { + if (this.$useWrapMode) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + var splits = this.$wrapData[pos.row]; + return splits.length && splits[0] < pos.column ? splits.indent : 0; + } else { + return 0; + } + }; + this.getScreenLastRowColumn = function(screenRow) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + return this.documentToScreenColumn(pos.row, pos.column); + }; + this.getDocumentLastRowColumn = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.getScreenLastRowColumn(screenRow); + }; + this.getDocumentLastRowColumnPosition = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10); + }; + this.getRowSplitData = function(row) { + if (!this.$useWrapMode) { + return undefined; + } else { + return this.$wrapData[row]; + } + }; + this.getScreenTabSize = function(screenColumn) { + return this.$tabSize - screenColumn % this.$tabSize; + }; + + + this.screenToDocumentRow = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).row; + }; + + + this.screenToDocumentColumn = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).column; + }; + this.screenToDocumentPosition = function(screenRow, screenColumn, offsetX) { + if (screenRow < 0) + return {row: 0, column: 0}; + + var line; + var docRow = 0; + var docColumn = 0; + var column; + var row = 0; + var rowLength = 0; + + var rowCache = this.$screenRowCache; + var i = this.$getRowCacheIndex(rowCache, screenRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var docRow = this.$docRowCache[i]; + var doCache = screenRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var maxRow = this.getLength() - 1; + var foldLine = this.getNextFoldLine(docRow); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (row <= screenRow) { + rowLength = this.getRowLength(docRow); + if (row + rowLength > screenRow || docRow >= maxRow) { + break; + } else { + row += rowLength; + docRow++; + if (docRow > foldStart) { + docRow = foldLine.end.row+1; + foldLine = this.getNextFoldLine(docRow, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + } + + if (doCache) { + this.$docRowCache.push(docRow); + this.$screenRowCache.push(row); + } + } + + if (foldLine && foldLine.start.row <= docRow) { + line = this.getFoldDisplayLine(foldLine); + docRow = foldLine.start.row; + } else if (row + rowLength <= screenRow || docRow > maxRow) { + return { + row: maxRow, + column: this.getLine(maxRow).length + }; + } else { + line = this.getLine(docRow); + foldLine = null; + } + var wrapIndent = 0, splitIndex = Math.floor(screenRow - row); + if (this.$useWrapMode) { + var splits = this.$wrapData[docRow]; + if (splits) { + column = splits[splitIndex]; + if(splitIndex > 0 && splits.length) { + wrapIndent = splits.indent; + docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; + line = line.substring(docColumn); + } + } + } + + if (offsetX !== undefined && this.$bidiHandler.isBidiRow(row + splitIndex, docRow, splitIndex)) + screenColumn = this.$bidiHandler.offsetToCol(offsetX); + + docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; + if (this.$useWrapMode && docColumn >= column) + docColumn = column - 1; + + if (foldLine) + return foldLine.idxToPosition(docColumn); + + return {row: docRow, column: docColumn}; + }; + this.documentToScreenPosition = function(docRow, docColumn) { + if (typeof docColumn === "undefined") + var pos = this.$clipPositionToDocument(docRow.row, docRow.column); + else + pos = this.$clipPositionToDocument(docRow, docColumn); + + docRow = pos.row; + docColumn = pos.column; + + var screenRow = 0; + var foldStartRow = null; + var fold = null; + fold = this.getFoldAt(docRow, docColumn, 1); + if (fold) { + docRow = fold.start.row; + docColumn = fold.start.column; + } + + var rowEnd, row = 0; + + + var rowCache = this.$docRowCache; + var i = this.$getRowCacheIndex(rowCache, docRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var screenRow = this.$screenRowCache[i]; + var doCache = docRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var foldLine = this.getNextFoldLine(row); + var foldStart = foldLine ?foldLine.start.row :Infinity; + + while (row < docRow) { + if (row >= foldStart) { + rowEnd = foldLine.end.row + 1; + if (rowEnd > docRow) + break; + foldLine = this.getNextFoldLine(rowEnd, foldLine); + foldStart = foldLine ?foldLine.start.row :Infinity; + } + else { + rowEnd = row + 1; + } + + screenRow += this.getRowLength(row); + row = rowEnd; + + if (doCache) { + this.$docRowCache.push(row); + this.$screenRowCache.push(screenRow); + } + } + var textLine = ""; + if (foldLine && row >= foldStart) { + textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn); + foldStartRow = foldLine.start.row; + } else { + textLine = this.getLine(docRow).substring(0, docColumn); + foldStartRow = docRow; + } + var wrapIndent = 0; + if (this.$useWrapMode) { + var wrapRow = this.$wrapData[foldStartRow]; + if (wrapRow) { + var screenRowOffset = 0; + while (textLine.length >= wrapRow[screenRowOffset]) { + screenRow ++; + screenRowOffset++; + } + textLine = textLine.substring( + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); + wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; + } + } + + return { + row: screenRow, + column: wrapIndent + this.$getStringScreenWidth(textLine)[0] + }; + }; + this.documentToScreenColumn = function(row, docColumn) { + return this.documentToScreenPosition(row, docColumn).column; + }; + this.documentToScreenRow = function(docRow, docColumn) { + return this.documentToScreenPosition(docRow, docColumn).row; + }; + this.getScreenLength = function() { + var screenRows = 0; + var fold = null; + if (!this.$useWrapMode) { + screenRows = this.getLength(); + var foldData = this.$foldData; + for (var i = 0; i < foldData.length; i++) { + fold = foldData[i]; + screenRows -= fold.end.row - fold.start.row; + } + } else { + var lastRow = this.$wrapData.length; + var row = 0, i = 0; + var fold = this.$foldData[i++]; + var foldStart = fold ? fold.start.row :Infinity; + + while (row < lastRow) { + var splits = this.$wrapData[row]; + screenRows += splits ? splits.length + 1 : 1; + row ++; + if (row > foldStart) { + row = fold.end.row+1; + fold = this.$foldData[i++]; + foldStart = fold ?fold.start.row :Infinity; + } + } + } + if (this.lineWidgets) + screenRows += this.$getWidgetScreenLength(); + + return screenRows; + }; + this.$setFontMetrics = function(fm) { + if (!this.$enableVarChar) return; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn === 0) + return [0, 0]; + if (!maxScreenColumn) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charAt(column); + if (c === "\t") { + screenColumn += this.getScreenTabSize(screenColumn); + } else { + screenColumn += fm.getCharacterWidth(c); + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + }; + + this.destroy = function() { + if (this.bgTokenizer) { + this.bgTokenizer.setDocument(null); + this.bgTokenizer = null; + } + this.$stopWorker(); + }; + + this.isFullWidth = isFullWidth; + function isFullWidth(c) { + if (c < 0x1100) + return false; + return c >= 0x1100 && c <= 0x115F || + c >= 0x11A3 && c <= 0x11A7 || + c >= 0x11FA && c <= 0x11FF || + c >= 0x2329 && c <= 0x232A || + c >= 0x2E80 && c <= 0x2E99 || + c >= 0x2E9B && c <= 0x2EF3 || + c >= 0x2F00 && c <= 0x2FD5 || + c >= 0x2FF0 && c <= 0x2FFB || + c >= 0x3000 && c <= 0x303E || + c >= 0x3041 && c <= 0x3096 || + c >= 0x3099 && c <= 0x30FF || + c >= 0x3105 && c <= 0x312D || + c >= 0x3131 && c <= 0x318E || + c >= 0x3190 && c <= 0x31BA || + c >= 0x31C0 && c <= 0x31E3 || + c >= 0x31F0 && c <= 0x321E || + c >= 0x3220 && c <= 0x3247 || + c >= 0x3250 && c <= 0x32FE || + c >= 0x3300 && c <= 0x4DBF || + c >= 0x4E00 && c <= 0xA48C || + c >= 0xA490 && c <= 0xA4C6 || + c >= 0xA960 && c <= 0xA97C || + c >= 0xAC00 && c <= 0xD7A3 || + c >= 0xD7B0 && c <= 0xD7C6 || + c >= 0xD7CB && c <= 0xD7FB || + c >= 0xF900 && c <= 0xFAFF || + c >= 0xFE10 && c <= 0xFE19 || + c >= 0xFE30 && c <= 0xFE52 || + c >= 0xFE54 && c <= 0xFE66 || + c >= 0xFE68 && c <= 0xFE6B || + c >= 0xFF01 && c <= 0xFF60 || + c >= 0xFFE0 && c <= 0xFFE6; + } + + }).call(EditSession.prototype); + + acequire("./edit_session/folding").Folding.call(EditSession.prototype); + acequire("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); + + + config.defineOptions(EditSession.prototype, "session", { + wrap: { + set: function(value) { + if (!value || value == "off") + value = false; + else if (value == "free") + value = true; + else if (value == "printMargin") + value = -1; + else if (typeof value == "string") + value = parseInt(value, 10) || false; + + if (this.$wrap == value) + return; + this.$wrap = value; + if (!value) { + this.setUseWrapMode(false); + } else { + var col = typeof value == "number" ? value : null; + this.setWrapLimitRange(col, col); + this.setUseWrapMode(true); + } + }, + get: function() { + if (this.getUseWrapMode()) { + if (this.$wrap == -1) + return "printMargin"; + if (!this.getWrapLimitRange().min) + return "free"; + return this.$wrap; + } + return "off"; + }, + handlesSet: true + }, + wrapMethod: { + set: function(val) { + val = val == "auto" + ? this.$mode.type != "text" + : val != "text"; + if (val != this.$wrapAsCode) { + this.$wrapAsCode = val; + if (this.$useWrapMode) { + this.$modified = true; + this.$resetRowCache(0); + this.$updateWrapData(0, this.getLength() - 1); + } + } + }, + initialValue: "auto" + }, + indentedSoftWrap: { initialValue: true }, + firstLineNumber: { + set: function() {this._signal("changeBreakpoint");}, + initialValue: 1 + }, + useWorker: { + set: function(useWorker) { + this.$useWorker = useWorker; + + this.$stopWorker(); + if (useWorker) + this.$startWorker(); + }, + initialValue: true + }, + useSoftTabs: {initialValue: true}, + tabSize: { + set: function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.$modified = true; + this.$rowLengthCache = []; + this.$tabSize = tabSize; + this._signal("changeTabSize"); + }, + initialValue: 4, + handlesSet: true + }, + navigateWithinSoftTabs: {initialValue: false}, + overwrite: { + set: function(val) {this._signal("changeOverwrite");}, + initialValue: false + }, + newLineMode: { + set: function(val) {this.doc.setNewLineMode(val);}, + get: function() {return this.doc.getNewLineMode();}, + handlesSet: true + }, + mode: { + set: function(val) { this.setMode(val); }, + get: function() { return this.$modeId; } + } + }); + + exports.EditSession = EditSession; + }); + + ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("./lib/lang"); + var oop = acequire("./lib/oop"); + var Range = acequire("./range").Range; + + var Search = function() { + this.$options = {}; + }; + + (function() { + this.set = function(options) { + oop.mixin(this.$options, options); + return this; + }; + this.getOptions = function() { + return lang.copyObject(this.$options); + }; + this.setOptions = function(options) { + this.$options = options; + }; + this.find = function(session) { + var options = this.$options; + var iterator = this.$matchIterator(session, options); + if (!iterator) + return false; + + var firstRange = null; + iterator.forEach(function(sr, sc, er, ec) { + firstRange = new Range(sr, sc, er, ec); + if (sc == ec && options.start && options.start.start + && options.skipCurrent != false && firstRange.isEqual(options.start) + ) { + firstRange = null; + return false; + } + + return true; + }); + + return firstRange; + }; + this.findAll = function(session) { + var options = this.$options; + if (!options.needle) + return []; + this.$assembleRegExp(options); + + var range = options.range; + var lines = range + ? session.getLines(range.start.row, range.end.row) + : session.doc.getAllLines(); + + var ranges = []; + var re = options.re; + if (options.$isMultiLine) { + var len = re.length; + var maxRow = lines.length - len; + var prevRange; + outer: for (var row = re.offset || 0; row <= maxRow; row++) { + for (var j = 0; j < len; j++) + if (lines[row + j].search(re[j]) == -1) + continue outer; + + var startLine = lines[row]; + var line = lines[row + len - 1]; + var startIndex = startLine.length - startLine.match(re[0])[0].length; + var endIndex = line.match(re[len - 1])[0].length; + + if (prevRange && prevRange.end.row === row && + prevRange.end.column > startIndex + ) { + continue; + } + ranges.push(prevRange = new Range( + row, startIndex, row + len - 1, endIndex + )); + if (len > 2) + row = row + len - 2; + } + } else { + for (var i = 0; i < lines.length; i++) { + var matches = lang.getMatchOffsets(lines[i], re); + for (var j = 0; j < matches.length; j++) { + var match = matches[j]; + ranges.push(new Range(i, match.offset, i, match.offset + match.length)); + } + } + } + + if (range) { + var startColumn = range.start.column; + var endColumn = range.start.column; + var i = 0, j = ranges.length - 1; + while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row) + i++; + + while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row) + j--; + + ranges = ranges.slice(i, j + 1); + for (i = 0, j = ranges.length; i < j; i++) { + ranges[i].start.row += range.start.row; + ranges[i].end.row += range.start.row; + } + } + + return ranges; + }; + this.replace = function(input, replacement) { + var options = this.$options; + + var re = this.$assembleRegExp(options); + if (options.$isMultiLine) + return replacement; + + if (!re) + return; + + var match = re.exec(input); + if (!match || match[0].length != input.length) + return null; + + replacement = input.replace(re, replacement); + if (options.preserveCase) { + replacement = replacement.split(""); + for (var i = Math.min(input.length, input.length); i--; ) { + var ch = input[i]; + if (ch && ch.toLowerCase() != ch) + replacement[i] = replacement[i].toUpperCase(); + else + replacement[i] = replacement[i].toLowerCase(); + } + replacement = replacement.join(""); + } + + return replacement; + }; + + this.$assembleRegExp = function(options, $disableFakeMultiline) { + if (options.needle instanceof RegExp) + return options.re = options.needle; + + var needle = options.needle; + + if (!options.needle) + return options.re = false; + + if (!options.regExp) + needle = lang.escapeRegExp(needle); + + if (options.wholeWord) + needle = addWordBoundary(needle, options); + + var modifier = options.caseSensitive ? "gm" : "gmi"; + + options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); + if (options.$isMultiLine) + return options.re = this.$assembleMultilineRegExp(needle, modifier); + + try { + var re = new RegExp(needle, modifier); + } catch(e) { + re = false; + } + return options.re = re; + }; + + this.$assembleMultilineRegExp = function(needle, modifier) { + var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n"); + var re = []; + for (var i = 0; i < parts.length; i++) try { + re.push(new RegExp(parts[i], modifier)); + } catch(e) { + return false; + } + return re; + }; + + this.$matchIterator = function(session, options) { + var re = this.$assembleRegExp(options); + if (!re) + return false; + var backwards = options.backwards == true; + var skipCurrent = options.skipCurrent != false; + + var range = options.range; + var start = options.start; + if (!start) + start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); + + if (start.start) + start = start[skipCurrent != backwards ? "end" : "start"]; + + var firstRow = range ? range.start.row : 0; + var lastRow = range ? range.end.row : session.getLength() - 1; + + if (backwards) { + var forEach = function(callback) { + var row = start.row; + if (forEachInLine(row, start.column, callback)) + return; + for (row--; row >= firstRow; row--) + if (forEachInLine(row, Number.MAX_VALUE, callback)) + return; + if (options.wrap == false) + return; + for (row = lastRow, firstRow = start.row; row >= firstRow; row--) + if (forEachInLine(row, Number.MAX_VALUE, callback)) + return; + }; + } + else { + var forEach = function(callback) { + var row = start.row; + if (forEachInLine(row, start.column, callback)) + return; + for (row = row + 1; row <= lastRow; row++) + if (forEachInLine(row, 0, callback)) + return; + if (options.wrap == false) + return; + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (forEachInLine(row, 0, callback)) + return; + }; + } + + if (options.$isMultiLine) { + var len = re.length; + var forEachInLine = function(row, offset, callback) { + var startRow = backwards ? row - len + 1 : row; + if (startRow < 0) return; + var line = session.getLine(startRow); + var startIndex = line.search(re[0]); + if (!backwards && startIndex < offset || startIndex === -1) return; + for (var i = 1; i < len; i++) { + line = session.getLine(startRow + i); + if (line.search(re[i]) == -1) + return; + } + var endIndex = line.match(re[len - 1])[0].length; + if (backwards && endIndex > offset) return; + if (callback(startRow, startIndex, startRow + len - 1, endIndex)) + return true; + }; + } + else if (backwards) { + var forEachInLine = function(row, endIndex, callback) { + var line = session.getLine(row); + var matches = []; + var m, last = 0; + re.lastIndex = 0; + while((m = re.exec(line))) { + var length = m[0].length; + last = m.index; + if (!length) { + if (last >= line.length) break; + re.lastIndex = last += 1; + } + if (m.index + length > endIndex) + break; + matches.push(m.index, length); + } + for (var i = matches.length - 1; i >= 0; i -= 2) { + var column = matches[i - 1]; + var length = matches[i]; + if (callback(row, column, row, column + length)) + return true; + } + }; + } + else { + var forEachInLine = function(row, startIndex, callback) { + var line = session.getLine(row); + var m; + var last = startIndex; + re.lastIndex = startIndex; + while((m = re.exec(line))) { + var length = m[0].length; + last = m.index; + if (callback(row, last, row,last + length)) + return true; + if (!length) { + re.lastIndex = last += 1; + if (last >= line.length) return false; + } + } + }; + } + return {forEach: forEach}; + }; + + }).call(Search.prototype); + + function addWordBoundary(needle, options) { + function wordBoundary(c) { + if (/\w/.test(c) || options.regExp) return "\\b"; + return ""; + } + return wordBoundary(needle[0]) + needle + + wordBoundary(needle[needle.length - 1]); + } + + exports.Search = Search; + }); + + ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(acequire, exports, module) { + "use strict"; + + var keyUtil = acequire("../lib/keys"); + var useragent = acequire("../lib/useragent"); + var KEY_MODS = keyUtil.KEY_MODS; + + function HashHandler(config, platform) { + this.platform = platform || (useragent.isMac ? "mac" : "win"); + this.commands = {}; + this.commandKeyBinding = {}; + this.addCommands(config); + this.$singleCommand = true; + } + + function MultiHashHandler(config, platform) { + HashHandler.call(this, config, platform); + this.$singleCommand = false; + } + + MultiHashHandler.prototype = HashHandler.prototype; + + (function() { + + + this.addCommand = function(command) { + if (this.commands[command.name]) + this.removeCommand(command); + + this.commands[command.name] = command; + + if (command.bindKey) + this._buildKeyHash(command); + }; + + this.removeCommand = function(command, keepCommand) { + var name = command && (typeof command === 'string' ? command : command.name); + command = this.commands[name]; + if (!keepCommand) + delete this.commands[name]; + var ckb = this.commandKeyBinding; + for (var keyId in ckb) { + var cmdGroup = ckb[keyId]; + if (cmdGroup == command) { + delete ckb[keyId]; + } else if (Array.isArray(cmdGroup)) { + var i = cmdGroup.indexOf(command); + if (i != -1) { + cmdGroup.splice(i, 1); + if (cmdGroup.length == 1) + ckb[keyId] = cmdGroup[0]; + } + } + } + }; + + this.bindKey = function(key, command, position) { + if (typeof key == "object" && key) { + if (position == undefined) + position = key.position; + key = key[this.platform]; + } + if (!key) + return; + if (typeof command == "function") + return this.addCommand({exec: command, bindKey: key, name: command.name || key}); + + key.split("|").forEach(function(keyPart) { + var chain = ""; + if (keyPart.indexOf(" ") != -1) { + var parts = keyPart.split(/\s+/); + keyPart = parts.pop(); + parts.forEach(function(keyPart) { + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + chain += (chain ? " " : "") + id; + this._addCommandToBinding(chain, "chainKeys"); + }, this); + chain += " "; + } + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + this._addCommandToBinding(chain + id, command, position); + }, this); + }; + + function getPosition(command) { + return typeof command == "object" && command.bindKey + && command.bindKey.position + || (command.isDefault ? -100 : 0); + } + this._addCommandToBinding = function(keyId, command, position) { + var ckb = this.commandKeyBinding, i; + if (!command) { + delete ckb[keyId]; + } else if (!ckb[keyId] || this.$singleCommand) { + ckb[keyId] = command; + } else { + if (!Array.isArray(ckb[keyId])) { + ckb[keyId] = [ckb[keyId]]; + } else if ((i = ckb[keyId].indexOf(command)) != -1) { + ckb[keyId].splice(i, 1); + } + + if (typeof position != "number") { + position = getPosition(command); + } + + var commands = ckb[keyId]; + for (i = 0; i < commands.length; i++) { + var other = commands[i]; + var otherPos = getPosition(other); + if (otherPos > position) + break; + } + commands.splice(i, 0, command); + } + }; + + this.addCommands = function(commands) { + commands && Object.keys(commands).forEach(function(name) { + var command = commands[name]; + if (!command) + return; + + if (typeof command === "string") + return this.bindKey(command, name); + + if (typeof command === "function") + command = { exec: command }; + + if (typeof command !== "object") + return; + + if (!command.name) + command.name = name; + + this.addCommand(command); + }, this); + }; + + this.removeCommands = function(commands) { + Object.keys(commands).forEach(function(name) { + this.removeCommand(commands[name]); + }, this); + }; + + this.bindKeys = function(keyList) { + Object.keys(keyList).forEach(function(key) { + this.bindKey(key, keyList[key]); + }, this); + }; + + this._buildKeyHash = function(command) { + this.bindKey(command.bindKey, command); + }; + this.parseKeys = function(keys) { + var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x;}); + var key = parts.pop(); + + var keyCode = keyUtil[key]; + if (keyUtil.FUNCTION_KEYS[keyCode]) + key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase(); + else if (!parts.length) + return {key: key, hashId: -1}; + else if (parts.length == 1 && parts[0] == "shift") + return {key: key.toUpperCase(), hashId: -1}; + + var hashId = 0; + for (var i = parts.length; i--;) { + var modifier = keyUtil.KEY_MODS[parts[i]]; + if (modifier == null) { + if (typeof console != "undefined") + console.error("invalid modifier " + parts[i] + " in " + keys); + return false; + } + hashId |= modifier; + } + return {key: key, hashId: hashId}; + }; + + this.findKeyCommand = function findKeyCommand(hashId, keyString) { + var key = KEY_MODS[hashId] + keyString; + return this.commandKeyBinding[key]; + }; + + this.handleKeyboard = function(data, hashId, keyString, keyCode) { + if (keyCode < 0) return; + var key = KEY_MODS[hashId] + keyString; + var command = this.commandKeyBinding[key]; + if (data.$keyChain) { + data.$keyChain += " " + key; + command = this.commandKeyBinding[data.$keyChain] || command; + } + + if (command) { + if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { + data.$keyChain = data.$keyChain || key; + return {command: "null"}; + } + } + + if (data.$keyChain) { + if ((!hashId || hashId == 4) && keyString.length == 1) + data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input + else if (hashId == -1 || keyCode > 0) + data.$keyChain = ""; // reset keyChain + } + return {command: command}; + }; + + this.getStatusText = function(editor, data) { + return data.$keyChain || ""; + }; + + }).call(HashHandler.prototype); + + exports.HashHandler = HashHandler; + exports.MultiHashHandler = MultiHashHandler; + }); + + ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var MultiHashHandler = acequire("../keyboard/hash_handler").MultiHashHandler; + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var CommandManager = function(platform, commands) { + MultiHashHandler.call(this, commands, platform); + this.byName = this.commands; + this.setDefaultHandler("exec", function(e) { + return e.command.exec(e.editor, e.args || {}); + }); + }; + + oop.inherits(CommandManager, MultiHashHandler); + + (function() { + + oop.implement(this, EventEmitter); + + this.exec = function(command, editor, args) { + if (Array.isArray(command)) { + for (var i = command.length; i--; ) { + if (this.exec(command[i], editor, args)) return true; + } + return false; + } + + if (typeof command === "string") + command = this.commands[command]; + + if (!command) + return false; + + if (editor && editor.$readOnly && !command.readOnly) + return false; + + if (command.isAvailable && !command.isAvailable(editor)) + return false; + + var e = {editor: editor, command: command, args: args}; + e.returnValue = this._emit("exec", e); + this._signal("afterExec", e); + + return e.returnValue === false ? false : true; + }; + + this.toggleRecording = function(editor) { + if (this.$inReplay) + return; + + editor && editor._emit("changeStatus"); + if (this.recording) { + this.macro.pop(); + this.removeEventListener("exec", this.$addCommandToMacro); + + if (!this.macro.length) + this.macro = this.oldMacro; + + return this.recording = false; + } + if (!this.$addCommandToMacro) { + this.$addCommandToMacro = function(e) { + this.macro.push([e.command, e.args]); + }.bind(this); + } + + this.oldMacro = this.macro; + this.macro = []; + this.on("exec", this.$addCommandToMacro); + return this.recording = true; + }; + + this.replay = function(editor) { + if (this.$inReplay || !this.macro) + return; + + if (this.recording) + return this.toggleRecording(editor); + + try { + this.$inReplay = true; + this.macro.forEach(function(x) { + if (typeof x == "string") + this.exec(x, editor); + else + this.exec(x[0], editor, x[1]); + }, this); + } finally { + this.$inReplay = false; + } + }; + + this.trimMacro = function(m) { + return m.map(function(x){ + if (typeof x[0] != "string") + x[0] = x[0].name; + if (!x[1]) + x = x[0]; + return x; + }); + }; + + }).call(CommandManager.prototype); + + exports.CommandManager = CommandManager; + + }); + + ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(acequire, exports, module) { + "use strict"; + + var lang = acequire("../lib/lang"); + var config = acequire("../config"); + var Range = acequire("../range").Range; + + function bindKey(win, mac) { + return {win: win, mac: mac}; + } + exports.commands = [{ + name: "showSettingsMenu", + bindKey: bindKey("Ctrl-,", "Command-,"), + exec: function(editor) { + config.loadModule("ace/ext/settings_menu", function(module) { + module.init(editor); + editor.showSettingsMenu(); + }); + }, + readOnly: true + }, { + name: "goToNextError", + bindKey: bindKey("Alt-E", "F4"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, 1); + }); + }, + scrollIntoView: "animate", + readOnly: true + }, { + name: "goToPreviousError", + bindKey: bindKey("Alt-Shift-E", "Shift-F4"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, -1); + }); + }, + scrollIntoView: "animate", + readOnly: true + }, { + name: "selectall", + bindKey: bindKey("Ctrl-A", "Command-A"), + exec: function(editor) { editor.selectAll(); }, + readOnly: true + }, { + name: "centerselection", + bindKey: bindKey(null, "Ctrl-L"), + exec: function(editor) { editor.centerSelection(); }, + readOnly: true + }, { + name: "gotoline", + bindKey: bindKey("Ctrl-L", "Command-L"), + exec: function(editor) { + var line = parseInt(prompt("Enter line number:"), 10); + if (!isNaN(line)) { + editor.gotoLine(line); + } + }, + readOnly: true + }, { + name: "fold", + bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), + exec: function(editor) { editor.session.toggleFold(false); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "unfold", + bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), + exec: function(editor) { editor.session.toggleFold(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "toggleFoldWidget", + bindKey: bindKey("F2", "F2"), + exec: function(editor) { editor.session.toggleFoldWidget(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "toggleParentFoldWidget", + bindKey: bindKey("Alt-F2", "Alt-F2"), + exec: function(editor) { editor.session.toggleFoldWidget(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "foldall", + bindKey: bindKey(null, "Ctrl-Command-Option-0"), + exec: function(editor) { editor.session.foldAll(); }, + scrollIntoView: "center", + readOnly: true + }, { + name: "foldOther", + bindKey: bindKey("Alt-0", "Command-Option-0"), + exec: function(editor) { + editor.session.foldAll(); + editor.session.unfold(editor.selection.getAllRanges()); + }, + scrollIntoView: "center", + readOnly: true + }, { + name: "unfoldall", + bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), + exec: function(editor) { editor.session.unfold(); }, + scrollIntoView: "center", + readOnly: true + }, { + name: "findnext", + bindKey: bindKey("Ctrl-K", "Command-G"), + exec: function(editor) { editor.findNext(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "findprevious", + bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), + exec: function(editor) { editor.findPrevious(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true + }, { + name: "selectOrFindNext", + bindKey: bindKey("Alt-K", "Ctrl-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findNext(); + }, + readOnly: true + }, { + name: "selectOrFindPrevious", + bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findPrevious(); + }, + readOnly: true + }, { + name: "find", + bindKey: bindKey("Ctrl-F", "Command-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor);}); + }, + readOnly: true + }, { + name: "overwrite", + bindKey: "Insert", + exec: function(editor) { editor.toggleOverwrite(); }, + readOnly: true + }, { + name: "selecttostart", + bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Home|Command-Shift-Up"), + exec: function(editor) { editor.getSelection().selectFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "gotostart", + bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), + exec: function(editor) { editor.navigateFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "selectup", + bindKey: bindKey("Shift-Up", "Shift-Up|Ctrl-Shift-P"), + exec: function(editor) { editor.getSelection().selectUp(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "golineup", + bindKey: bindKey("Up", "Up|Ctrl-P"), + exec: function(editor, args) { editor.navigateUp(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttoend", + bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-End|Command-Shift-Down"), + exec: function(editor) { editor.getSelection().selectFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "gotoend", + bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), + exec: function(editor) { editor.navigateFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" + }, { + name: "selectdown", + bindKey: bindKey("Shift-Down", "Shift-Down|Ctrl-Shift-N"), + exec: function(editor) { editor.getSelection().selectDown(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "golinedown", + bindKey: bindKey("Down", "Down|Ctrl-N"), + exec: function(editor, args) { editor.navigateDown(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectwordleft", + bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), + exec: function(editor) { editor.getSelection().selectWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotowordleft", + bindKey: bindKey("Ctrl-Left", "Option-Left"), + exec: function(editor) { editor.navigateWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttolinestart", + bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left|Ctrl-Shift-A"), + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotolinestart", + bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), + exec: function(editor) { editor.navigateLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectleft", + bindKey: bindKey("Shift-Left", "Shift-Left|Ctrl-Shift-B"), + exec: function(editor) { editor.getSelection().selectLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotoleft", + bindKey: bindKey("Left", "Left|Ctrl-B"), + exec: function(editor, args) { editor.navigateLeft(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectwordright", + bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), + exec: function(editor) { editor.getSelection().selectWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotowordright", + bindKey: bindKey("Ctrl-Right", "Option-Right"), + exec: function(editor) { editor.navigateWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selecttolineend", + bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right|Shift-End|Ctrl-Shift-E"), + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotolineend", + bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), + exec: function(editor) { editor.navigateLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectright", + bindKey: bindKey("Shift-Right", "Shift-Right"), + exec: function(editor) { editor.getSelection().selectRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "gotoright", + bindKey: bindKey("Right", "Right|Ctrl-F"), + exec: function(editor, args) { editor.navigateRight(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectpagedown", + bindKey: "Shift-PageDown", + exec: function(editor) { editor.selectPageDown(); }, + readOnly: true + }, { + name: "pagedown", + bindKey: bindKey(null, "Option-PageDown"), + exec: function(editor) { editor.scrollPageDown(); }, + readOnly: true + }, { + name: "gotopagedown", + bindKey: bindKey("PageDown", "PageDown|Ctrl-V"), + exec: function(editor) { editor.gotoPageDown(); }, + readOnly: true + }, { + name: "selectpageup", + bindKey: "Shift-PageUp", + exec: function(editor) { editor.selectPageUp(); }, + readOnly: true + }, { + name: "pageup", + bindKey: bindKey(null, "Option-PageUp"), + exec: function(editor) { editor.scrollPageUp(); }, + readOnly: true + }, { + name: "gotopageup", + bindKey: "PageUp", + exec: function(editor) { editor.gotoPageUp(); }, + readOnly: true + }, { + name: "scrollup", + bindKey: bindKey("Ctrl-Up", null), + exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true + }, { + name: "scrolldown", + bindKey: bindKey("Ctrl-Down", null), + exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true + }, { + name: "selectlinestart", + bindKey: "Shift-Home", + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectlineend", + bindKey: "Shift-End", + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "togglerecording", + bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"), + exec: function(editor) { editor.commands.toggleRecording(editor); }, + readOnly: true + }, { + name: "replaymacro", + bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"), + exec: function(editor) { editor.commands.replay(editor); }, + readOnly: true + }, { + name: "jumptomatching", + bindKey: bindKey("Ctrl-P", "Ctrl-P"), + exec: function(editor) { editor.jumpToMatching(); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "selecttomatching", + bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), + exec: function(editor) { editor.jumpToMatching(true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "expandToMatching", + bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), + exec: function(editor) { editor.jumpToMatching(true, true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true + }, { + name: "passKeysToBrowser", + bindKey: bindKey(null, null), + exec: function() {}, + passEvent: true, + readOnly: true + }, { + name: "copy", + exec: function(editor) { + }, + readOnly: true + }, + { + name: "cut", + exec: function(editor) { + var range = editor.getSelectionRange(); + editor._emit("cut", range); + + if (!editor.selection.isEmpty()) { + editor.session.remove(range); + editor.clearSelection(); + } + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "paste", + exec: function(editor, args) { + editor.$handlePaste(args); + }, + scrollIntoView: "cursor" + }, { + name: "removeline", + bindKey: bindKey("Ctrl-D", "Command-D"), + exec: function(editor) { editor.removeLines(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEachLine" + }, { + name: "duplicateSelection", + bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), + exec: function(editor) { editor.duplicateSelection(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "sortlines", + bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"), + exec: function(editor) { editor.sortLines(); }, + scrollIntoView: "selection", + multiSelectAction: "forEachLine" + }, { + name: "togglecomment", + bindKey: bindKey("Ctrl-/", "Command-/"), + exec: function(editor) { editor.toggleCommentLines(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "toggleBlockComment", + bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"), + exec: function(editor) { editor.toggleBlockComment(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "modifyNumberUp", + bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), + exec: function(editor) { editor.modifyNumber(1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "modifyNumberDown", + bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), + exec: function(editor) { editor.modifyNumber(-1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" + }, { + name: "replace", + bindKey: bindKey("Ctrl-H", "Command-Option-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true);}); + } + }, { + name: "undo", + bindKey: bindKey("Ctrl-Z", "Command-Z"), + exec: function(editor) { editor.undo(); } + }, { + name: "redo", + bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), + exec: function(editor) { editor.redo(); } + }, { + name: "copylinesup", + bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), + exec: function(editor) { editor.copyLinesUp(); }, + scrollIntoView: "cursor" + }, { + name: "movelinesup", + bindKey: bindKey("Alt-Up", "Option-Up"), + exec: function(editor) { editor.moveLinesUp(); }, + scrollIntoView: "cursor" + }, { + name: "copylinesdown", + bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), + exec: function(editor) { editor.copyLinesDown(); }, + scrollIntoView: "cursor" + }, { + name: "movelinesdown", + bindKey: bindKey("Alt-Down", "Option-Down"), + exec: function(editor) { editor.moveLinesDown(); }, + scrollIntoView: "cursor" + }, { + name: "del", + bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"), + exec: function(editor) { editor.remove("right"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "backspace", + bindKey: bindKey( + "Shift-Backspace|Backspace", + "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H" + ), + exec: function(editor) { editor.remove("left"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "cut_or_delete", + bindKey: bindKey("Shift-Delete", null), + exec: function(editor) { + if (editor.selection.isEmpty()) { + editor.remove("left"); + } else { + return false; + } + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolinestart", + bindKey: bindKey("Alt-Backspace", "Command-Backspace"), + exec: function(editor) { editor.removeToLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolineend", + bindKey: bindKey("Alt-Delete", "Ctrl-K|Command-Delete"), + exec: function(editor) { editor.removeToLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolinestarthard", + bindKey: bindKey("Ctrl-Shift-Backspace", null), + exec: function(editor) { + var range = editor.selection.getRange(); + range.start.column = 0; + editor.session.remove(range); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removetolineendhard", + bindKey: bindKey("Ctrl-Shift-Delete", null), + exec: function(editor) { + var range = editor.selection.getRange(); + range.end.column = Number.MAX_VALUE; + editor.session.remove(range); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removewordleft", + bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), + exec: function(editor) { editor.removeWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "removewordright", + bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), + exec: function(editor) { editor.removeWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "outdent", + bindKey: bindKey("Shift-Tab", "Shift-Tab"), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "indent", + bindKey: bindKey("Tab", "Tab"), + exec: function(editor) { editor.indent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" + }, { + name: "blockoutdent", + bindKey: bindKey("Ctrl-[", "Ctrl-["), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "blockindent", + bindKey: bindKey("Ctrl-]", "Ctrl-]"), + exec: function(editor) { editor.blockIndent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" + }, { + name: "insertstring", + exec: function(editor, str) { editor.insert(str); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "inserttext", + exec: function(editor, args) { + editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "splitline", + bindKey: bindKey(null, "Ctrl-O"), + exec: function(editor) { editor.splitLine(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "transposeletters", + bindKey: bindKey("Alt-Shift-X", "Ctrl-T"), + exec: function(editor) { editor.transposeLetters(); }, + multiSelectAction: function(editor) {editor.transposeSelections(1); }, + scrollIntoView: "cursor" + }, { + name: "touppercase", + bindKey: bindKey("Ctrl-U", "Ctrl-U"), + exec: function(editor) { editor.toUpperCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "tolowercase", + bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), + exec: function(editor) { editor.toLowerCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" + }, { + name: "expandtoline", + bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"), + exec: function(editor) { + var range = editor.selection.getRange(); + + range.start.column = range.end.column = 0; + range.end.row++; + editor.selection.setRange(range, false); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true + }, { + name: "joinlines", + bindKey: bindKey(null, null), + exec: function(editor) { + var isBackwards = editor.selection.isBackwards(); + var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); + var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); + var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; + var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); + var selectedCount = selectedText.replace(/\n\s*/, " ").length; + var insertLine = editor.session.doc.getLine(selectionStart.row); + + for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) { + var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i))); + if (curLine.length !== 0) { + curLine = " " + curLine; + } + insertLine += curLine; + } + + if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { + insertLine += editor.session.doc.getNewLineCharacter(); + } + + editor.clearSelection(); + editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine); + + if (selectedCount > 0) { + editor.selection.moveCursorTo(selectionStart.row, selectionStart.column); + editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount); + } else { + firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol; + editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol); + } + }, + multiSelectAction: "forEach", + readOnly: true + }, { + name: "invertSelection", + bindKey: bindKey(null, null), + exec: function(editor) { + var endRow = editor.session.doc.getLength() - 1; + var endCol = editor.session.doc.getLine(endRow).length; + var ranges = editor.selection.rangeList.ranges; + var newRanges = []; + if (ranges.length < 1) { + ranges = [editor.selection.getRange()]; + } + + for (var i = 0; i < ranges.length; i++) { + if (i == (ranges.length - 1)) { + if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) { + newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol)); + } + } + + if (i === 0) { + if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) { + newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column)); + } + } else { + newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column)); + } + } + + editor.exitMultiSelectMode(); + editor.clearSelection(); + + for(var i = 0; i < newRanges.length; i++) { + editor.selection.addRange(newRanges[i], false); + } + }, + readOnly: true, + scrollIntoView: "none" + }]; + + }); + + ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config","ace/token_iterator"], function(acequire, exports, module) { + "use strict"; + + acequire("./lib/fixoldbrowsers"); + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var lang = acequire("./lib/lang"); + var useragent = acequire("./lib/useragent"); + var TextInput = acequire("./keyboard/textinput").TextInput; + var MouseHandler = acequire("./mouse/mouse_handler").MouseHandler; + var FoldHandler = acequire("./mouse/fold_handler").FoldHandler; + var KeyBinding = acequire("./keyboard/keybinding").KeyBinding; + var EditSession = acequire("./edit_session").EditSession; + var Search = acequire("./search").Search; + var Range = acequire("./range").Range; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var CommandManager = acequire("./commands/command_manager").CommandManager; + var defaultCommands = acequire("./commands/default_commands").commands; + var config = acequire("./config"); + var TokenIterator = acequire("./token_iterator").TokenIterator; + var Editor = function(renderer, session) { + var container = renderer.getContainerElement(); + this.container = container; + this.renderer = renderer; + this.id = "editor" + (++Editor.$uid); + + this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); + if (typeof document == "object") { + this.textInput = new TextInput(renderer.getTextAreaContainer(), this); + this.renderer.textarea = this.textInput.getElement(); + this.$mouseHandler = new MouseHandler(this); + new FoldHandler(this); + } + + this.keyBinding = new KeyBinding(this); + + this.$blockScrolling = 0; + this.$search = new Search().set({ + wrap: true + }); + + this.$historyTracker = this.$historyTracker.bind(this); + this.commands.on("exec", this.$historyTracker); + + this.$initOperationListeners(); + + this._$emitInputEvent = lang.delayedCall(function() { + this._signal("input", {}); + if (this.session && this.session.bgTokenizer) + this.session.bgTokenizer.scheduleStart(); + }.bind(this)); + + this.on("change", function(_, _self) { + _self._$emitInputEvent.schedule(31); + }); + + this.setSession(session || new EditSession("")); + config.resetOptions(this); + config._signal("editor", this); + }; + + Editor.$uid = 0; + + (function(){ + + oop.implement(this, EventEmitter); + + this.$initOperationListeners = function() { + function last(a) {return a[a.length - 1];} + + this.selections = []; + this.commands.on("exec", this.startOperation.bind(this), true); + this.commands.on("afterExec", this.endOperation.bind(this), true); + + this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); + + this.on("change", function() { + this.curOp || this.startOperation(); + this.curOp.docChanged = true; + }.bind(this), true); + + this.on("changeSelection", function() { + this.curOp || this.startOperation(); + this.curOp.selectionChanged = true; + }.bind(this), true); + }; + + this.curOp = null; + this.prevOp = {}; + this.startOperation = function(commadEvent) { + if (this.curOp) { + if (!commadEvent || this.curOp.command) + return; + this.prevOp = this.curOp; + } + if (!commadEvent) { + this.previousCommand = null; + commadEvent = {}; + } + + this.$opResetTimer.schedule(); + this.curOp = { + command: commadEvent.command || {}, + args: commadEvent.args, + scrollTop: this.renderer.scrollTop + }; + if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined) + this.$blockScrolling++; + }; + + this.endOperation = function(e) { + if (this.curOp) { + if (e && e.returnValue === false) + return this.curOp = null; + this._signal("beforeEndOperation"); + var command = this.curOp.command; + if (command.name && this.$blockScrolling > 0) + this.$blockScrolling--; + var scrollIntoView = command && command.scrollIntoView; + if (scrollIntoView) { + switch (scrollIntoView) { + case "center-animate": + scrollIntoView = "animate"; + case "center": + this.renderer.scrollCursorIntoView(null, 0.5); + break; + case "animate": + case "cursor": + this.renderer.scrollCursorIntoView(); + break; + case "selectionPart": + var range = this.selection.getRange(); + var config = this.renderer.layerConfig; + if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) { + this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead); + } + break; + default: + break; + } + if (scrollIntoView == "animate") + this.renderer.animateScrolling(this.curOp.scrollTop); + } + + this.prevOp = this.curOp; + this.curOp = null; + } + }; + this.$mergeableCommands = ["backspace", "del", "insertstring"]; + this.$historyTracker = function(e) { + if (!this.$mergeUndoDeltas) + return; + + var prev = this.prevOp; + var mergeableCommands = this.$mergeableCommands; + var shouldMerge = prev.command && (e.command.name == prev.command.name); + if (e.command.name == "insertstring") { + var text = e.args; + if (this.mergeNextCommand === undefined) + this.mergeNextCommand = true; + + shouldMerge = shouldMerge + && this.mergeNextCommand // previous command allows to coalesce with + && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type + + this.mergeNextCommand = true; + } else { + shouldMerge = shouldMerge + && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable + } + + if ( + this.$mergeUndoDeltas != "always" + && Date.now() - this.sequenceStartTime > 2000 + ) { + shouldMerge = false; // the sequence is too long + } + + if (shouldMerge) + this.session.mergeUndoDeltas = true; + else if (mergeableCommands.indexOf(e.command.name) !== -1) + this.sequenceStartTime = Date.now(); + }; + this.setKeyboardHandler = function(keyboardHandler, cb) { + if (keyboardHandler && typeof keyboardHandler === "string") { + this.$keybindingId = keyboardHandler; + var _self = this; + config.loadModule(["keybinding", keyboardHandler], function(module) { + if (_self.$keybindingId == keyboardHandler) + _self.keyBinding.setKeyboardHandler(module && module.handler); + cb && cb(); + }); + } else { + this.$keybindingId = null; + this.keyBinding.setKeyboardHandler(keyboardHandler); + cb && cb(); + } + }; + this.getKeyboardHandler = function() { + return this.keyBinding.getKeyboardHandler(); + }; + this.setSession = function(session) { + if (this.session == session) + return; + if (this.curOp) this.endOperation(); + this.curOp = {}; + + var oldSession = this.session; + if (oldSession) { + this.session.off("change", this.$onDocumentChange); + this.session.off("changeMode", this.$onChangeMode); + this.session.off("tokenizerUpdate", this.$onTokenizerUpdate); + this.session.off("changeTabSize", this.$onChangeTabSize); + this.session.off("changeWrapLimit", this.$onChangeWrapLimit); + this.session.off("changeWrapMode", this.$onChangeWrapMode); + this.session.off("changeFold", this.$onChangeFold); + this.session.off("changeFrontMarker", this.$onChangeFrontMarker); + this.session.off("changeBackMarker", this.$onChangeBackMarker); + this.session.off("changeBreakpoint", this.$onChangeBreakpoint); + this.session.off("changeAnnotation", this.$onChangeAnnotation); + this.session.off("changeOverwrite", this.$onCursorChange); + this.session.off("changeScrollTop", this.$onScrollTopChange); + this.session.off("changeScrollLeft", this.$onScrollLeftChange); + + var selection = this.session.getSelection(); + selection.off("changeCursor", this.$onCursorChange); + selection.off("changeSelection", this.$onSelectionChange); + } + + this.session = session; + if (session) { + this.$onDocumentChange = this.onDocumentChange.bind(this); + session.on("change", this.$onDocumentChange); + this.renderer.setSession(session); + + this.$onChangeMode = this.onChangeMode.bind(this); + session.on("changeMode", this.$onChangeMode); + + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.on("tokenizerUpdate", this.$onTokenizerUpdate); + + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); + session.on("changeTabSize", this.$onChangeTabSize); + + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); + session.on("changeWrapLimit", this.$onChangeWrapLimit); + + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); + session.on("changeWrapMode", this.$onChangeWrapMode); + + this.$onChangeFold = this.onChangeFold.bind(this); + session.on("changeFold", this.$onChangeFold); + + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); + this.session.on("changeFrontMarker", this.$onChangeFrontMarker); + + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); + this.session.on("changeBackMarker", this.$onChangeBackMarker); + + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); + this.session.on("changeBreakpoint", this.$onChangeBreakpoint); + + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); + this.session.on("changeAnnotation", this.$onChangeAnnotation); + + this.$onCursorChange = this.onCursorChange.bind(this); + this.session.on("changeOverwrite", this.$onCursorChange); + + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.on("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.on("changeScrollLeft", this.$onScrollLeftChange); + + this.selection = session.getSelection(); + this.selection.on("changeCursor", this.$onCursorChange); + + this.$onSelectionChange = this.onSelectionChange.bind(this); + this.selection.on("changeSelection", this.$onSelectionChange); + + this.onChangeMode(); + + this.$blockScrolling += 1; + this.onCursorChange(); + this.$blockScrolling -= 1; + + this.onScrollTopChange(); + this.onScrollLeftChange(); + this.onSelectionChange(); + this.onChangeFrontMarker(); + this.onChangeBackMarker(); + this.onChangeBreakpoint(); + this.onChangeAnnotation(); + this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); + this.renderer.updateFull(); + } else { + this.selection = null; + this.renderer.setSession(session); + } + + this._signal("changeSession", { + session: session, + oldSession: oldSession + }); + + this.curOp = null; + + oldSession && oldSession._signal("changeEditor", {oldEditor: this}); + session && session._signal("changeEditor", {editor: this}); + + if (session && session.bgTokenizer) + session.bgTokenizer.scheduleStart(); + }; + this.getSession = function() { + return this.session; + }; + this.setValue = function(val, cursorPos) { + this.session.doc.setValue(val); + + if (!cursorPos) + this.selectAll(); + else if (cursorPos == 1) + this.navigateFileEnd(); + else if (cursorPos == -1) + this.navigateFileStart(); + + return val; + }; + this.getValue = function() { + return this.session.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.resize = function(force) { + this.renderer.onResize(force); + }; + this.setTheme = function(theme, cb) { + this.renderer.setTheme(theme, cb); + }; + this.getTheme = function() { + return this.renderer.getTheme(); + }; + this.setStyle = function(style) { + this.renderer.setStyle(style); + }; + this.unsetStyle = function(style) { + this.renderer.unsetStyle(style); + }; + this.getFontSize = function () { + return this.getOption("fontSize") || + dom.computedStyle(this.container, "fontSize"); + }; + this.setFontSize = function(size) { + this.setOption("fontSize", size); + }; + + this.$highlightBrackets = function() { + if (this.session.$bracketHighlight) { + this.session.removeMarker(this.session.$bracketHighlight); + this.session.$bracketHighlight = null; + } + + if (this.$highlightPending) { + return; + } + var self = this; + this.$highlightPending = true; + setTimeout(function() { + self.$highlightPending = false; + var session = self.session; + if (!session || !session.bgTokenizer) return; + var pos = session.findMatchingBracket(self.getCursorPosition()); + if (pos) { + var range = new Range(pos.row, pos.column, pos.row, pos.column + 1); + } else if (session.$mode.getMatching) { + var range = session.$mode.getMatching(self.session); + } + if (range) + session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text"); + }, 50); + }; + this.$highlightTags = function() { + if (this.$highlightTagPending) + return; + var self = this; + this.$highlightTagPending = true; + setTimeout(function() { + self.$highlightTagPending = false; + + var session = self.session; + if (!session || !session.bgTokenizer) return; + + var pos = self.getCursorPosition(); + var iterator = new TokenIterator(self.session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + + if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { + session.removeMarker(session.$tagHighlight); + session.$tagHighlight = null; + return; + } + + if (token.type.indexOf("tag-open") != -1) { + token = iterator.stepForward(); + if (!token) + return; + } + + var tag = token.value; + var depth = 0; + var prevToken = iterator.stepBackward(); + + if (prevToken.value == '<'){ + do { + prevToken = token; + token = iterator.stepForward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<'){ + depth++; + } else if (prevToken.value === '= 0); + } else { + do { + token = prevToken; + prevToken = iterator.stepBackward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<') { + depth++; + } else if (prevToken.value === ' 1)) + highlight = false; + } + + if (session.$highlightLineMarker && !highlight) { + session.removeMarker(session.$highlightLineMarker.id); + session.$highlightLineMarker = null; + } else if (!session.$highlightLineMarker && highlight) { + var range = new Range(highlight.row, highlight.column, highlight.row, Infinity); + range.id = session.addMarker(range, "ace_active-line", "screenLine"); + session.$highlightLineMarker = range; + } else if (highlight) { + session.$highlightLineMarker.start.row = highlight.row; + session.$highlightLineMarker.end.row = highlight.row; + session.$highlightLineMarker.start.column = highlight.column; + session._signal("changeBackMarker"); + } + }; + + this.onSelectionChange = function(e) { + var session = this.session; + + if (session.$selectionMarker) { + session.removeMarker(session.$selectionMarker); + } + session.$selectionMarker = null; + + if (!this.selection.isEmpty()) { + var range = this.selection.getRange(); + var style = this.getSelectionStyle(); + session.$selectionMarker = session.addMarker(range, "ace_selection", style); + } else { + this.$updateHighlightActiveLine(); + } + + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); + this.session.highlight(re); + + this._signal("changeSelection"); + }; + + this.$getSelectionHighLightRegexp = function() { + var session = this.session; + + var selection = this.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) + return; + + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = session.getLine(selection.start.row); + var lineCols = line.length; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + if ((startOuter >= 0 && /^[\w\d]/.test(needle)) || + (endOuter <= lineCols && /[\w\d]$/.test(needle))) + return; + + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var re = this.$search.$assembleRegExp({ + wholeWord: true, + caseSensitive: true, + needle: needle + }); + + return re; + }; + + + this.onChangeFrontMarker = function() { + this.renderer.updateFrontMarkers(); + }; + + this.onChangeBackMarker = function() { + this.renderer.updateBackMarkers(); + }; + + + this.onChangeBreakpoint = function() { + this.renderer.updateBreakpoints(); + }; + + this.onChangeAnnotation = function() { + this.renderer.setAnnotations(this.session.getAnnotations()); + }; + + + this.onChangeMode = function(e) { + this.renderer.updateText(); + this._emit("changeMode", e); + }; + + + this.onChangeWrapLimit = function() { + this.renderer.updateFull(); + }; + + this.onChangeWrapMode = function() { + this.renderer.onResize(true); + }; + + + this.onChangeFold = function() { + this.$updateHighlightActiveLine(); + this.renderer.updateFull(); + }; + this.getSelectedText = function() { + return this.session.getTextRange(this.getSelectionRange()); + }; + this.getCopyText = function() { + var text = this.getSelectedText(); + this._signal("copy", text); + return text; + }; + this.onCopy = function() { + this.commands.exec("copy", this); + }; + this.onCut = function() { + this.commands.exec("cut", this); + }; + this.onPaste = function(text, event) { + var e = {text: text, event: event}; + this.commands.exec("paste", this, e); + }; + + this.$handlePaste = function(e) { + if (typeof e == "string") + e = {text: e}; + this._signal("paste", e); + var text = e.text; + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { + this.insert(text); + } else { + var lines = text.split(/\r\n|\r|\n/); + var ranges = this.selection.rangeList.ranges; + + if (lines.length > ranges.length || lines.length < 2 || !lines[1]) + return this.commands.exec("insertstring", this, text); + + for (var i = ranges.length; i--;) { + var range = ranges[i]; + if (!range.isEmpty()) + this.session.remove(range); + + this.session.insert(range.start, lines[i]); + } + } + }; + + this.execCommand = function(command, args) { + return this.commands.exec(command, this, args); + }; + this.insert = function(text, pasted) { + var session = this.session; + var mode = session.getMode(); + var cursor = this.getCursorPosition(); + + if (this.getBehavioursEnabled() && !pasted) { + var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); + if (transform) { + if (text !== transform.text) { + this.session.mergeUndoDeltas = false; + this.$mergeNextCommand = false; + } + text = transform.text; + + } + } + + if (text == "\t") + text = this.session.getTabString(); + if (!this.selection.isEmpty()) { + var range = this.getSelectionRange(); + cursor = this.session.remove(range); + this.clearSelection(); + } + else if (this.session.getOverwrite() && text.indexOf("\n") == -1) { + var range = new Range.fromPoints(cursor, cursor); + range.end.column += text.length; + this.session.remove(range); + } + + if (text == "\n" || text == "\r\n") { + var line = session.getLine(cursor.row); + if (cursor.column > line.search(/\S|$/)) { + var d = line.substr(cursor.column).search(/\S|$/); + session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); + } + } + this.clearSelection(); + + var start = cursor.column; + var lineState = session.getState(cursor.row); + var line = session.getLine(cursor.row); + var shouldOutdent = mode.checkOutdent(lineState, line, text); + var end = session.insert(cursor, text); + + if (transform && transform.selection) { + if (transform.selection.length == 2) { // Transform relative to the current column + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } else { // Transform relative to the current row. + this.selection.setSelectionRange( + new Range(cursor.row + transform.selection[0], + transform.selection[1], + cursor.row + transform.selection[2], + transform.selection[3])); + } + } + + if (session.getDocument().isNewLine(text)) { + var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); + + session.insert({row: cursor.row+1, column: 0}, lineIndent); + } + if (shouldOutdent) + mode.autoOutdent(lineState, session, cursor.row); + }; + + this.onTextInput = function(text) { + this.keyBinding.onTextInput(text); + }; + + this.onCommandKey = function(e, hashId, keyCode) { + this.keyBinding.onCommandKey(e, hashId, keyCode); + }; + this.setOverwrite = function(overwrite) { + this.session.setOverwrite(overwrite); + }; + this.getOverwrite = function() { + return this.session.getOverwrite(); + }; + this.toggleOverwrite = function() { + this.session.toggleOverwrite(); + }; + this.setScrollSpeed = function(speed) { + this.setOption("scrollSpeed", speed); + }; + this.getScrollSpeed = function() { + return this.getOption("scrollSpeed"); + }; + this.setDragDelay = function(dragDelay) { + this.setOption("dragDelay", dragDelay); + }; + this.getDragDelay = function() { + return this.getOption("dragDelay"); + }; + this.setSelectionStyle = function(val) { + this.setOption("selectionStyle", val); + }; + this.getSelectionStyle = function() { + return this.getOption("selectionStyle"); + }; + this.setHighlightActiveLine = function(shouldHighlight) { + this.setOption("highlightActiveLine", shouldHighlight); + }; + this.getHighlightActiveLine = function() { + return this.getOption("highlightActiveLine"); + }; + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + this.setHighlightSelectedWord = function(shouldHighlight) { + this.setOption("highlightSelectedWord", shouldHighlight); + }; + this.getHighlightSelectedWord = function() { + return this.$highlightSelectedWord; + }; + + this.setAnimatedScroll = function(shouldAnimate){ + this.renderer.setAnimatedScroll(shouldAnimate); + }; + + this.getAnimatedScroll = function(){ + return this.renderer.getAnimatedScroll(); + }; + this.setShowInvisibles = function(showInvisibles) { + this.renderer.setShowInvisibles(showInvisibles); + }; + this.getShowInvisibles = function() { + return this.renderer.getShowInvisibles(); + }; + + this.setDisplayIndentGuides = function(display) { + this.renderer.setDisplayIndentGuides(display); + }; + + this.getDisplayIndentGuides = function() { + return this.renderer.getDisplayIndentGuides(); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.renderer.setShowPrintMargin(showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.renderer.getShowPrintMargin(); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.renderer.setPrintMarginColumn(showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.renderer.getPrintMarginColumn(); + }; + this.setReadOnly = function(readOnly) { + this.setOption("readOnly", readOnly); + }; + this.getReadOnly = function() { + return this.getOption("readOnly"); + }; + this.setBehavioursEnabled = function (enabled) { + this.setOption("behavioursEnabled", enabled); + }; + this.getBehavioursEnabled = function () { + return this.getOption("behavioursEnabled"); + }; + this.setWrapBehavioursEnabled = function (enabled) { + this.setOption("wrapBehavioursEnabled", enabled); + }; + this.getWrapBehavioursEnabled = function () { + return this.getOption("wrapBehavioursEnabled"); + }; + this.setShowFoldWidgets = function(show) { + this.setOption("showFoldWidgets", show); + + }; + this.getShowFoldWidgets = function() { + return this.getOption("showFoldWidgets"); + }; + + this.setFadeFoldWidgets = function(fade) { + this.setOption("fadeFoldWidgets", fade); + }; + + this.getFadeFoldWidgets = function() { + return this.getOption("fadeFoldWidgets"); + }; + this.remove = function(dir) { + if (this.selection.isEmpty()){ + if (dir == "left") + this.selection.selectLeft(); + else + this.selection.selectRight(); + } + + var range = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var session = this.session; + var state = session.getState(range.start.row); + var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); + + if (range.end.column === 0) { + var text = session.getTextRange(range); + if (text[text.length - 1] == "\n") { + var line = session.getLine(range.end.row); + if (/^\s+$/.test(line)) { + range.end.column = line.length; + } + } + } + if (new_range) + range = new_range; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.removeWordRight = function() { + if (this.selection.isEmpty()) + this.selection.selectWordRight(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeWordLeft = function() { + if (this.selection.isEmpty()) + this.selection.selectWordLeft(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineStart = function() { + if (this.selection.isEmpty()) + this.selection.selectLineStart(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineEnd = function() { + if (this.selection.isEmpty()) + this.selection.selectLineEnd(); + + var range = this.getSelectionRange(); + if (range.start.column == range.end.column && range.start.row == range.end.row) { + range.end.column = 0; + range.end.row++; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.splitLine = function() { + if (!this.selection.isEmpty()) { + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + } + + var cursor = this.getCursorPosition(); + this.insert("\n"); + this.moveCursorToPosition(cursor); + }; + this.transposeLetters = function() { + if (!this.selection.isEmpty()) { + return; + } + + var cursor = this.getCursorPosition(); + var column = cursor.column; + if (column === 0) + return; + + var line = this.session.getLine(cursor.row); + var swap, range; + if (column < line.length) { + swap = line.charAt(column) + line.charAt(column-1); + range = new Range(cursor.row, column-1, cursor.row, column+1); + } + else { + swap = line.charAt(column-1) + line.charAt(column-2); + range = new Range(cursor.row, column-2, cursor.row, column); + } + this.session.replace(range, swap); + this.session.selection.moveToPosition(range.end); + }; + this.toLowerCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toLowerCase()); + this.selection.setSelectionRange(originalRange); + }; + this.toUpperCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toUpperCase()); + this.selection.setSelectionRange(originalRange); + }; + this.indent = function() { + var session = this.session; + var range = this.getSelectionRange(); + + if (range.start.row < range.end.row) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } else if (range.start.column < range.end.column) { + var text = session.getTextRange(range); + if (!/^\s+$/.test(text)) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } + } + + var line = session.getLine(range.start.row); + var position = range.start; + var size = session.getTabSize(); + var column = session.documentToScreenColumn(position.row, position.column); + + if (this.session.getUseSoftTabs()) { + var count = (size - column % size); + var indentString = lang.stringRepeat(" ", count); + } else { + var count = column % size; + while (line[range.start.column - 1] == " " && count) { + range.start.column--; + count--; + } + this.selection.setSelectionRange(range); + indentString = "\t"; + } + return this.insert(indentString); + }; + this.blockIndent = function() { + var rows = this.$getSelectedRows(); + this.session.indentRows(rows.first, rows.last, "\t"); + }; + this.blockOutdent = function() { + var selection = this.session.getSelection(); + this.session.outdentRows(selection.getRange()); + }; + this.sortLines = function() { + var rows = this.$getSelectedRows(); + var session = this.session; + + var lines = []; + for (var i = rows.first; i <= rows.last; i++) + lines.push(session.getLine(i)); + + lines.sort(function(a, b) { + if (a.toLowerCase() < b.toLowerCase()) return -1; + if (a.toLowerCase() > b.toLowerCase()) return 1; + return 0; + }); + + var deleteRange = new Range(0, 0, 0, 0); + for (var i = rows.first; i <= rows.last; i++) { + var line = session.getLine(i); + deleteRange.start.row = i; + deleteRange.end.row = i; + deleteRange.end.column = line.length; + session.replace(deleteRange, lines[i-rows.first]); + } + }; + this.toggleCommentLines = function() { + var state = this.session.getState(this.getCursorPosition().row); + var rows = this.$getSelectedRows(); + this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); + }; + + this.toggleBlockComment = function() { + var cursor = this.getCursorPosition(); + var state = this.session.getState(cursor.row); + var range = this.getSelectionRange(); + this.session.getMode().toggleBlockComment(state, this.session, range, cursor); + }; + this.getNumberAt = function(row, column) { + var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g; + _numberRx.lastIndex = 0; + + var s = this.session.getLine(row); + while (_numberRx.lastIndex < column) { + var m = _numberRx.exec(s); + if(m.index <= column && m.index+m[0].length >= column){ + var number = { + value: m[0], + start: m.index, + end: m.index+m[0].length + }; + return number; + } + } + return null; + }; + this.modifyNumber = function(amount) { + var row = this.selection.getCursor().row; + var column = this.selection.getCursor().column; + var charRange = new Range(row, column-1, row, column); + + var c = this.session.getTextRange(charRange); + if (!isNaN(parseFloat(c)) && isFinite(c)) { + var nr = this.getNumberAt(row, column); + if (nr) { + var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end; + var decimals = nr.start + nr.value.length - fp; + + var t = parseFloat(nr.value); + t *= Math.pow(10, decimals); + + + if(fp !== nr.end && column < fp){ + amount *= Math.pow(10, nr.end - column - 1); + } else { + amount *= Math.pow(10, nr.end - column); + } + + t += amount; + t /= Math.pow(10, decimals); + var nnr = t.toFixed(decimals); + var replaceRange = new Range(row, nr.start, row, nr.end); + this.session.replace(replaceRange, nnr); + this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length)); + + } + } + }; + this.removeLines = function() { + var rows = this.$getSelectedRows(); + this.session.removeFullLines(rows.first, rows.last); + this.clearSelection(); + }; + + this.duplicateSelection = function() { + var sel = this.selection; + var doc = this.session; + var range = sel.getRange(); + var reverse = sel.isBackwards(); + if (range.isEmpty()) { + var row = range.start.row; + doc.duplicateLines(row, row); + } else { + var point = reverse ? range.start : range.end; + var endPoint = doc.insert(point, doc.getTextRange(range), false); + range.start = point; + range.end = endPoint; + + sel.setSelectionRange(range, reverse); + } + }; + this.moveLinesDown = function() { + this.$moveLines(1, false); + }; + this.moveLinesUp = function() { + this.$moveLines(-1, false); + }; + this.moveText = function(range, toPosition, copy) { + return this.session.moveText(range, toPosition, copy); + }; + this.copyLinesUp = function() { + this.$moveLines(-1, true); + }; + this.copyLinesDown = function() { + this.$moveLines(1, true); + }; + this.$moveLines = function(dir, copy) { + var rows, moved; + var selection = this.selection; + if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { + var range = selection.toOrientedRange(); + rows = this.$getSelectedRows(range); + moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); + if (copy && dir == -1) moved = 0; + range.moveBy(moved, 0); + selection.fromOrientedRange(range); + } else { + var ranges = selection.rangeList.ranges; + selection.rangeList.detach(this.session); + this.inVirtualSelectionMode = true; + + var diff = 0; + var totalDiff = 0; + var l = ranges.length; + for (var i = 0; i < l; i++) { + var rangeIndex = i; + ranges[i].moveBy(diff, 0); + rows = this.$getSelectedRows(ranges[i]); + var first = rows.first; + var last = rows.last; + while (++i < l) { + if (totalDiff) ranges[i].moveBy(totalDiff, 0); + var subRows = this.$getSelectedRows(ranges[i]); + if (copy && subRows.first != last) + break; + else if (!copy && subRows.first > last + 1) + break; + last = subRows.last; + } + i--; + diff = this.session.$moveLines(first, last, copy ? 0 : dir); + if (copy && dir == -1) rangeIndex = i + 1; + while (rangeIndex <= i) { + ranges[rangeIndex].moveBy(diff, 0); + rangeIndex++; + } + if (!copy) diff = 0; + totalDiff += diff; + } + + selection.fromOrientedRange(selection.ranges[0]); + selection.rangeList.attach(this.session); + this.inVirtualSelectionMode = false; + } + }; + this.$getSelectedRows = function(range) { + range = (range || this.getSelectionRange()).collapseRows(); + + return { + first: this.session.getRowFoldStart(range.start.row), + last: this.session.getRowFoldEnd(range.end.row) + }; + }; + + this.onCompositionStart = function(text) { + this.renderer.showComposition(this.getCursorPosition()); + }; + + this.onCompositionUpdate = function(text) { + this.renderer.setCompositionText(text); + }; + + this.onCompositionEnd = function() { + this.renderer.hideComposition(); + }; + this.getFirstVisibleRow = function() { + return this.renderer.getFirstVisibleRow(); + }; + this.getLastVisibleRow = function() { + return this.renderer.getLastVisibleRow(); + }; + this.isRowVisible = function(row) { + return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); + }; + this.isRowFullyVisible = function(row) { + return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow()); + }; + this.$getVisibleRowCount = function() { + return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1; + }; + + this.$moveByPage = function(dir, select) { + var renderer = this.renderer; + var config = this.renderer.layerConfig; + var rows = dir * Math.floor(config.height / config.lineHeight); + + this.$blockScrolling++; + if (select === true) { + this.selection.$moveSelection(function(){ + this.moveCursorBy(rows, 0); + }); + } else if (select === false) { + this.selection.moveCursorBy(rows, 0); + this.selection.clearSelection(); + } + this.$blockScrolling--; + + var scrollTop = renderer.scrollTop; + + renderer.scrollBy(0, rows * config.lineHeight); + if (select != null) + renderer.scrollCursorIntoView(null, 0.5); + + renderer.animateScrolling(scrollTop); + }; + this.selectPageDown = function() { + this.$moveByPage(1, true); + }; + this.selectPageUp = function() { + this.$moveByPage(-1, true); + }; + this.gotoPageDown = function() { + this.$moveByPage(1, false); + }; + this.gotoPageUp = function() { + this.$moveByPage(-1, false); + }; + this.scrollPageDown = function() { + this.$moveByPage(1); + }; + this.scrollPageUp = function() { + this.$moveByPage(-1); + }; + this.scrollToRow = function(row) { + this.renderer.scrollToRow(row); + }; + this.scrollToLine = function(line, center, animate, callback) { + this.renderer.scrollToLine(line, center, animate, callback); + }; + this.centerSelection = function() { + var range = this.getSelectionRange(); + var pos = { + row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), + column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) + }; + this.renderer.alignCursor(pos, 0.5); + }; + this.getCursorPosition = function() { + return this.selection.getCursor(); + }; + this.getCursorPositionScreen = function() { + return this.session.documentToScreenPosition(this.getCursorPosition()); + }; + this.getSelectionRange = function() { + return this.selection.getRange(); + }; + this.selectAll = function() { + this.$blockScrolling += 1; + this.selection.selectAll(); + this.$blockScrolling -= 1; + }; + this.clearSelection = function() { + this.selection.clearSelection(); + }; + this.moveCursorTo = function(row, column) { + this.selection.moveCursorTo(row, column); + }; + this.moveCursorToPosition = function(pos) { + this.selection.moveCursorToPosition(pos); + }; + this.jumpToMatching = function(select, expand) { + var cursor = this.getCursorPosition(); + var iterator = new TokenIterator(this.session, cursor.row, cursor.column); + var prevToken = iterator.getCurrentToken(); + var token = prevToken || iterator.stepForward(); + + if (!token) return; + var matchType; + var found = false; + var depth = {}; + var i = cursor.column - token.start; + var bracketType; + var brackets = { + ")": "(", + "(": "(", + "]": "[", + "[": "[", + "{": "{", + "}": "{" + }; + + do { + if (token.value.match(/[{}()\[\]]/g)) { + for (; i < token.value.length && !found; i++) { + if (!brackets[token.value[i]]) { + continue; + } + + bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen"); + + if (isNaN(depth[bracketType])) { + depth[bracketType] = 0; + } + + switch (token.value[i]) { + case '(': + case '[': + case '{': + depth[bracketType]++; + break; + case ')': + case ']': + case '}': + depth[bracketType]--; + + if (depth[bracketType] === -1) { + matchType = 'bracket'; + found = true; + } + break; + } + } + } + else if (token && token.type.indexOf('tag-name') !== -1) { + if (isNaN(depth[token.value])) { + depth[token.value] = 0; + } + + if (prevToken.value === '<') { + depth[token.value]++; + } + else if (prevToken.value === '= 0; --i) { + if(this.$tryReplace(ranges[i], replacement)) { + replaced++; + } + } + + this.selection.setSelectionRange(selection); + this.$blockScrolling -= 1; + + return replaced; + }; + + this.$tryReplace = function(range, replacement) { + var input = this.session.getTextRange(range); + replacement = this.$search.replace(input, replacement); + if (replacement !== null) { + range.end = this.session.replace(range, replacement); + return range; + } else { + return null; + } + }; + this.getLastSearchOptions = function() { + return this.$search.getOptions(); + }; + this.find = function(needle, options, animate) { + if (!options) + options = {}; + + if (typeof needle == "string" || needle instanceof RegExp) + options.needle = needle; + else if (typeof needle == "object") + oop.mixin(options, needle); + + var range = this.selection.getRange(); + if (options.needle == null) { + needle = this.session.getTextRange(range) + || this.$search.$options.needle; + if (!needle) { + range = this.session.getWordRange(range.start.row, range.start.column); + needle = this.session.getTextRange(range); + } + this.$search.set({needle: needle}); + } + + this.$search.set(options); + if (!options.start) + this.$search.set({start: range}); + + var newRange = this.$search.find(this.session); + if (options.preventScroll) + return newRange; + if (newRange) { + this.revealRange(newRange, animate); + return newRange; + } + if (options.backwards) + range.start = range.end; + else + range.end = range.start; + this.selection.setRange(range); + }; + this.findNext = function(options, animate) { + this.find({skipCurrent: true, backwards: false}, options, animate); + }; + this.findPrevious = function(options, animate) { + this.find(options, {skipCurrent: true, backwards: true}, animate); + }; + + this.revealRange = function(range, animate) { + this.$blockScrolling += 1; + this.session.unfold(range); + this.selection.setSelectionRange(range); + this.$blockScrolling -= 1; + + var scrollTop = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + if (animate !== false) + this.renderer.animateScrolling(scrollTop); + }; + this.undo = function() { + this.$blockScrolling++; + this.session.getUndoManager().undo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.redo = function() { + this.$blockScrolling++; + this.session.getUndoManager().redo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.destroy = function() { + this.renderer.destroy(); + this._signal("destroy", this); + if (this.session) { + this.session.destroy(); + } + }; + this.setAutoScrollEditorIntoView = function(enable) { + if (!enable) + return; + var rect; + var self = this; + var shouldScroll = false; + if (!this.$scrollAnchor) + this.$scrollAnchor = document.createElement("div"); + var scrollAnchor = this.$scrollAnchor; + scrollAnchor.style.cssText = "position:absolute"; + this.container.insertBefore(scrollAnchor, this.container.firstChild); + var onChangeSelection = this.on("changeSelection", function() { + shouldScroll = true; + }); + var onBeforeRender = this.renderer.on("beforeRender", function() { + if (shouldScroll) + rect = self.renderer.container.getBoundingClientRect(); + }); + var onAfterRender = this.renderer.on("afterRender", function() { + if (shouldScroll && rect && (self.isFocused() + || self.searchBox && self.searchBox.isFocused()) + ) { + var renderer = self.renderer; + var pos = renderer.$cursorLayer.$pixelPos; + var config = renderer.layerConfig; + var top = pos.top - config.offset; + if (pos.top >= 0 && top + rect.top < 0) { + shouldScroll = true; + } else if (pos.top < config.height && + pos.top + rect.top + config.lineHeight > window.innerHeight) { + shouldScroll = false; + } else { + shouldScroll = null; + } + if (shouldScroll != null) { + scrollAnchor.style.top = top + "px"; + scrollAnchor.style.left = pos.left + "px"; + scrollAnchor.style.height = config.lineHeight + "px"; + scrollAnchor.scrollIntoView(shouldScroll); + } + shouldScroll = rect = null; + } + }); + this.setAutoScrollEditorIntoView = function(enable) { + if (enable) + return; + delete this.setAutoScrollEditorIntoView; + this.off("changeSelection", onChangeSelection); + this.renderer.off("afterRender", onAfterRender); + this.renderer.off("beforeRender", onBeforeRender); + }; + }; + + + this.$resetCursorStyle = function() { + var style = this.$cursorStyle || "ace"; + var cursorLayer = this.renderer.$cursorLayer; + if (!cursorLayer) + return; + cursorLayer.setSmoothBlinking(/smooth/.test(style)); + cursorLayer.isBlinking = !this.$readOnly && style != "wide"; + dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style)); + }; + + }).call(Editor.prototype); + + + + config.defineOptions(Editor.prototype, "editor", { + selectionStyle: { + set: function(style) { + this.onSelectionChange(); + this._signal("changeSelectionStyle", {data: style}); + }, + initialValue: "line" + }, + highlightActiveLine: { + set: function() {this.$updateHighlightActiveLine();}, + initialValue: true + }, + highlightSelectedWord: { + set: function(shouldHighlight) {this.$onSelectionChange();}, + initialValue: true + }, + readOnly: { + set: function(readOnly) { + this.$resetCursorStyle(); + }, + initialValue: false + }, + cursorStyle: { + set: function(val) { this.$resetCursorStyle(); }, + values: ["ace", "slim", "smooth", "wide"], + initialValue: "ace" + }, + mergeUndoDeltas: { + values: [false, true, "always"], + initialValue: true + }, + behavioursEnabled: {initialValue: true}, + wrapBehavioursEnabled: {initialValue: true}, + autoScrollEditorIntoView: { + set: function(val) {this.setAutoScrollEditorIntoView(val);} + }, + keyboardHandler: { + set: function(val) { this.setKeyboardHandler(val); }, + get: function() { return this.keybindingId; }, + handlesSet: true + }, + + hScrollBarAlwaysVisible: "renderer", + vScrollBarAlwaysVisible: "renderer", + highlightGutterLine: "renderer", + animatedScroll: "renderer", + showInvisibles: "renderer", + showPrintMargin: "renderer", + printMarginColumn: "renderer", + printMargin: "renderer", + fadeFoldWidgets: "renderer", + showFoldWidgets: "renderer", + showLineNumbers: "renderer", + showGutter: "renderer", + displayIndentGuides: "renderer", + fontSize: "renderer", + fontFamily: "renderer", + maxLines: "renderer", + minLines: "renderer", + scrollPastEnd: "renderer", + fixedWidthGutter: "renderer", + theme: "renderer", + + scrollSpeed: "$mouseHandler", + dragDelay: "$mouseHandler", + dragEnabled: "$mouseHandler", + focusTimout: "$mouseHandler", + tooltipFollowsMouse: "$mouseHandler", + + firstLineNumber: "session", + overwrite: "session", + newLineMode: "session", + useWorker: "session", + useSoftTabs: "session", + tabSize: "session", + wrap: "session", + indentedSoftWrap: "session", + foldStyle: "session", + mode: "session" + }); + + exports.Editor = Editor; + }); + + ace.define("ace/undomanager",["require","exports","module"], function(acequire, exports, module) { + "use strict"; + var UndoManager = function() { + this.reset(); + }; + + (function() { + this.execute = function(options) { + var deltaSets = options.args[0]; + this.$doc = options.args[1]; + if (options.merge && this.hasUndo()){ + this.dirtyCounter--; + deltaSets = this.$undoStack.pop().concat(deltaSets); + } + this.$undoStack.push(deltaSets); + this.$redoStack = []; + if (this.dirtyCounter < 0) { + this.dirtyCounter = NaN; + } + this.dirtyCounter++; + }; + this.undo = function(dontSelect) { + var deltaSets = this.$undoStack.pop(); + var undoSelectionRange = null; + if (deltaSets) { + undoSelectionRange = this.$doc.undoChanges(deltaSets, dontSelect); + this.$redoStack.push(deltaSets); + this.dirtyCounter--; + } + + return undoSelectionRange; + }; + this.redo = function(dontSelect) { + var deltaSets = this.$redoStack.pop(); + var redoSelectionRange = null; + if (deltaSets) { + redoSelectionRange = + this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect); + this.$undoStack.push(deltaSets); + this.dirtyCounter++; + } + return redoSelectionRange; + }; + this.reset = function() { + this.$undoStack = []; + this.$redoStack = []; + this.dirtyCounter = 0; + }; + this.hasUndo = function() { + return this.$undoStack.length > 0; + }; + this.hasRedo = function() { + return this.$redoStack.length > 0; + }; + this.markClean = function() { + this.dirtyCounter = 0; + }; + this.isClean = function() { + return this.dirtyCounter === 0; + }; + this.$serializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $serializeDelta); + }; + this.$deserializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $deserializeDelta); + }; + + function $serializeDelta(delta){ + return { + action: delta.action, + start: delta.start, + end: delta.end, + lines: delta.lines.length == 1 ? null : delta.lines, + text: delta.lines.length == 1 ? delta.lines[0] : null + }; + } + + function $deserializeDelta(delta) { + return { + action: delta.action, + start: delta.start, + end: delta.end, + lines: delta.lines || [delta.text] + }; + } + + function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { + var deltaSets_new = new Array(deltaSets_old.length); + for (var i = 0; i < deltaSets_old.length; i++) { + var deltaSet_old = deltaSets_old[i]; + var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; + + for (var j = 0; j < deltaSet_old.deltas.length; j++) { + var delta_old = deltaSet_old.deltas[j]; + deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old); + } + + deltaSets_new[i] = deltaSet_new; + } + return deltaSets_new; + } + + }).call(UndoManager.prototype); + + exports.UndoManager = UndoManager; + }); + + ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var oop = acequire("../lib/oop"); + var lang = acequire("../lib/lang"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var Gutter = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_gutter-layer"; + parentEl.appendChild(this.element); + this.setShowFoldWidgets(this.$showFoldWidgets); + + this.gutterWidth = 0; + + this.$annotations = []; + this.$updateAnnotations = this.$updateAnnotations.bind(this); + + this.$cells = []; + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.setSession = function(session) { + if (this.session) + this.session.removeEventListener("change", this.$updateAnnotations); + this.session = session; + if (session) + session.on("change", this.$updateAnnotations); + }; + + this.addGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.addGutterDecoration"); + this.session.addGutterDecoration(row, className); + }; + + this.removeGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.removeGutterDecoration"); + this.session.removeGutterDecoration(row, className); + }; + + this.setAnnotations = function(annotations) { + this.$annotations = []; + for (var i = 0; i < annotations.length; i++) { + var annotation = annotations[i]; + var row = annotation.row; + var rowInfo = this.$annotations[row]; + if (!rowInfo) + rowInfo = this.$annotations[row] = {text: []}; + + var annoText = annotation.text; + annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || ""; + + if (rowInfo.text.indexOf(annoText) === -1) + rowInfo.text.push(annoText); + + var type = annotation.type; + if (type == "error") + rowInfo.className = " ace_error"; + else if (type == "warning" && rowInfo.className != " ace_error") + rowInfo.className = " ace_warning"; + else if (type == "info" && (!rowInfo.className)) + rowInfo.className = " ace_info"; + } + }; + + this.$updateAnnotations = function (delta) { + if (!this.$annotations.length) + return; + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; + if (len === 0) { + } else if (delta.action == 'remove') { + this.$annotations.splice(firstRow, len + 1, null); + } else { + var args = new Array(len + 1); + args.unshift(firstRow, 1); + this.$annotations.splice.apply(this.$annotations, args); + } + }; + + this.update = function(config) { + var session = this.session; + var firstRow = config.firstRow; + var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar + session.getLength() - 1); + var fold = session.getNextFoldLine(firstRow); + var foldStart = fold ? fold.start.row : Infinity; + var foldWidgets = this.$showFoldWidgets && session.foldWidgets; + var breakpoints = session.$breakpoints; + var decorations = session.$decorations; + var firstLineNumber = session.$firstLineNumber; + var lastLineNumber = 0; + + var gutterRenderer = session.gutterRenderer || this.$renderer; + + var cell = null; + var index = -1; + var row = firstRow; + while (true) { + if (row > foldStart) { + row = fold.end.row + 1; + fold = session.getNextFoldLine(row, fold); + foldStart = fold ? fold.start.row : Infinity; + } + if (row > lastRow) { + while (this.$cells.length > index + 1) { + cell = this.$cells.pop(); + this.element.removeChild(cell.element); + } + break; + } + + cell = this.$cells[++index]; + if (!cell) { + cell = {element: null, textNode: null, foldWidget: null}; + cell.element = dom.createElement("div"); + cell.textNode = document.createTextNode(''); + cell.element.appendChild(cell.textNode); + this.element.appendChild(cell.element); + this.$cells[index] = cell; + } + + var className = "ace_gutter-cell "; + if (breakpoints[row]) + className += breakpoints[row]; + if (decorations[row]) + className += decorations[row]; + if (this.$annotations[row]) + className += this.$annotations[row].className; + if (cell.element.className != className) + cell.element.className = className; + + var height = session.getRowLength(row) * config.lineHeight + "px"; + if (height != cell.element.style.height) + cell.element.style.height = height; + + if (foldWidgets) { + var c = foldWidgets[row]; + if (c == null) + c = foldWidgets[row] = session.getFoldWidget(row); + } + + if (c) { + if (!cell.foldWidget) { + cell.foldWidget = dom.createElement("span"); + cell.element.appendChild(cell.foldWidget); + } + var className = "ace_fold-widget ace_" + c; + if (c == "start" && row == foldStart && row < fold.end.row) + className += " ace_closed"; + else + className += " ace_open"; + if (cell.foldWidget.className != className) + cell.foldWidget.className = className; + + var height = config.lineHeight + "px"; + if (cell.foldWidget.style.height != height) + cell.foldWidget.style.height = height; + } else { + if (cell.foldWidget) { + cell.element.removeChild(cell.foldWidget); + cell.foldWidget = null; + } + } + + var text = lastLineNumber = gutterRenderer + ? gutterRenderer.getText(session, row) + : row + firstLineNumber; + if (text !== cell.textNode.data) + cell.textNode.data = text; + + row++; + } + + this.element.style.height = config.minHeight + "px"; + + if (this.$fixedWidth || session.$useWrapMode) + lastLineNumber = session.getLength() + firstLineNumber; + + var gutterWidth = gutterRenderer + ? gutterRenderer.getWidth(session, lastLineNumber, config) + : lastLineNumber.toString().length * config.characterWidth; + + var padding = this.$padding || this.$computePadding(); + gutterWidth += padding.left + padding.right; + if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { + this.gutterWidth = gutterWidth; + this.element.style.width = Math.ceil(this.gutterWidth) + "px"; + this._emit("changeGutterWidth", gutterWidth); + } + }; + + this.$fixedWidth = false; + + this.$showLineNumbers = true; + this.$renderer = ""; + this.setShowLineNumbers = function(show) { + this.$renderer = !show && { + getWidth: function() {return "";}, + getText: function() {return "";} + }; + }; + + this.getShowLineNumbers = function() { + return this.$showLineNumbers; + }; + + this.$showFoldWidgets = true; + this.setShowFoldWidgets = function(show) { + if (show) + dom.addCssClass(this.element, "ace_folding-enabled"); + else + dom.removeCssClass(this.element, "ace_folding-enabled"); + + this.$showFoldWidgets = show; + this.$padding = null; + }; + + this.getShowFoldWidgets = function() { + return this.$showFoldWidgets; + }; + + this.$computePadding = function() { + if (!this.element.firstChild) + return {left: 0, right: 0}; + var style = dom.computedStyle(this.element.firstChild); + this.$padding = {}; + this.$padding.left = parseInt(style.paddingLeft) + 1 || 0; + this.$padding.right = parseInt(style.paddingRight) || 0; + return this.$padding; + }; + + this.getRegion = function(point) { + var padding = this.$padding || this.$computePadding(); + var rect = this.element.getBoundingClientRect(); + if (point.x < padding.left + rect.left) + return "markers"; + if (this.$showFoldWidgets && point.x > rect.right - padding.right) + return "foldWidgets"; + }; + + }).call(Gutter.prototype); + + exports.Gutter = Gutter; + + }); + + ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + var dom = acequire("../lib/dom"); + + var Marker = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_marker-layer"; + parentEl.appendChild(this.element); + }; + + (function() { + + this.$padding = 0; + + this.setPadding = function(padding) { + this.$padding = padding; + }; + this.setSession = function(session) { + this.session = session; + }; + + this.setMarkers = function(markers) { + this.markers = markers; + }; + + this.update = function(config) { + if (!config) return; + + this.config = config; + + + var html = []; + for (var key in this.markers) { + var marker = this.markers[key]; + + if (!marker.range) { + marker.update(html, this, this.session, config); + continue; + } + + var range = marker.range.clipRows(config.firstRow, config.lastRow); + if (range.isEmpty()) continue; + + range = range.toScreenRange(this.session); + if (marker.renderer) { + var top = this.$getTop(range.start.row, config); + var left = this.$padding + (this.session.$bidiHandler.isBidiRow(range.start.row) + ? this.session.$bidiHandler.getPosLeft(range.start.column) + : range.start.column * config.characterWidth); + marker.renderer(html, range, left, top, config); + } else if (marker.type == "fullLine") { + this.drawFullLineMarker(html, range, marker.clazz, config); + } else if (marker.type == "screenLine") { + this.drawScreenLineMarker(html, range, marker.clazz, config); + } else if (range.isMultiLine()) { + if (marker.type == "text") + this.drawTextMarker(html, range, marker.clazz, config); + else + this.drawMultiLineMarker(html, range, marker.clazz, config); + } else { + if (this.session.$bidiHandler.isBidiRow(range.start.row)) { + this.drawBidiSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); + } else { + this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); + } + } + } + this.element.innerHTML = html.join(""); + }; + + this.$getTop = function(row, layerConfig) { + return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; + }; + + function getBorderClass(tl, tr, br, bl) { + return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0); + } + this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) { + var session = this.session; + var start = range.start.row; + var end = range.end.row; + var row = start; + var prev = 0; + var curr = 0; + var next = session.getScreenLastRowColumn(row); + var clazzModified = null; + var lineRange = new Range(row, range.start.column, row, curr); + for (; row <= end; row++) { + lineRange.start.row = lineRange.end.row = row; + lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row); + lineRange.end.column = next; + prev = curr; + curr = next; + next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column; + clazzModified = clazz + (row == start ? " ace_start" : "") + " ace_br" + + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end); + + if (this.session.$bidiHandler.isBidiRow(row)) { + this.drawBidiSingleLineMarker(stringBuilder, lineRange, clazzModified, + layerConfig, row == end ? 0 : 1, extraStyle); + } else { + this.drawSingleLineMarker(stringBuilder, lineRange, clazzModified, + layerConfig, row == end ? 0 : 1, extraStyle); + } + } + }; + this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var padding = this.$padding; + var height, top, left; + extraStyle = extraStyle || ""; + if (this.session.$bidiHandler.isBidiRow(range.start.row)) { + var range1 = range.clone(); + range1.end.row = range1.start.row; + range1.end.column = this.session.getLine(range1.start.row).length; + this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br1 ace_start", config, null, extraStyle); + } else { + height = config.lineHeight; + top = this.$getTop(range.start.row, config); + left = padding + range.start.column * config.characterWidth; + stringBuilder.push( + "
" + ); + } + if (this.session.$bidiHandler.isBidiRow(range.end.row)) { + var range1 = range.clone(); + range1.start.row = range1.end.row; + range1.start.column = 0; + this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br12", config, null, extraStyle); + } else { + var width = range.end.column * config.characterWidth; + height = config.lineHeight; + top = this.$getTop(range.end.row, config); + stringBuilder.push( + "
" + ); + } + height = (range.end.row - range.start.row - 1) * config.lineHeight; + if (height <= 0) + return; + top = this.$getTop(range.start.row + 1, config); + + var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8); + + stringBuilder.push( + "
" + ); + }; + this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { + var height = config.lineHeight; + var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth; + + var top = this.$getTop(range.start.row, config); + var left = this.$padding + range.start.column * config.characterWidth; + + stringBuilder.push( + "
" + ); + }; + this.drawBidiSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { + var height = config.lineHeight, top = this.$getTop(range.start.row, config), padding = this.$padding; + var selections = this.session.$bidiHandler.getSelections(range.start.column, range.end.column); + + selections.forEach(function(selection) { + stringBuilder.push( + "
" + ); + }); + }; + + this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + if (range.start.row != range.end.row) + height += this.$getTop(range.end.row, config) - top; + + stringBuilder.push( + "
" + ); + }; + + this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + + stringBuilder.push( + "
" + ); + }; + + }).call(Marker.prototype); + + exports.Marker = Marker; + + }); + + ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var useragent = acequire("../lib/useragent"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var Text = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_text-layer"; + parentEl.appendChild(this.element); + this.$updateEolChar = this.$updateEolChar.bind(this); + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.EOF_CHAR = "\xB6"; + this.EOL_CHAR_LF = "\xAC"; + this.EOL_CHAR_CRLF = "\xa4"; + this.EOL_CHAR = this.EOL_CHAR_LF; + this.TAB_CHAR = "\u2014"; //"\u21E5"; + this.SPACE_CHAR = "\xB7"; + this.$padding = 0; + + this.$updateEolChar = function() { + var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n" + ? this.EOL_CHAR_LF + : this.EOL_CHAR_CRLF; + if (this.EOL_CHAR != EOL_CHAR) { + this.EOL_CHAR = EOL_CHAR; + return true; + } + }; + + this.setPadding = function(padding) { + this.$padding = padding; + this.element.style.padding = "0 " + padding + "px"; + }; + + this.getLineHeight = function() { + return this.$fontMetrics.$characterSize.height || 0; + }; + + this.getCharacterWidth = function() { + return this.$fontMetrics.$characterSize.width || 0; + }; + + this.$setFontMetrics = function(measure) { + this.$fontMetrics = measure; + this.$fontMetrics.on("changeCharacterSize", function(e) { + this._signal("changeCharacterSize", e); + }.bind(this)); + this.$pollSizeChanges(); + }; + + this.checkForSizeChanges = function() { + this.$fontMetrics.checkForSizeChanges(); + }; + this.$pollSizeChanges = function() { + return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges(); + }; + this.setSession = function(session) { + this.session = session; + if (session) + this.$computeTabString(); + }; + + this.showInvisibles = false; + this.setShowInvisibles = function(showInvisibles) { + if (this.showInvisibles == showInvisibles) + return false; + + this.showInvisibles = showInvisibles; + this.$computeTabString(); + return true; + }; + + this.displayIndentGuides = true; + this.setDisplayIndentGuides = function(display) { + if (this.displayIndentGuides == display) + return false; + + this.displayIndentGuides = display; + this.$computeTabString(); + return true; + }; + + this.$tabStrings = []; + this.onChangeTabSize = + this.$computeTabString = function() { + var tabSize = this.session.getTabSize(); + this.tabSize = tabSize; + var tabStr = this.$tabStrings = [0]; + for (var i = 1; i < tabSize + 1; i++) { + if (this.showInvisibles) { + tabStr.push("" + + lang.stringRepeat(this.TAB_CHAR, i) + + ""); + } else { + tabStr.push(lang.stringRepeat(" ", i)); + } + } + if (this.displayIndentGuides) { + this.$indentGuideRe = /\s\S| \t|\t |\s$/; + var className = "ace_indent-guide"; + var spaceClass = ""; + var tabClass = ""; + if (this.showInvisibles) { + className += " ace_invisible"; + spaceClass = " ace_invisible_space"; + tabClass = " ace_invisible_tab"; + var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); + var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); + } else{ + var spaceContent = lang.stringRepeat(" ", this.tabSize); + var tabContent = spaceContent; + } + + this.$tabStrings[" "] = "" + spaceContent + ""; + this.$tabStrings["\t"] = "" + tabContent + ""; + } + }; + + this.updateLines = function(config, firstRow, lastRow) { + if (this.config.lastRow != config.lastRow || + this.config.firstRow != config.firstRow) { + this.scrollLines(config); + } + this.config = config; + + var first = Math.max(firstRow, config.firstRow); + var last = Math.min(lastRow, config.lastRow); + + var lineElements = this.element.childNodes; + var lineElementsIdx = 0; + + for (var row = config.firstRow; row < first; row++) { + var foldLine = this.session.getFoldLine(row); + if (foldLine) { + if (foldLine.containsRow(first)) { + first = foldLine.start.row; + break; + } else { + row = foldLine.end.row; + } + } + lineElementsIdx ++; + } + + var row = first; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > last) + break; + + var lineElement = lineElements[lineElementsIdx++]; + if (lineElement) { + var html = []; + this.$renderLine( + html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false + ); + lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + lineElement.innerHTML = html.join(""); + } + row++; + } + }; + + this.scrollLines = function(config) { + var oldConfig = this.config; + this.config = config; + + if (!oldConfig || oldConfig.lastRow < config.firstRow) + return this.update(config); + + if (config.lastRow < oldConfig.firstRow) + return this.update(config); + + var el = this.element; + if (oldConfig.firstRow < config.firstRow) + for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) + el.removeChild(el.firstChild); + + if (oldConfig.lastRow > config.lastRow) + for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) + el.removeChild(el.lastChild); + + if (config.firstRow < oldConfig.firstRow) { + var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); + if (el.firstChild) + el.insertBefore(fragment, el.firstChild); + else + el.appendChild(fragment); + } + + if (config.lastRow > oldConfig.lastRow) { + var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); + el.appendChild(fragment); + } + }; + + this.$renderLinesFragment = function(config, firstRow, lastRow) { + var fragment = this.element.ownerDocument.createDocumentFragment(); + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + if (row > lastRow) + break; + + var container = dom.createElement("div"); + + var html = []; + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + container.innerHTML = html.join(""); + if (this.$useLineGroups()) { + container.className = 'ace_line_group'; + fragment.appendChild(container); + container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + + } else { + while(container.firstChild) + fragment.appendChild(container.firstChild); + } + + row++; + } + return fragment; + }; + + this.update = function(config) { + this.config = config; + + var html = []; + var firstRow = config.firstRow, lastRow = config.lastRow; + + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > lastRow) + break; + + if (this.$useLineGroups()) + html.push("
"); + + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + + if (this.$useLineGroups()) + html.push("
"); // end the line group + + row++; + } + this.element.innerHTML = html.join(""); + }; + + this.$textToken = { + "text": true, + "rparen": true, + "lparen": true + }; + + this.$renderToken = function(stringBuilder, screenColumn, token, value) { + var self = this; + var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + var replaceFunc = function(c, a, b, tabIdx, idx4) { + if (a) { + return self.showInvisibles + ? "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" + : c; + } else if (c == "&") { + return "&"; + } else if (c == "<") { + return "<"; + } else if (c == ">") { + return ">"; + } else if (c == "\t") { + var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); + screenColumn += tabSize - 1; + return self.$tabStrings[tabSize]; + } else if (c == "\u3000") { + var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; + var space = self.showInvisibles ? self.SPACE_CHAR : ""; + screenColumn += 1; + return "" + space + ""; + } else if (b) { + return "" + self.SPACE_CHAR + ""; + } else { + screenColumn += 1; + return "" + c + ""; + } + }; + + var output = value.replace(replaceReg, replaceFunc); + + if (!this.$textToken[token.type]) { + var classes = "ace_" + token.type.replace(/\./g, " ace_"); + var style = ""; + if (token.type == "fold") + style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; + stringBuilder.push("", output, ""); + } + else { + stringBuilder.push(output); + } + return screenColumn + value.length; + }; + + this.renderIndentGuide = function(stringBuilder, value, max) { + var cols = value.search(this.$indentGuideRe); + if (cols <= 0 || cols >= max) + return value; + if (value[0] == " ") { + cols -= cols % this.tabSize; + stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); + return value.substr(cols); + } else if (value[0] == "\t") { + stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols)); + return value.substr(cols); + } + return value; + }; + + this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { + var chars = 0; + var split = 0; + var splitChars = splits[0]; + var screenColumn = 0; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + var value = token.value; + if (i == 0 && this.displayIndentGuides) { + chars = value.length; + value = this.renderIndentGuide(stringBuilder, value, splitChars); + if (!value) + continue; + chars -= value.length; + } + + if (chars + value.length < splitChars) { + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + chars += value.length; + } else { + while (chars + value.length >= splitChars) { + screenColumn = this.$renderToken( + stringBuilder, screenColumn, + token, value.substring(0, splitChars - chars) + ); + value = value.substring(splitChars - chars); + chars = splitChars; + + if (!onlyContents) { + stringBuilder.push("", + "
" + ); + } + + stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); + + split ++; + screenColumn = 0; + splitChars = splits[split] || Number.MAX_VALUE; + } + if (value.length != 0) { + chars += value.length; + screenColumn = this.$renderToken( + stringBuilder, screenColumn, token, value + ); + } + } + } + }; + + this.$renderSimpleLine = function(stringBuilder, tokens) { + var screenColumn = 0; + var token = tokens[0]; + var value = token.value; + if (this.displayIndentGuides) + value = this.renderIndentGuide(stringBuilder, value); + if (value) + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + for (var i = 1; i < tokens.length; i++) { + token = tokens[i]; + value = token.value; + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + } + }; + this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { + if (!foldLine && foldLine != false) + foldLine = this.session.getFoldLine(row); + + if (foldLine) + var tokens = this.$getFoldLineTokens(row, foldLine); + else + var tokens = this.session.getTokens(row); + + + if (!onlyContents) { + stringBuilder.push( + "
" + ); + } + + if (tokens.length) { + var splits = this.session.getRowSplitData(row); + if (splits && splits.length) + this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); + else + this.$renderSimpleLine(stringBuilder, tokens); + } + + if (this.showInvisibles) { + if (foldLine) + row = foldLine.end.row; + + stringBuilder.push( + "", + row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, + "" + ); + } + if (!onlyContents) + stringBuilder.push("
"); + }; + + this.$getFoldLineTokens = function(row, foldLine) { + var session = this.session; + var renderTokens = []; + + function addTokens(tokens, from, to) { + var idx = 0, col = 0; + while ((col + tokens[idx].value.length) < from) { + col += tokens[idx].value.length; + idx++; + + if (idx == tokens.length) + return; + } + if (col != from) { + var value = tokens[idx].value.substring(from - col); + if (value.length > (to - from)) + value = value.substring(0, to - from); + + renderTokens.push({ + type: tokens[idx].type, + value: value + }); + + col = from + value.length; + idx += 1; + } + + while (col < to && idx < tokens.length) { + var value = tokens[idx].value; + if (value.length + col > to) { + renderTokens.push({ + type: tokens[idx].type, + value: value.substring(0, to - col) + }); + } else + renderTokens.push(tokens[idx]); + col += value.length; + idx += 1; + } + } + + var tokens = session.getTokens(row); + foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) { + if (placeholder != null) { + renderTokens.push({ + type: "fold", + value: placeholder + }); + } else { + if (isNewRow) + tokens = session.getTokens(row); + + if (tokens.length) + addTokens(tokens, lastColumn, column); + } + }, foldLine.end.row, this.session.getLine(foldLine.end.row).length); + + return renderTokens; + }; + + this.$useLineGroups = function() { + return this.session.getUseWrapMode(); + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.$measureNode) + this.$measureNode.parentNode.removeChild(this.$measureNode); + delete this.$measureNode; + }; + + }).call(Text.prototype); + + exports.Text = Text; + + }); + + ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var isIE8; + + var Cursor = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_cursor-layer"; + parentEl.appendChild(this.element); + + if (isIE8 === undefined) + isIE8 = !("opacity" in this.element.style); + + this.isVisible = false; + this.isBlinking = true; + this.blinkInterval = 1000; + this.smoothBlinking = false; + + this.cursors = []; + this.cursor = this.addCursor(); + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.$updateCursors = (isIE8 + ? this.$updateVisibility + : this.$updateOpacity).bind(this); + }; + + (function() { + + this.$updateVisibility = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.visibility = val ? "" : "hidden"; + }; + this.$updateOpacity = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.opacity = val ? "" : "0"; + }; + + + this.$padding = 0; + this.setPadding = function(padding) { + this.$padding = padding; + }; + + this.setSession = function(session) { + this.session = session; + }; + + this.setBlinking = function(blinking) { + if (blinking != this.isBlinking){ + this.isBlinking = blinking; + this.restartTimer(); + } + }; + + this.setBlinkInterval = function(blinkInterval) { + if (blinkInterval != this.blinkInterval){ + this.blinkInterval = blinkInterval; + this.restartTimer(); + } + }; + + this.setSmoothBlinking = function(smoothBlinking) { + if (smoothBlinking != this.smoothBlinking && !isIE8) { + this.smoothBlinking = smoothBlinking; + dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); + this.$updateCursors(true); + this.$updateCursors = (this.$updateOpacity).bind(this); + this.restartTimer(); + } + }; + + this.addCursor = function() { + var el = dom.createElement("div"); + el.className = "ace_cursor"; + this.element.appendChild(el); + this.cursors.push(el); + return el; + }; + + this.removeCursor = function() { + if (this.cursors.length > 1) { + var el = this.cursors.pop(); + el.parentNode.removeChild(el); + return el; + } + }; + + this.hideCursor = function() { + this.isVisible = false; + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.showCursor = function() { + this.isVisible = true; + dom.removeCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.restartTimer = function() { + var update = this.$updateCursors; + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + if (this.smoothBlinking) { + dom.removeCssClass(this.element, "ace_smooth-blinking"); + } + + update(true); + + if (!this.isBlinking || !this.blinkInterval || !this.isVisible) + return; + + if (this.smoothBlinking) { + setTimeout(function(){ + dom.addCssClass(this.element, "ace_smooth-blinking"); + }.bind(this)); + } + + var blink = function(){ + this.timeoutId = setTimeout(function() { + update(false); + }, 0.6 * this.blinkInterval); + }.bind(this); + + this.intervalId = setInterval(function() { + update(true); + blink(); + }, this.blinkInterval); + + blink(); + }; + + this.getPixelPosition = function(position, onScreen) { + if (!this.config || !this.session) + return {left : 0, top : 0}; + + if (!position) + position = this.session.selection.getCursor(); + var pos = this.session.documentToScreenPosition(position); + var cursorLeft = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, position.row) + ? this.session.$bidiHandler.getPosLeft(pos.column) + : pos.column * this.config.characterWidth); + + var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * + this.config.lineHeight; + + return {left : cursorLeft, top : cursorTop}; + }; + + this.update = function(config) { + this.config = config; + + var selections = this.session.$selectionMarkers; + var i = 0, cursorIndex = 0; + + if (selections === undefined || selections.length === 0){ + selections = [{cursor: null}]; + } + + for (var i = 0, n = selections.length; i < n; i++) { + var pixelPos = this.getPixelPosition(selections[i].cursor, true); + if ((pixelPos.top > config.height + config.offset || + pixelPos.top < 0) && i > 1) { + continue; + } + + var style = (this.cursors[cursorIndex++] || this.addCursor()).style; + + if (!this.drawCursor) { + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + } else { + this.drawCursor(style, pixelPos, config, selections[i], this.session); + } + } + while (this.cursors.length > cursorIndex) + this.removeCursor(); + + var overwrite = this.session.getOverwrite(); + this.$setOverwrite(overwrite); + this.$pixelPos = pixelPos; + this.restartTimer(); + }; + + this.drawCursor = null; + + this.$setOverwrite = function(overwrite) { + if (overwrite != this.overwrite) { + this.overwrite = overwrite; + if (overwrite) + dom.addCssClass(this.element, "ace_overwrite-cursors"); + else + dom.removeCssClass(this.element, "ace_overwrite-cursors"); + } + }; + + this.destroy = function() { + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + }; + + }).call(Cursor.prototype); + + exports.Cursor = Cursor; + + }); + + ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var event = acequire("./lib/event"); + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var MAX_SCROLL_H = 0x8000; + var ScrollBar = function(parent) { + this.element = dom.createElement("div"); + this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix; + + this.inner = dom.createElement("div"); + this.inner.className = "ace_scrollbar-inner"; + this.element.appendChild(this.inner); + + parent.appendChild(this.element); + + this.setVisible(false); + this.skipEvent = false; + + event.addListener(this.element, "scroll", this.onScroll.bind(this)); + event.addListener(this.element, "mousedown", event.preventDefault); + }; + + (function() { + oop.implement(this, EventEmitter); + + this.setVisible = function(isVisible) { + this.element.style.display = isVisible ? "" : "none"; + this.isVisible = isVisible; + this.coeff = 1; + }; + }).call(ScrollBar.prototype); + var VScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollTop = 0; + this.scrollHeight = 0; + renderer.$scrollbarWidth = + this.width = dom.scrollbarWidth(parent.ownerDocument); + this.inner.style.width = + this.element.style.width = (this.width || 15) + 5 + "px"; + this.$minWidth = 0; + }; + + oop.inherits(VScrollBar, ScrollBar); + + (function() { + + this.classSuffix = '-v'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollTop = this.element.scrollTop; + if (this.coeff != 1) { + var h = this.element.clientHeight / this.scrollHeight; + this.scrollTop = this.scrollTop * (1 - h) / (this.coeff - h); + } + this._emit("scroll", {data: this.scrollTop}); + } + this.skipEvent = false; + }; + this.getWidth = function() { + return Math.max(this.isVisible ? this.width : 0, this.$minWidth || 0); + }; + this.setHeight = function(height) { + this.element.style.height = height + "px"; + }; + this.setInnerHeight = + this.setScrollHeight = function(height) { + this.scrollHeight = height; + if (height > MAX_SCROLL_H) { + this.coeff = MAX_SCROLL_H / height; + height = MAX_SCROLL_H; + } else if (this.coeff != 1) { + this.coeff = 1; + } + this.inner.style.height = height + "px"; + }; + this.setScrollTop = function(scrollTop) { + if (this.scrollTop != scrollTop) { + this.skipEvent = true; + this.scrollTop = scrollTop; + this.element.scrollTop = scrollTop * this.coeff; + } + }; + + }).call(VScrollBar.prototype); + var HScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollLeft = 0; + this.height = renderer.$scrollbarWidth; + this.inner.style.height = + this.element.style.height = (this.height || 15) + 5 + "px"; + }; + + oop.inherits(HScrollBar, ScrollBar); + + (function() { + + this.classSuffix = '-h'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollLeft = this.element.scrollLeft; + this._emit("scroll", {data: this.scrollLeft}); + } + this.skipEvent = false; + }; + this.getHeight = function() { + return this.isVisible ? this.height : 0; + }; + this.setWidth = function(width) { + this.element.style.width = width + "px"; + }; + this.setInnerWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollLeft = function(scrollLeft) { + if (this.scrollLeft != scrollLeft) { + this.skipEvent = true; + this.scrollLeft = this.element.scrollLeft = scrollLeft; + } + }; + + }).call(HScrollBar.prototype); + + + exports.ScrollBar = VScrollBar; // backward compatibility + exports.ScrollBarV = VScrollBar; // backward compatibility + exports.ScrollBarH = HScrollBar; // backward compatibility + + exports.VScrollBar = VScrollBar; + exports.HScrollBar = HScrollBar; + }); + + ace.define("ace/renderloop",["require","exports","module","ace/lib/event"], function(acequire, exports, module) { + "use strict"; + + var event = acequire("./lib/event"); + + + var RenderLoop = function(onRender, win) { + this.onRender = onRender; + this.pending = false; + this.changes = 0; + this.window = win || window; + }; + + (function() { + + + this.schedule = function(change) { + this.changes = this.changes | change; + if (!this.pending && this.changes) { + this.pending = true; + var _self = this; + event.nextFrame(function() { + _self.pending = false; + var changes; + while (changes = _self.changes) { + _self.changes = 0; + _self.onRender(changes); + } + }, this.window); + } + }; + + }).call(RenderLoop.prototype); + + exports.RenderLoop = RenderLoop; + }); + + ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(acequire, exports, module) { + + var oop = acequire("../lib/oop"); + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var useragent = acequire("../lib/useragent"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + + var CHAR_COUNT = 0; + + var FontMetrics = exports.FontMetrics = function(parentEl) { + this.el = dom.createElement("div"); + this.$setMeasureNodeStyles(this.el.style, true); + + this.$main = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$main.style); + + this.$measureNode = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$measureNode.style); + + + this.el.appendChild(this.$main); + this.el.appendChild(this.$measureNode); + parentEl.appendChild(this.el); + + if (!CHAR_COUNT) + this.$testFractionalRect(); + this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT); + + this.$characterSize = {width: 0, height: 0}; + this.checkForSizeChanges(); + }; + + (function() { + + oop.implement(this, EventEmitter); + + this.$characterSize = {width: 0, height: 0}; + + this.$testFractionalRect = function() { + var el = dom.createElement("div"); + this.$setMeasureNodeStyles(el.style); + el.style.width = "0.2px"; + document.documentElement.appendChild(el); + var w = el.getBoundingClientRect().width; + if (w > 0 && w < 1) + CHAR_COUNT = 50; + else + CHAR_COUNT = 100; + el.parentNode.removeChild(el); + }; + + this.$setMeasureNodeStyles = function(style, isRoot) { + style.width = style.height = "auto"; + style.left = style.top = "0px"; + style.visibility = "hidden"; + style.position = "absolute"; + style.whiteSpace = "pre"; + + if (useragent.isIE < 8) { + style["font-family"] = "inherit"; + } else { + style.font = "inherit"; + } + style.overflow = isRoot ? "hidden" : "visible"; + }; + + this.checkForSizeChanges = function() { + var size = this.$measureSizes(); + if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { + this.$measureNode.style.fontWeight = "bold"; + var boldSize = this.$measureSizes(); + this.$measureNode.style.fontWeight = ""; + this.$characterSize = size; + this.charSizes = Object.create(null); + this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height; + this._emit("changeCharacterSize", {data: size}); + } + }; + + this.$pollSizeChanges = function() { + if (this.$pollSizeChangesTimer) + return this.$pollSizeChangesTimer; + var self = this; + return this.$pollSizeChangesTimer = setInterval(function() { + self.checkForSizeChanges(); + }, 500); + }; + + this.setPolling = function(val) { + if (val) { + this.$pollSizeChanges(); + } else if (this.$pollSizeChangesTimer) { + clearInterval(this.$pollSizeChangesTimer); + this.$pollSizeChangesTimer = 0; + } + }; + + this.$measureSizes = function() { + if (CHAR_COUNT === 50) { + var rect = null; + try { + rect = this.$measureNode.getBoundingClientRect(); + } catch(e) { + rect = {width: 0, height:0 }; + } + var size = { + height: rect.height, + width: rect.width / CHAR_COUNT + }; + } else { + var size = { + height: this.$measureNode.clientHeight, + width: this.$measureNode.clientWidth / CHAR_COUNT + }; + } + if (size.width === 0 || size.height === 0) + return null; + return size; + }; + + this.$measureCharWidth = function(ch) { + this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT); + var rect = this.$main.getBoundingClientRect(); + return rect.width / CHAR_COUNT; + }; + + this.getCharacterWidth = function(ch) { + var w = this.charSizes[ch]; + if (w === undefined) { + w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width; + } + return w; + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.el && this.el.parentNode) + this.el.parentNode.removeChild(this.el); + }; + + }).call(FontMetrics.prototype); + + }); + + ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var config = acequire("./config"); + var useragent = acequire("./lib/useragent"); + var GutterLayer = acequire("./layer/gutter").Gutter; + var MarkerLayer = acequire("./layer/marker").Marker; + var TextLayer = acequire("./layer/text").Text; + var CursorLayer = acequire("./layer/cursor").Cursor; + var HScrollBar = acequire("./scrollbar").HScrollBar; + var VScrollBar = acequire("./scrollbar").VScrollBar; + var RenderLoop = acequire("./renderloop").RenderLoop; + var FontMetrics = acequire("./layer/font_metrics").FontMetrics; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var editorCss = ".ace_editor {\ + position: relative;\ + overflow: hidden;\ + font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\ + direction: ltr;\ + text-align: left;\ + -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\ + }\ + .ace_scroller {\ + position: absolute;\ + overflow: hidden;\ + top: 0;\ + bottom: 0;\ + background-color: inherit;\ + -ms-user-select: none;\ + -moz-user-select: none;\ + -webkit-user-select: none;\ + user-select: none;\ + cursor: text;\ + }\ + .ace_content {\ + position: absolute;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + min-width: 100%;\ + }\ + .ace_dragging .ace_scroller:before{\ + position: absolute;\ + top: 0;\ + left: 0;\ + right: 0;\ + bottom: 0;\ + content: '';\ + background: rgba(250, 250, 250, 0.01);\ + z-index: 1000;\ + }\ + .ace_dragging.ace_dark .ace_scroller:before{\ + background: rgba(0, 0, 0, 0.01);\ + }\ + .ace_selecting, .ace_selecting * {\ + cursor: text !important;\ + }\ + .ace_gutter {\ + position: absolute;\ + overflow : hidden;\ + width: auto;\ + top: 0;\ + bottom: 0;\ + left: 0;\ + cursor: default;\ + z-index: 4;\ + -ms-user-select: none;\ + -moz-user-select: none;\ + -webkit-user-select: none;\ + user-select: none;\ + }\ + .ace_gutter-active-line {\ + position: absolute;\ + left: 0;\ + right: 0;\ + }\ + .ace_scroller.ace_scroll-left {\ + box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\ + }\ + .ace_gutter-cell {\ + padding-left: 19px;\ + padding-right: 6px;\ + background-repeat: no-repeat;\ + }\ + .ace_gutter-cell.ace_error {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\ + background-repeat: no-repeat;\ + background-position: 2px center;\ + }\ + .ace_gutter-cell.ace_warning {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\ + background-position: 2px center;\ + }\ + .ace_gutter-cell.ace_info {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\ + background-position: 2px center;\ + }\ + .ace_dark .ace_gutter-cell.ace_info {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\ + }\ + .ace_scrollbar {\ + position: absolute;\ + right: 0;\ + bottom: 0;\ + z-index: 6;\ + }\ + .ace_scrollbar-inner {\ + position: absolute;\ + cursor: text;\ + left: 0;\ + top: 0;\ + }\ + .ace_scrollbar-v{\ + overflow-x: hidden;\ + overflow-y: scroll;\ + top: 0;\ + }\ + .ace_scrollbar-h {\ + overflow-x: scroll;\ + overflow-y: hidden;\ + left: 0;\ + }\ + .ace_print-margin {\ + position: absolute;\ + height: 100%;\ + }\ + .ace_text-input {\ + position: absolute;\ + z-index: 0;\ + width: 0.5em;\ + height: 1em;\ + opacity: 0;\ + background: transparent;\ + -moz-appearance: none;\ + appearance: none;\ + border: none;\ + resize: none;\ + outline: none;\ + overflow: hidden;\ + font: inherit;\ + padding: 0 1px;\ + margin: 0 -1px;\ + text-indent: -1em;\ + -ms-user-select: text;\ + -moz-user-select: text;\ + -webkit-user-select: text;\ + user-select: text;\ + white-space: pre!important;\ + }\ + .ace_text-input.ace_composition {\ + background: inherit;\ + color: inherit;\ + z-index: 1000;\ + opacity: 1;\ + text-indent: 0;\ + }\ + .ace_layer {\ + z-index: 1;\ + position: absolute;\ + overflow: hidden;\ + word-wrap: normal;\ + white-space: pre;\ + height: 100%;\ + width: 100%;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + pointer-events: none;\ + }\ + .ace_gutter-layer {\ + position: relative;\ + width: auto;\ + text-align: right;\ + pointer-events: auto;\ + }\ + .ace_text-layer {\ + font: inherit !important;\ + }\ + .ace_cjk {\ + display: inline-block;\ + text-align: center;\ + }\ + .ace_cursor-layer {\ + z-index: 4;\ + }\ + .ace_cursor {\ + z-index: 4;\ + position: absolute;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + border-left: 2px solid;\ + transform: translatez(0);\ + }\ + .ace_multiselect .ace_cursor {\ + border-left-width: 1px;\ + }\ + .ace_slim-cursors .ace_cursor {\ + border-left-width: 1px;\ + }\ + .ace_overwrite-cursors .ace_cursor {\ + border-left-width: 0;\ + border-bottom: 1px solid;\ + }\ + .ace_hidden-cursors .ace_cursor {\ + opacity: 0.2;\ + }\ + .ace_smooth-blinking .ace_cursor {\ + -webkit-transition: opacity 0.18s;\ + transition: opacity 0.18s;\ + }\ + .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\ + position: absolute;\ + z-index: 3;\ + }\ + .ace_marker-layer .ace_selection {\ + position: absolute;\ + z-index: 5;\ + }\ + .ace_marker-layer .ace_bracket {\ + position: absolute;\ + z-index: 6;\ + }\ + .ace_marker-layer .ace_active-line {\ + position: absolute;\ + z-index: 2;\ + }\ + .ace_marker-layer .ace_selected-word {\ + position: absolute;\ + z-index: 4;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + }\ + .ace_line .ace_fold {\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + display: inline-block;\ + height: 11px;\ + margin-top: -2px;\ + vertical-align: middle;\ + background-image:\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\ + background-repeat: no-repeat, repeat-x;\ + background-position: center center, top left;\ + color: transparent;\ + border: 1px solid black;\ + border-radius: 2px;\ + cursor: pointer;\ + pointer-events: auto;\ + }\ + .ace_dark .ace_fold {\ + }\ + .ace_fold:hover{\ + background-image:\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ + url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\ + }\ + .ace_tooltip {\ + background-color: #FFF;\ + background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\ + background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\ + border: 1px solid gray;\ + border-radius: 1px;\ + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\ + color: black;\ + max-width: 100%;\ + padding: 3px 4px;\ + position: fixed;\ + z-index: 999999;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + cursor: default;\ + white-space: pre;\ + word-wrap: break-word;\ + line-height: normal;\ + font-style: normal;\ + font-weight: normal;\ + letter-spacing: normal;\ + pointer-events: none;\ + }\ + .ace_folding-enabled > .ace_gutter-cell {\ + padding-right: 13px;\ + }\ + .ace_fold-widget {\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ + margin: 0 -12px 0 1px;\ + display: none;\ + width: 11px;\ + vertical-align: top;\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\ + background-repeat: no-repeat;\ + background-position: center;\ + border-radius: 3px;\ + border: 1px solid transparent;\ + cursor: pointer;\ + }\ + .ace_folding-enabled .ace_fold-widget {\ + display: inline-block; \ + }\ + .ace_fold-widget.ace_end {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\ + }\ + .ace_fold-widget.ace_closed {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\ + }\ + .ace_fold-widget:hover {\ + border: 1px solid rgba(0, 0, 0, 0.3);\ + background-color: rgba(255, 255, 255, 0.2);\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\ + }\ + .ace_fold-widget:active {\ + border: 1px solid rgba(0, 0, 0, 0.4);\ + background-color: rgba(0, 0, 0, 0.05);\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\ + }\ + .ace_dark .ace_fold-widget {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\ + }\ + .ace_dark .ace_fold-widget.ace_end {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\ + }\ + .ace_dark .ace_fold-widget.ace_closed {\ + background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\ + }\ + .ace_dark .ace_fold-widget:hover {\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ + background-color: rgba(255, 255, 255, 0.1);\ + }\ + .ace_dark .ace_fold-widget:active {\ + box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ + }\ + .ace_fold-widget.ace_invalid {\ + background-color: #FFB4B4;\ + border-color: #DE5555;\ + }\ + .ace_fade-fold-widgets .ace_fold-widget {\ + -webkit-transition: opacity 0.4s ease 0.05s;\ + transition: opacity 0.4s ease 0.05s;\ + opacity: 0;\ + }\ + .ace_fade-fold-widgets:hover .ace_fold-widget {\ + -webkit-transition: opacity 0.05s ease 0.05s;\ + transition: opacity 0.05s ease 0.05s;\ + opacity:1;\ + }\ + .ace_underline {\ + text-decoration: underline;\ + }\ + .ace_bold {\ + font-weight: bold;\ + }\ + .ace_nobold .ace_bold {\ + font-weight: normal;\ + }\ + .ace_italic {\ + font-style: italic;\ + }\ + .ace_error-marker {\ + background-color: rgba(255, 0, 0,0.2);\ + position: absolute;\ + z-index: 9;\ + }\ + .ace_highlight-marker {\ + background-color: rgba(255, 255, 0,0.2);\ + position: absolute;\ + z-index: 8;\ + }\ + .ace_br1 {border-top-left-radius : 3px;}\ + .ace_br2 {border-top-right-radius : 3px;}\ + .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\ + .ace_br4 {border-bottom-right-radius: 3px;}\ + .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\ + .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\ + .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\ + .ace_br8 {border-bottom-left-radius : 3px;}\ + .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\ + .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\ + .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\ + .ace_text-input-ios {\ + position: absolute !important;\ + top: -100000px !important;\ + left: -100000px !important;\ + }\ + "; + + dom.importCssString(editorCss, "ace_editor.css"); + + var VirtualRenderer = function(container, theme) { + var _self = this; + + this.container = container || dom.createElement("div"); + this.$keepTextAreaAtCursor = !useragent.isOldIE; + + dom.addCssClass(this.container, "ace_editor"); + + this.setTheme(theme); + + this.$gutter = dom.createElement("div"); + this.$gutter.className = "ace_gutter"; + this.container.appendChild(this.$gutter); + this.$gutter.setAttribute("aria-hidden", true); + + this.scroller = dom.createElement("div"); + this.scroller.className = "ace_scroller"; + this.container.appendChild(this.scroller); + + this.content = dom.createElement("div"); + this.content.className = "ace_content"; + this.scroller.appendChild(this.content); + + this.$gutterLayer = new GutterLayer(this.$gutter); + this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)); + + this.$markerBack = new MarkerLayer(this.content); + + var textLayer = this.$textLayer = new TextLayer(this.content); + this.canvas = textLayer.element; + + this.$markerFront = new MarkerLayer(this.content); + + this.$cursorLayer = new CursorLayer(this.content); + this.$horizScroll = false; + this.$vScroll = false; + + this.scrollBar = + this.scrollBarV = new VScrollBar(this.container, this); + this.scrollBarH = new HScrollBar(this.container, this); + this.scrollBarV.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollTop(e.data - _self.scrollMargin.top); + }); + this.scrollBarH.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollLeft(e.data - _self.scrollMargin.left); + }); + + this.scrollTop = 0; + this.scrollLeft = 0; + + this.cursorPos = { + row : 0, + column : 0 + }; + + this.$fontMetrics = new FontMetrics(this.container); + this.$textLayer.$setFontMetrics(this.$fontMetrics); + this.$textLayer.addEventListener("changeCharacterSize", function(e) { + _self.updateCharacterSize(); + _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height); + _self._signal("changeCharacterSize", e); + }); + + this.$size = { + width: 0, + height: 0, + scrollerHeight: 0, + scrollerWidth: 0, + $dirty: true + }; + + this.layerConfig = { + width : 1, + padding : 0, + firstRow : 0, + firstRowScreen: 0, + lastRow : 0, + lineHeight : 0, + characterWidth : 0, + minHeight : 1, + maxHeight : 1, + offset : 0, + height : 1, + gutterOffset: 1 + }; + + this.scrollMargin = { + left: 0, + right: 0, + top: 0, + bottom: 0, + v: 0, + h: 0 + }; + + this.$loop = new RenderLoop( + this.$renderChanges.bind(this), + this.container.ownerDocument.defaultView + ); + this.$loop.schedule(this.CHANGE_FULL); + + this.updateCharacterSize(); + this.setPadding(4); + config.resetOptions(this); + config._emit("renderer", this); + }; + + (function() { + + this.CHANGE_CURSOR = 1; + this.CHANGE_MARKER = 2; + this.CHANGE_GUTTER = 4; + this.CHANGE_SCROLL = 8; + this.CHANGE_LINES = 16; + this.CHANGE_TEXT = 32; + this.CHANGE_SIZE = 64; + this.CHANGE_MARKER_BACK = 128; + this.CHANGE_MARKER_FRONT = 256; + this.CHANGE_FULL = 512; + this.CHANGE_H_SCROLL = 1024; + + oop.implement(this, EventEmitter); + + this.updateCharacterSize = function() { + if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) { + this.$allowBoldFonts = this.$textLayer.allowBoldFonts; + this.setStyle("ace_nobold", !this.$allowBoldFonts); + } + + this.layerConfig.characterWidth = + this.characterWidth = this.$textLayer.getCharacterWidth(); + this.layerConfig.lineHeight = + this.lineHeight = this.$textLayer.getLineHeight(); + this.$updatePrintMargin(); + }; + this.setSession = function(session) { + if (this.session) + this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode); + + this.session = session; + if (session && this.scrollMargin.top && session.getScrollTop() <= 0) + session.setScrollTop(-this.scrollMargin.top); + + this.$cursorLayer.setSession(session); + this.$markerBack.setSession(session); + this.$markerFront.setSession(session); + this.$gutterLayer.setSession(session); + this.$textLayer.setSession(session); + if (!session) + return; + + this.$loop.schedule(this.CHANGE_FULL); + this.session.$setFontMetrics(this.$fontMetrics); + this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null; + + this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); + this.onChangeNewLineMode(); + this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); + }; + this.updateLines = function(firstRow, lastRow, force) { + if (lastRow === undefined) + lastRow = Infinity; + + if (!this.$changedLines) { + this.$changedLines = { + firstRow: firstRow, + lastRow: lastRow + }; + } + else { + if (this.$changedLines.firstRow > firstRow) + this.$changedLines.firstRow = firstRow; + + if (this.$changedLines.lastRow < lastRow) + this.$changedLines.lastRow = lastRow; + } + if (this.$changedLines.lastRow < this.layerConfig.firstRow) { + if (force) + this.$changedLines.lastRow = this.layerConfig.lastRow; + else + return; + } + if (this.$changedLines.firstRow > this.layerConfig.lastRow) + return; + this.$loop.schedule(this.CHANGE_LINES); + }; + + this.onChangeNewLineMode = function() { + this.$loop.schedule(this.CHANGE_TEXT); + this.$textLayer.$updateEolChar(); + this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR); + }; + + this.onChangeTabSize = function() { + this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); + this.$textLayer.onChangeTabSize(); + }; + this.updateText = function() { + this.$loop.schedule(this.CHANGE_TEXT); + }; + this.updateFull = function(force) { + if (force) + this.$renderChanges(this.CHANGE_FULL, true); + else + this.$loop.schedule(this.CHANGE_FULL); + }; + this.updateFontSize = function() { + this.$textLayer.checkForSizeChanges(); + }; + + this.$changes = 0; + this.$updateSizeAsync = function() { + if (this.$loop.pending) + this.$size.$dirty = true; + else + this.onResize(); + }; + this.onResize = function(force, gutterWidth, width, height) { + if (this.resizing > 2) + return; + else if (this.resizing > 0) + this.resizing++; + else + this.resizing = force ? 1 : 0; + var el = this.container; + if (!height) + height = el.clientHeight || el.scrollHeight; + if (!width) + width = el.clientWidth || el.scrollWidth; + var changes = this.$updateCachedSize(force, gutterWidth, width, height); + + + if (!this.$size.scrollerHeight || (!width && !height)) + return this.resizing = 0; + + if (force) + this.$gutterLayer.$padding = null; + + if (force) + this.$renderChanges(changes | this.$changes, true); + else + this.$loop.schedule(changes | this.$changes); + + if (this.resizing) + this.resizing = 0; + this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null; + }; + + this.$updateCachedSize = function(force, gutterWidth, width, height) { + height -= (this.$extraHeight || 0); + var changes = 0; + var size = this.$size; + var oldSize = { + width: size.width, + height: size.height, + scrollerHeight: size.scrollerHeight, + scrollerWidth: size.scrollerWidth + }; + if (height && (force || size.height != height)) { + size.height = height; + changes |= this.CHANGE_SIZE; + + size.scrollerHeight = size.height; + if (this.$horizScroll) + size.scrollerHeight -= this.scrollBarH.getHeight(); + this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; + + changes = changes | this.CHANGE_SCROLL; + } + + if (width && (force || size.width != width)) { + changes |= this.CHANGE_SIZE; + size.width = width; + + if (gutterWidth == null) + gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + + this.gutterWidth = gutterWidth; + + this.scrollBarH.element.style.left = + this.scroller.style.left = gutterWidth + "px"; + size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); + + this.scrollBarH.element.style.right = + this.scroller.style.right = this.scrollBarV.getWidth() + "px"; + this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; + + if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) + changes |= this.CHANGE_FULL; + } + + size.$dirty = !width || !height; + + if (changes) + this._signal("resize", oldSize); + + return changes; + }; + + this.onGutterResize = function() { + var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + if (gutterWidth != this.gutterWidth) + this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); + + if (this.session.getUseWrapMode() && this.adjustWrapLimit()) { + this.$loop.schedule(this.CHANGE_FULL); + } else if (this.$size.$dirty) { + this.$loop.schedule(this.CHANGE_FULL); + } else { + this.$computeLayerConfig(); + this.$loop.schedule(this.CHANGE_MARKER); + } + }; + this.adjustWrapLimit = function() { + var availableWidth = this.$size.scrollerWidth - this.$padding * 2; + var limit = Math.floor(availableWidth / this.characterWidth); + return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn); + }; + this.setAnimatedScroll = function(shouldAnimate){ + this.setOption("animatedScroll", shouldAnimate); + }; + this.getAnimatedScroll = function() { + return this.$animatedScroll; + }; + this.setShowInvisibles = function(showInvisibles) { + this.setOption("showInvisibles", showInvisibles); + this.session.$bidiHandler.setShowInvisibles(showInvisibles); + }; + this.getShowInvisibles = function() { + return this.getOption("showInvisibles"); + }; + this.getDisplayIndentGuides = function() { + return this.getOption("displayIndentGuides"); + }; + + this.setDisplayIndentGuides = function(display) { + this.setOption("displayIndentGuides", display); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.setOption("showPrintMargin", showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.getOption("showPrintMargin"); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.setOption("printMarginColumn", showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.getOption("printMarginColumn"); + }; + this.getShowGutter = function(){ + return this.getOption("showGutter"); + }; + this.setShowGutter = function(show){ + return this.setOption("showGutter", show); + }; + + this.getFadeFoldWidgets = function(){ + return this.getOption("fadeFoldWidgets"); + }; + + this.setFadeFoldWidgets = function(show) { + this.setOption("fadeFoldWidgets", show); + }; + + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + + this.$updateGutterLineHighlight = function() { + var pos = this.$cursorLayer.$pixelPos; + var height = this.layerConfig.lineHeight; + if (this.session.getUseWrapMode()) { + var cursor = this.session.selection.getCursor(); + cursor.column = 0; + pos = this.$cursorLayer.getPixelPosition(cursor, true); + height *= this.session.getRowLength(cursor.row); + } + this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px"; + this.$gutterLineHighlight.style.height = height + "px"; + }; + + this.$updatePrintMargin = function() { + if (!this.$showPrintMargin && !this.$printMarginEl) + return; + + if (!this.$printMarginEl) { + var containerEl = dom.createElement("div"); + containerEl.className = "ace_layer ace_print-margin-layer"; + this.$printMarginEl = dom.createElement("div"); + this.$printMarginEl.className = "ace_print-margin"; + containerEl.appendChild(this.$printMarginEl); + this.content.insertBefore(containerEl, this.content.firstChild); + } + + var style = this.$printMarginEl.style; + style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px"; + style.visibility = this.$showPrintMargin ? "visible" : "hidden"; + + if (this.session && this.session.$wrap == -1) + this.adjustWrapLimit(); + }; + this.getContainerElement = function() { + return this.container; + }; + this.getMouseEventTarget = function() { + return this.scroller; + }; + this.getTextAreaContainer = function() { + return this.container; + }; + this.$moveTextAreaToCursor = function() { + if (!this.$keepTextAreaAtCursor) + return; + var config = this.layerConfig; + var posTop = this.$cursorLayer.$pixelPos.top; + var posLeft = this.$cursorLayer.$pixelPos.left; + posTop -= config.offset; + + var style = this.textarea.style; + var h = this.lineHeight; + if (posTop < 0 || posTop > config.height - h) { + style.top = style.left = "0"; + return; + } + + var w = this.characterWidth; + if (this.$composition) { + var val = this.textarea.value.replace(/^\x01+/, ""); + w *= (this.session.$getStringScreenWidth(val)[0]+2); + h += 2; + } + posLeft -= this.scrollLeft; + if (posLeft > this.$size.scrollerWidth - w) + posLeft = this.$size.scrollerWidth - w; + + posLeft += this.gutterWidth; + style.height = h + "px"; + style.width = w + "px"; + style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; + style.top = Math.min(posTop, this.$size.height - h) + "px"; + }; + this.getFirstVisibleRow = function() { + return this.layerConfig.firstRow; + }; + this.getFirstFullyVisibleRow = function() { + return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); + }; + this.getLastFullyVisibleRow = function() { + var config = this.layerConfig; + var lastRow = config.lastRow; + var top = this.session.documentToScreenRow(lastRow, 0) * config.lineHeight; + if (top - this.session.getScrollTop() > config.height - config.lineHeight) + return lastRow - 1; + return lastRow; + }; + this.getLastVisibleRow = function() { + return this.layerConfig.lastRow; + }; + + this.$padding = null; + this.setPadding = function(padding) { + this.$padding = padding; + this.$textLayer.setPadding(padding); + this.$cursorLayer.setPadding(padding); + this.$markerFront.setPadding(padding); + this.$markerBack.setPadding(padding); + this.$loop.schedule(this.CHANGE_FULL); + this.$updatePrintMargin(); + }; + + this.setScrollMargin = function(top, bottom, left, right) { + var sm = this.scrollMargin; + sm.top = top|0; + sm.bottom = bottom|0; + sm.right = right|0; + sm.left = left|0; + sm.v = sm.top + sm.bottom; + sm.h = sm.left + sm.right; + if (sm.top && this.scrollTop <= 0 && this.session) + this.session.setScrollTop(-sm.top); + this.updateFull(); + }; + this.getHScrollBarAlwaysVisible = function() { + return this.$hScrollBarAlwaysVisible; + }; + this.setHScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("hScrollBarAlwaysVisible", alwaysVisible); + }; + this.getVScrollBarAlwaysVisible = function() { + return this.$vScrollBarAlwaysVisible; + }; + this.setVScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("vScrollBarAlwaysVisible", alwaysVisible); + }; + + this.$updateScrollBarV = function() { + var scrollHeight = this.layerConfig.maxHeight; + var scrollerHeight = this.$size.scrollerHeight; + if (!this.$maxLines && this.$scrollPastEnd) { + scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd; + if (this.scrollTop > scrollHeight - scrollerHeight) { + scrollHeight = this.scrollTop + scrollerHeight; + this.scrollBarV.scrollTop = null; + } + } + this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v); + this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); + }; + this.$updateScrollBarH = function() { + this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h); + this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left); + }; + + this.$frozen = false; + this.freeze = function() { + this.$frozen = true; + }; + + this.unfreeze = function() { + this.$frozen = false; + }; + + this.$renderChanges = function(changes, force) { + if (this.$changes) { + changes |= this.$changes; + this.$changes = 0; + } + if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { + this.$changes |= changes; + return; + } + if (this.$size.$dirty) { + this.$changes |= changes; + return this.onResize(true); + } + if (!this.lineHeight) { + this.$textLayer.checkForSizeChanges(); + } + + this._signal("beforeRender"); + + if (this.session && this.session.$bidiHandler) + this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics); + + var config = this.layerConfig; + if (changes & this.CHANGE_FULL || + changes & this.CHANGE_SIZE || + changes & this.CHANGE_TEXT || + changes & this.CHANGE_LINES || + changes & this.CHANGE_SCROLL || + changes & this.CHANGE_H_SCROLL + ) { + changes |= this.$computeLayerConfig(); + if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) { + var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight; + if (st > 0) { + this.scrollTop = st; + changes = changes | this.CHANGE_SCROLL; + changes |= this.$computeLayerConfig(); + } + } + config = this.layerConfig; + this.$updateScrollBarV(); + if (changes & this.CHANGE_H_SCROLL) + this.$updateScrollBarH(); + this.$gutterLayer.element.style.marginTop = (-config.offset) + "px"; + this.content.style.marginTop = (-config.offset) + "px"; + this.content.style.width = config.width + 2 * this.$padding + "px"; + this.content.style.height = config.minHeight + "px"; + } + if (changes & this.CHANGE_H_SCROLL) { + this.content.style.marginLeft = -this.scrollLeft + "px"; + this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left"; + } + if (changes & this.CHANGE_FULL) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this._signal("afterRender"); + return; + } + if (changes & this.CHANGE_SCROLL) { + if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) + this.$textLayer.update(config); + else + this.$textLayer.scrollLines(config); + + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this.$moveTextAreaToCursor(); + this._signal("afterRender"); + return; + } + + if (changes & this.CHANGE_TEXT) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_LINES) { + if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { + if (this.$showGutter) + this.$gutterLayer.update(config); + } + + if (changes & this.CHANGE_CURSOR) { + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { + this.$markerFront.update(config); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) { + this.$markerBack.update(config); + } + + this._signal("afterRender"); + }; + + + this.$autosize = function() { + var height = this.session.getScreenLength() * this.lineHeight; + var maxHeight = this.$maxLines * this.lineHeight; + var desiredHeight = Math.min(maxHeight, + Math.max((this.$minLines || 1) * this.lineHeight, height) + ) + this.scrollMargin.v + (this.$extraHeight || 0); + if (this.$horizScroll) + desiredHeight += this.scrollBarH.getHeight(); + if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight) + desiredHeight = this.$maxPixelHeight; + var vScroll = height > maxHeight; + + if (desiredHeight != this.desiredHeight || + this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { + if (vScroll != this.$vScroll) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var w = this.container.clientWidth; + this.container.style.height = desiredHeight + "px"; + this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight); + this.desiredHeight = desiredHeight; + + this._signal("autosize"); + } + }; + + this.$computeLayerConfig = function() { + var session = this.session; + var size = this.$size; + + var hideScrollbars = size.height <= 2 * this.lineHeight; + var screenLines = this.session.getScreenLength(); + var maxHeight = screenLines * this.lineHeight; + + var longestLine = this.$getLongestLine(); + + var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || + size.scrollerWidth - longestLine - 2 * this.$padding < 0); + + var hScrollChanged = this.$horizScroll !== horizScroll; + if (hScrollChanged) { + this.$horizScroll = horizScroll; + this.scrollBarH.setVisible(horizScroll); + } + var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine + if (this.$maxLines && this.lineHeight > 1) + this.$autosize(); + + var offset = this.scrollTop % this.lineHeight; + var minHeight = size.scrollerHeight + this.lineHeight; + + var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd + ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd + : 0; + maxHeight += scrollPastEnd; + + var sm = this.scrollMargin; + this.session.setScrollTop(Math.max(-sm.top, + Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom))); + + this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, + longestLine + 2 * this.$padding - size.scrollerWidth + sm.right))); + + var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || + size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top); + var vScrollChanged = vScrollBefore !== vScroll; + if (vScrollChanged) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; + var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); + var lastRow = firstRow + lineCount; + var firstRowScreen, firstRowHeight; + var lineHeight = this.lineHeight; + firstRow = session.screenToDocumentRow(firstRow, 0); + var foldLine = session.getFoldLine(firstRow); + if (foldLine) { + firstRow = foldLine.start.row; + } + + firstRowScreen = session.documentToScreenRow(firstRow, 0); + firstRowHeight = session.getRowLength(firstRow) * lineHeight; + + lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); + minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + + firstRowHeight; + + offset = this.scrollTop - firstRowScreen * lineHeight; + + var changes = 0; + if (this.layerConfig.width != longestLine) + changes = this.CHANGE_H_SCROLL; + if (hScrollChanged || vScrollChanged) { + changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height); + this._signal("scrollbarVisibilityChanged"); + if (vScrollChanged) + longestLine = this.$getLongestLine(); + } + + this.layerConfig = { + width : longestLine, + padding : this.$padding, + firstRow : firstRow, + firstRowScreen: firstRowScreen, + lastRow : lastRow, + lineHeight : lineHeight, + characterWidth : this.characterWidth, + minHeight : minHeight, + maxHeight : maxHeight, + offset : offset, + gutterOffset : lineHeight ? Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)) : 0, + height : this.$size.scrollerHeight + }; + + return changes; + }; + + this.$updateLines = function() { + if (!this.$changedLines) return; + var firstRow = this.$changedLines.firstRow; + var lastRow = this.$changedLines.lastRow; + this.$changedLines = null; + + var layerConfig = this.layerConfig; + + if (firstRow > layerConfig.lastRow + 1) { return; } + if (lastRow < layerConfig.firstRow) { return; } + if (lastRow === Infinity) { + if (this.$showGutter) + this.$gutterLayer.update(layerConfig); + this.$textLayer.update(layerConfig); + return; + } + this.$textLayer.updateLines(layerConfig, firstRow, lastRow); + return true; + }; + + this.$getLongestLine = function() { + var charCount = this.session.getScreenWidth(); + if (this.showInvisibles && !this.session.$useWrapMode) + charCount += 1; + + return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth)); + }; + this.updateFrontMarkers = function() { + this.$markerFront.setMarkers(this.session.getMarkers(true)); + this.$loop.schedule(this.CHANGE_MARKER_FRONT); + }; + this.updateBackMarkers = function() { + this.$markerBack.setMarkers(this.session.getMarkers()); + this.$loop.schedule(this.CHANGE_MARKER_BACK); + }; + this.addGutterDecoration = function(row, className){ + this.$gutterLayer.addGutterDecoration(row, className); + }; + this.removeGutterDecoration = function(row, className){ + this.$gutterLayer.removeGutterDecoration(row, className); + }; + this.updateBreakpoints = function(rows) { + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.setAnnotations = function(annotations) { + this.$gutterLayer.setAnnotations(annotations); + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.updateCursor = function() { + this.$loop.schedule(this.CHANGE_CURSOR); + }; + this.hideCursor = function() { + this.$cursorLayer.hideCursor(); + }; + this.showCursor = function() { + this.$cursorLayer.showCursor(); + }; + + this.scrollSelectionIntoView = function(anchor, lead, offset) { + this.scrollCursorIntoView(anchor, offset); + this.scrollCursorIntoView(lead, offset); + }; + this.scrollCursorIntoView = function(cursor, offset, $viewMargin) { + if (this.$size.scrollerHeight === 0) + return; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + + var left = pos.left; + var top = pos.top; + + var topMargin = $viewMargin && $viewMargin.top || 0; + var bottomMargin = $viewMargin && $viewMargin.bottom || 0; + + var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop; + + if (scrollTop + topMargin > top) { + if (offset && scrollTop + topMargin > top + this.lineHeight) + top -= offset * this.$size.scrollerHeight; + if (top === 0) + top = -this.scrollMargin.top; + this.session.setScrollTop(top); + } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) { + if (offset && scrollTop + this.$size.scrollerHeight - bottomMargin < top - this.lineHeight) + top += offset * this.$size.scrollerHeight; + this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight); + } + + var scrollLeft = this.scrollLeft; + + if (scrollLeft > left) { + if (left < this.$padding + 2 * this.layerConfig.characterWidth) + left = -this.scrollMargin.left; + this.session.setScrollLeft(left); + } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) { + this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth)); + } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) { + this.session.setScrollLeft(0); + } + }; + this.getScrollTop = function() { + return this.session.getScrollTop(); + }; + this.getScrollLeft = function() { + return this.session.getScrollLeft(); + }; + this.getScrollTopRow = function() { + return this.scrollTop / this.lineHeight; + }; + this.getScrollBottomRow = function() { + return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1); + }; + this.scrollToRow = function(row) { + this.session.setScrollTop(row * this.lineHeight); + }; + + this.alignCursor = function(cursor, alignment) { + if (typeof cursor == "number") + cursor = {row: cursor, column: 0}; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + var h = this.$size.scrollerHeight - this.lineHeight; + var offset = pos.top - h * (alignment || 0); + + this.session.setScrollTop(offset); + return offset; + }; + + this.STEPS = 8; + this.$calcSteps = function(fromValue, toValue){ + var i = 0; + var l = this.STEPS; + var steps = []; + + var func = function(t, x_min, dx) { + return dx * (Math.pow(t - 1, 3) + 1) + x_min; + }; + + for (i = 0; i < l; ++i) + steps.push(func(i / this.STEPS, fromValue, toValue - fromValue)); + + return steps; + }; + this.scrollToLine = function(line, center, animate, callback) { + var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); + var offset = pos.top; + if (center) + offset -= this.$size.scrollerHeight / 2; + + var initialScroll = this.scrollTop; + this.session.setScrollTop(offset); + if (animate !== false) + this.animateScrolling(initialScroll, callback); + }; + + this.animateScrolling = function(fromValue, callback) { + var toValue = this.scrollTop; + if (!this.$animatedScroll) + return; + var _self = this; + + if (fromValue == toValue) + return; + + if (this.$scrollAnimation) { + var oldSteps = this.$scrollAnimation.steps; + if (oldSteps.length) { + fromValue = oldSteps[0]; + if (fromValue == toValue) + return; + } + } + + var steps = _self.$calcSteps(fromValue, toValue); + this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps}; + + clearInterval(this.$timer); + + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + this.$timer = setInterval(function() { + if (steps.length) { + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + } else if (toValue != null) { + _self.session.$scrollTop = -1; + _self.session.setScrollTop(toValue); + toValue = null; + } else { + _self.$timer = clearInterval(_self.$timer); + _self.$scrollAnimation = null; + callback && callback(); + } + }, 10); + }; + this.scrollToY = function(scrollTop) { + if (this.scrollTop !== scrollTop) { + this.$loop.schedule(this.CHANGE_SCROLL); + this.scrollTop = scrollTop; + } + }; + this.scrollToX = function(scrollLeft) { + if (this.scrollLeft !== scrollLeft) + this.scrollLeft = scrollLeft; + this.$loop.schedule(this.CHANGE_H_SCROLL); + }; + this.scrollTo = function(x, y) { + this.session.setScrollTop(y); + this.session.setScrollLeft(y); + }; + this.scrollBy = function(deltaX, deltaY) { + deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); + deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); + }; + this.isScrollableBy = function(deltaX, deltaY) { + if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top) + return true; + if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight + - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom) + return true; + if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left) + return true; + if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth + - this.layerConfig.width < -1 + this.scrollMargin.right) + return true; + }; + + this.pixelToScreenCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding; + var offset = offsetX / this.characterWidth; + var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); + var col = Math.round(offset); + + return {row: row, column: col, side: offset - col > 0 ? 1 : -1, offsetX: offsetX}; + }; + + this.screenToTextCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding; + + var col = Math.round(offsetX / this.characterWidth); + + var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight; + + return this.session.screenToDocumentPosition(row, Math.max(col, 0), offsetX); + }; + this.textToScreenCoordinates = function(row, column) { + var canvasPos = this.scroller.getBoundingClientRect(); + var pos = this.session.documentToScreenPosition(row, column); + + var x = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, row) + ? this.session.$bidiHandler.getPosLeft(pos.column) + : Math.round(pos.column * this.characterWidth)); + + var y = pos.row * this.lineHeight; + + return { + pageX: canvasPos.left + x - this.scrollLeft, + pageY: canvasPos.top + y - this.scrollTop + }; + }; + this.visualizeFocus = function() { + dom.addCssClass(this.container, "ace_focus"); + }; + this.visualizeBlur = function() { + dom.removeCssClass(this.container, "ace_focus"); + }; + this.showComposition = function(position) { + if (!this.$composition) + this.$composition = { + keepTextAreaAtCursor: this.$keepTextAreaAtCursor, + cssText: this.textarea.style.cssText + }; + + this.$keepTextAreaAtCursor = true; + dom.addCssClass(this.textarea, "ace_composition"); + this.textarea.style.cssText = ""; + this.$moveTextAreaToCursor(); + }; + this.setCompositionText = function(text) { + this.$moveTextAreaToCursor(); + }; + this.hideComposition = function() { + if (!this.$composition) + return; + + dom.removeCssClass(this.textarea, "ace_composition"); + this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; + this.textarea.style.cssText = this.$composition.cssText; + this.$composition = null; + }; + this.setTheme = function(theme, cb) { + var _self = this; + this.$themeId = theme; + _self._dispatchEvent('themeChange',{theme:theme}); + + if (!theme || typeof theme == "string") { + var moduleName = theme || this.$options.theme.initialValue; + config.loadModule(["theme", moduleName], afterLoad); + } else { + afterLoad(theme); + } + + function afterLoad(module) { + if (_self.$themeId != theme) + return cb && cb(); + if (!module || !module.cssClass) + throw new Error("couldn't load module " + theme + " or it didn't call define"); + dom.importCssString( + module.cssText, + module.cssClass, + _self.container.ownerDocument + ); + + if (_self.theme) + dom.removeCssClass(_self.container, _self.theme.cssClass); + + var padding = "padding" in module ? module.padding + : "padding" in (_self.theme || {}) ? 4 : _self.$padding; + if (_self.$padding && padding != _self.$padding) + _self.setPadding(padding); + _self.$theme = module.cssClass; + + _self.theme = module; + dom.addCssClass(_self.container, module.cssClass); + dom.setCssClass(_self.container, "ace_dark", module.isDark); + if (_self.$size) { + _self.$size.width = 0; + _self.$updateSizeAsync(); + } + + _self._dispatchEvent('themeLoaded', {theme:module}); + cb && cb(); + } + }; + this.getTheme = function() { + return this.$themeId; + }; + this.setStyle = function(style, include) { + dom.setCssClass(this.container, style, include !== false); + }; + this.unsetStyle = function(style) { + dom.removeCssClass(this.container, style); + }; + + this.setCursorStyle = function(style) { + if (this.scroller.style.cursor != style) + this.scroller.style.cursor = style; + }; + this.setMouseCursor = function(cursorStyle) { + this.scroller.style.cursor = cursorStyle; + }; + this.destroy = function() { + this.$textLayer.destroy(); + this.$cursorLayer.destroy(); + }; + + }).call(VirtualRenderer.prototype); + + + config.defineOptions(VirtualRenderer.prototype, "renderer", { + animatedScroll: {initialValue: false}, + showInvisibles: { + set: function(value) { + if (this.$textLayer.setShowInvisibles(value)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: false + }, + showPrintMargin: { + set: function() { this.$updatePrintMargin(); }, + initialValue: true + }, + printMarginColumn: { + set: function() { this.$updatePrintMargin(); }, + initialValue: 80 + }, + printMargin: { + set: function(val) { + if (typeof val == "number") + this.$printMarginColumn = val; + this.$showPrintMargin = !!val; + this.$updatePrintMargin(); + }, + get: function() { + return this.$showPrintMargin && this.$printMarginColumn; + } + }, + showGutter: { + set: function(show){ + this.$gutter.style.display = show ? "block" : "none"; + this.$loop.schedule(this.CHANGE_FULL); + this.onGutterResize(); + }, + initialValue: true + }, + fadeFoldWidgets: { + set: function(show) { + dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show); + }, + initialValue: false + }, + showFoldWidgets: { + set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);}, + initialValue: true + }, + showLineNumbers: { + set: function(show) { + this.$gutterLayer.setShowLineNumbers(show); + this.$loop.schedule(this.CHANGE_GUTTER); + }, + initialValue: true + }, + displayIndentGuides: { + set: function(show) { + if (this.$textLayer.setDisplayIndentGuides(show)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: true + }, + highlightGutterLine: { + set: function(shouldHighlight) { + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter-active-line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + if (this.$cursorLayer.$pixelPos) + this.$updateGutterLineHighlight(); + }, + initialValue: false, + value: true + }, + hScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + vScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$vScrollBarAlwaysVisible || !this.$vScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + fontSize: { + set: function(size) { + if (typeof size == "number") + size = size + "px"; + this.container.style.fontSize = size; + this.updateFontSize(); + }, + initialValue: 12 + }, + fontFamily: { + set: function(name) { + this.container.style.fontFamily = name; + this.updateFontSize(); + } + }, + maxLines: { + set: function(val) { + this.updateFull(); + } + }, + minLines: { + set: function(val) { + this.updateFull(); + } + }, + maxPixelHeight: { + set: function(val) { + this.updateFull(); + }, + initialValue: 0 + }, + scrollPastEnd: { + set: function(val) { + val = +val || 0; + if (this.$scrollPastEnd == val) + return; + this.$scrollPastEnd = val; + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: 0, + handlesSet: true + }, + fixedWidthGutter: { + set: function(val) { + this.$gutterLayer.$fixedWidth = !!val; + this.$loop.schedule(this.CHANGE_GUTTER); + } + }, + theme: { + set: function(val) { this.setTheme(val); }, + get: function() { return this.$themeId || this.theme; }, + initialValue: "./theme/textmate", + handlesSet: true + } + }); + + exports.VirtualRenderer = VirtualRenderer; + }); + + ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var net = acequire("../lib/net"); + var EventEmitter = acequire("../lib/event_emitter").EventEmitter; + var config = acequire("../config"); + + function $workerBlob(workerUrl, mod) { + var script = mod.src;"importScripts('" + net.qualifyURL(workerUrl) + "');"; + try { + return new Blob([script], {"type": "application/javascript"}); + } catch (e) { // Backwards-compatibility + var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder; + var blobBuilder = new BlobBuilder(); + blobBuilder.append(script); + return blobBuilder.getBlob("application/javascript"); + } + } + + function createWorker(workerUrl, mod) { + var blob = $workerBlob(workerUrl, mod); + var URL = window.URL || window.webkitURL; + var blobURL = URL.createObjectURL(blob); + return new Worker(blobURL); + } + + var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl, importScripts) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.onMessage = this.onMessage.bind(this); + if (acequire.nameToUrl && !acequire.toUrl) + acequire.toUrl = acequire.nameToUrl; + + if (config.get("packaged") || !acequire.toUrl) { + workerUrl = workerUrl || config.moduleUrl(mod.id, "worker"); + } else { + var normalizePath = this.$normalizePath; + workerUrl = workerUrl || normalizePath(acequire.toUrl("ace/worker/worker.js", null, "_")); + + var tlns = {}; + topLevelNamespaces.forEach(function(ns) { + tlns[ns] = normalizePath(acequire.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); + }); + } + + this.$worker = createWorker(workerUrl, mod); + if (importScripts) { + this.send("importScripts", importScripts); + } + this.$worker.postMessage({ + init : true, + tlns : tlns, + module : mod.id, + classname : classname + }); + + this.callbackId = 1; + this.callbacks = {}; + + this.$worker.onmessage = this.onMessage; + }; + + (function(){ + + oop.implement(this, EventEmitter); + + this.onMessage = function(e) { + var msg = e.data; + switch (msg.type) { + case "event": + this._signal(msg.name, {data: msg.data}); + break; + case "call": + var callback = this.callbacks[msg.id]; + if (callback) { + callback(msg.data); + delete this.callbacks[msg.id]; + } + break; + case "error": + this.reportError(msg.data); + break; + case "log": + window.console && console.log && console.log.apply(console, msg.data); + break; + } + }; + + this.reportError = function(err) { + window.console && console.error && console.error(err); + }; + + this.$normalizePath = function(path) { + return net.qualifyURL(path); + }; + + this.terminate = function() { + this._signal("terminate", {}); + this.deltaQueue = null; + this.$worker.terminate(); + this.$worker = null; + if (this.$doc) + this.$doc.off("change", this.changeListener); + this.$doc = null; + }; + + this.send = function(cmd, args) { + this.$worker.postMessage({command: cmd, args: args}); + }; + + this.call = function(cmd, args, callback) { + if (callback) { + var id = this.callbackId++; + this.callbacks[id] = callback; + args.push(id); + } + this.send(cmd, args); + }; + + this.emit = function(event, data) { + try { + this.$worker.postMessage({event: event, data: {data: data.data}}); + } + catch(ex) { + console.error(ex.stack); + } + }; + + this.attachToDocument = function(doc) { + if (this.$doc) + this.terminate(); + + this.$doc = doc; + this.call("setValue", [doc.getValue()]); + doc.on("change", this.changeListener); + }; + + this.changeListener = function(delta) { + if (!this.deltaQueue) { + this.deltaQueue = []; + setTimeout(this.$sendDeltaQueue, 0); + } + if (delta.action == "insert") + this.deltaQueue.push(delta.start, delta.lines); + else + this.deltaQueue.push(delta.start, delta.end); + }; + + this.$sendDeltaQueue = function() { + var q = this.deltaQueue; + if (!q) return; + this.deltaQueue = null; + if (q.length > 50 && q.length > this.$doc.getLength() >> 1) { + this.call("setValue", [this.$doc.getValue()]); + } else + this.emit("change", {data: q}); + }; + + }).call(WorkerClient.prototype); + + + var UIWorkerClient = function(topLevelNamespaces, mod, classname) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.callbackId = 1; + this.callbacks = {}; + this.messageBuffer = []; + + var main = null; + var emitSync = false; + var sender = Object.create(EventEmitter); + var _self = this; + + this.$worker = {}; + this.$worker.terminate = function() {}; + this.$worker.postMessage = function(e) { + _self.messageBuffer.push(e); + if (main) { + if (emitSync) + setTimeout(processNext); + else + processNext(); + } + }; + this.setEmitSync = function(val) { emitSync = val; }; + + var processNext = function() { + var msg = _self.messageBuffer.shift(); + if (msg.command) + main[msg.command].apply(main, msg.args); + else if (msg.event) + sender._signal(msg.event, msg.data); + }; + + sender.postMessage = function(msg) { + _self.onMessage({data: msg}); + }; + sender.callback = function(data, callbackId) { + this.postMessage({type: "call", id: callbackId, data: data}); + }; + sender.emit = function(name, data) { + this.postMessage({type: "event", name: name, data: data}); + }; + + config.loadModule(["worker", mod], function(Main) { + main = new Main[classname](sender); + while (_self.messageBuffer.length) + processNext(); + }); + }; + + UIWorkerClient.prototype = WorkerClient.prototype; + + exports.UIWorkerClient = UIWorkerClient; + exports.WorkerClient = WorkerClient; + exports.createWorker = createWorker; + + + }); + + ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("./range").Range; + var EventEmitter = acequire("./lib/event_emitter").EventEmitter; + var oop = acequire("./lib/oop"); + + var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) { + var _self = this; + this.length = length; + this.session = session; + this.doc = session.getDocument(); + this.mainClass = mainClass; + this.othersClass = othersClass; + this.$onUpdate = this.onUpdate.bind(this); + this.doc.on("change", this.$onUpdate); + this.$others = others; + + this.$onCursorChange = function() { + setTimeout(function() { + _self.onCursorChange(); + }); + }; + + this.$pos = pos; + var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1}; + this.$undoStackDepth = undoStack.length; + this.setup(); + + session.selection.on("changeCursor", this.$onCursorChange); + }; + + (function() { + + oop.implement(this, EventEmitter); + this.setup = function() { + var _self = this; + var doc = this.doc; + var session = this.session; + + this.selectionBefore = session.selection.toJSON(); + if (session.selection.inMultiSelectMode) + session.selection.toSingleRange(); + + this.pos = doc.createAnchor(this.$pos.row, this.$pos.column); + var pos = this.pos; + pos.$insertRight = true; + pos.detach(); + pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false); + this.others = []; + this.$others.forEach(function(other) { + var anchor = doc.createAnchor(other.row, other.column); + anchor.$insertRight = true; + anchor.detach(); + _self.others.push(anchor); + }); + session.setUndoSelect(false); + }; + this.showOtherMarkers = function() { + if (this.othersActive) return; + var session = this.session; + var _self = this; + this.othersActive = true; + this.others.forEach(function(anchor) { + anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false); + }); + }; + this.hideOtherMarkers = function() { + if (!this.othersActive) return; + this.othersActive = false; + for (var i = 0; i < this.others.length; i++) { + this.session.removeMarker(this.others[i].markerId); + } + }; + this.onUpdate = function(delta) { + if (this.$updating) + return this.updateAnchors(delta); + + var range = delta; + if (range.start.row !== range.end.row) return; + if (range.start.row !== this.pos.row) return; + this.$updating = true; + var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column; + var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1; + var distanceFromStart = range.start.column - this.pos.column; + + this.updateAnchors(delta); + + if (inMainRange) + this.length += lengthDiff; + + if (inMainRange && !this.session.$fromUndo) { + if (delta.action === 'insert') { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + this.doc.insertMergedLines(newPos, delta.lines); + } + } else if (delta.action === 'remove') { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff)); + } + } + } + + this.$updating = false; + this.updateMarkers(); + }; + + this.updateAnchors = function(delta) { + this.pos.onChange(delta); + for (var i = this.others.length; i--;) + this.others[i].onChange(delta); + this.updateMarkers(); + }; + + this.updateMarkers = function() { + if (this.$updating) + return; + var _self = this; + var session = this.session; + var updateMarker = function(pos, className) { + session.removeMarker(pos.markerId); + pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false); + }; + updateMarker(this.pos, this.mainClass); + for (var i = this.others.length; i--;) + updateMarker(this.others[i], this.othersClass); + }; + + this.onCursorChange = function(event) { + if (this.$updating || !this.session) return; + var pos = this.session.selection.getCursor(); + if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) { + this.showOtherMarkers(); + this._emit("cursorEnter", event); + } else { + this.hideOtherMarkers(); + this._emit("cursorLeave", event); + } + }; + this.detach = function() { + this.session.removeMarker(this.pos && this.pos.markerId); + this.hideOtherMarkers(); + this.doc.removeEventListener("change", this.$onUpdate); + this.session.selection.removeEventListener("changeCursor", this.$onCursorChange); + this.session.setUndoSelect(true); + this.session = null; + }; + this.cancel = function() { + if (this.$undoStackDepth === -1) + return; + var undoManager = this.session.getUndoManager(); + var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth; + for (var i = 0; i < undosRequired; i++) { + undoManager.undo(true); + } + if (this.selectionBefore) + this.session.selection.fromJSON(this.selectionBefore); + }; + }).call(PlaceHolder.prototype); + + + exports.PlaceHolder = PlaceHolder; + }); + + ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(acequire, exports, module) { + + var event = acequire("../lib/event"); + var useragent = acequire("../lib/useragent"); + function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; + } + + function onMouseDown(e) { + var ev = e.domEvent; + var alt = ev.altKey; + var shift = ev.shiftKey; + var ctrl = ev.ctrlKey; + var accel = e.getAccelKey(); + var button = e.getButton(); + + if (ctrl && useragent.isMac) + button = ev.button; + + if (e.editor.inMultiSelectMode && button == 2) { + e.editor.textInput.onContextMenu(e.domEvent); + return; + } + + if (!ctrl && !alt && !accel) { + if (button === 0 && e.editor.inMultiSelectMode) + e.editor.exitMultiSelectMode(); + return; + } + + if (button !== 0) + return; + + var editor = e.editor; + var selection = editor.selection; + var isMultiSelect = editor.inMultiSelectMode; + var pos = e.getDocumentPosition(); + var cursor = selection.getCursor(); + var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); + + var mouseX = e.x, mouseY = e.y; + var onMouseSelection = function(e) { + mouseX = e.clientX; + mouseY = e.clientY; + }; + + var session = editor.session; + var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var screenCursor = screenAnchor; + + var selectionMode; + if (editor.$mouseHandler.$enableJumpToDef) { + if (ctrl && alt || accel && alt) + selectionMode = shift ? "block" : "add"; + else if (alt && editor.$blockSelectEnabled) + selectionMode = "block"; + } else { + if (accel && !alt) { + selectionMode = "add"; + if (!isMultiSelect && shift) + return; + } else if (alt && editor.$blockSelectEnabled) { + selectionMode = "block"; + } + } + + if (selectionMode && useragent.isMac && ev.ctrlKey) { + editor.$mouseHandler.cancelContextMenu(); + } + + if (selectionMode == "add") { + if (!isMultiSelect && inSelection) + return; // dragging + + if (!isMultiSelect) { + var range = selection.toOrientedRange(); + editor.addSelectionMarker(range); + } + + var oldRange = selection.rangeList.rangeAtPoint(pos); + + + editor.$blockScrolling++; + editor.inVirtualSelectionMode = true; + + if (shift) { + oldRange = null; + range = selection.ranges[0] || range; + editor.removeSelectionMarker(range); + } + editor.once("mouseup", function() { + var tmpSel = selection.toOrientedRange(); + + if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) + selection.substractPoint(tmpSel.cursor); + else { + if (shift) { + selection.substractPoint(range.cursor); + } else if (range) { + editor.removeSelectionMarker(range); + selection.addRange(range); + } + selection.addRange(tmpSel); + } + editor.$blockScrolling--; + editor.inVirtualSelectionMode = false; + }); + + } else if (selectionMode == "block") { + e.stop(); + editor.inVirtualSelectionMode = true; + var initialRange; + var rectSel = []; + var blockSelect = function() { + var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column, newCursor.offsetX); + + if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead)) + return; + screenCursor = newCursor; + + editor.$blockScrolling++; + editor.selection.moveToPosition(cursor); + editor.renderer.scrollCursorIntoView(); + + editor.removeSelectionMarkers(rectSel); + rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); + if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty()) + rectSel[0] = editor.$mouseHandler.$clickSelection.clone(); + rectSel.forEach(editor.addSelectionMarker, editor); + editor.updateSelectionMarkers(); + editor.$blockScrolling--; + }; + editor.$blockScrolling++; + if (isMultiSelect && !accel) { + selection.toSingleRange(); + } else if (!isMultiSelect && accel) { + initialRange = selection.toOrientedRange(); + editor.addSelectionMarker(initialRange); + } + + if (shift) + screenAnchor = session.documentToScreenPosition(selection.lead); + else + selection.moveToPosition(pos); + editor.$blockScrolling--; + + screenCursor = {row: -1, column: -1}; + + var onMouseSelectionEnd = function(e) { + clearInterval(timerId); + editor.removeSelectionMarkers(rectSel); + if (!rectSel.length) + rectSel = [selection.toOrientedRange()]; + editor.$blockScrolling++; + if (initialRange) { + editor.removeSelectionMarker(initialRange); + selection.toSingleRange(initialRange); + } + for (var i = 0; i < rectSel.length; i++) + selection.addRange(rectSel[i]); + editor.inVirtualSelectionMode = false; + editor.$mouseHandler.$clickSelection = null; + editor.$blockScrolling--; + }; + + var onSelectionInterval = blockSelect; + + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(function() {onSelectionInterval();}, 20); + + return e.preventDefault(); + } + } + + + exports.onMouseDown = onMouseDown; + + }); + + ace.define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(acequire, exports, module) { + exports.defaultCommands = [{ + name: "addCursorAbove", + exec: function(editor) { editor.selectMoreLines(-1); }, + bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorBelow", + exec: function(editor) { editor.selectMoreLines(1); }, + bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorAboveSkipCurrent", + exec: function(editor) { editor.selectMoreLines(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "addCursorBelowSkipCurrent", + exec: function(editor) { editor.selectMoreLines(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectMoreBefore", + exec: function(editor) { editor.selectMore(-1); }, + bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectMoreAfter", + exec: function(editor) { editor.selectMore(1); }, + bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectNextBefore", + exec: function(editor) { editor.selectMore(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "selectNextAfter", + exec: function(editor) { editor.selectMore(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, + scrollIntoView: "cursor", + readOnly: true + }, { + name: "splitIntoLines", + exec: function(editor) { editor.multiSelect.splitIntoLines(); }, + bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"}, + readOnly: true + }, { + name: "alignCursors", + exec: function(editor) { editor.alignCursors(); }, + bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, + scrollIntoView: "cursor" + }, { + name: "findAll", + exec: function(editor) { editor.findAll(); }, + bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, + scrollIntoView: "cursor", + readOnly: true + }]; + exports.multiSelectCommands = [{ + name: "singleSelection", + bindKey: "esc", + exec: function(editor) { editor.exitMultiSelectMode(); }, + scrollIntoView: "cursor", + readOnly: true, + isAvailable: function(editor) {return editor && editor.inMultiSelectMode;} + }]; + + var HashHandler = acequire("../keyboard/hash_handler").HashHandler; + exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); + + }); + + ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(acequire, exports, module) { + + var RangeList = acequire("./range_list").RangeList; + var Range = acequire("./range").Range; + var Selection = acequire("./selection").Selection; + var onMouseDown = acequire("./mouse/multi_select_handler").onMouseDown; + var event = acequire("./lib/event"); + var lang = acequire("./lib/lang"); + var commands = acequire("./commands/multi_select_commands"); + exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); + var Search = acequire("./search").Search; + var search = new Search(); + + function find(session, needle, dir) { + search.$options.wrap = true; + search.$options.needle = needle; + search.$options.backwards = dir == -1; + return search.find(session); + } + var EditSession = acequire("./edit_session").EditSession; + (function() { + this.getSelectionMarkers = function() { + return this.$selectionMarkers; + }; + }).call(EditSession.prototype); + (function() { + this.ranges = null; + this.rangeList = null; + this.addRange = function(range, $blockChangeEvents) { + if (!range) + return; + + if (!this.inMultiSelectMode && this.rangeCount === 0) { + var oldRange = this.toOrientedRange(); + this.rangeList.add(oldRange); + this.rangeList.add(range); + if (this.rangeList.ranges.length != 2) { + this.rangeList.removeAll(); + return $blockChangeEvents || this.fromOrientedRange(range); + } + this.rangeList.removeAll(); + this.rangeList.add(oldRange); + this.$onAddRange(oldRange); + } + + if (!range.cursor) + range.cursor = range.end; + + var removed = this.rangeList.add(range); + + this.$onAddRange(range); + + if (removed.length) + this.$onRemoveRange(removed); + + if (this.rangeCount > 1 && !this.inMultiSelectMode) { + this._signal("multiSelect"); + this.inMultiSelectMode = true; + this.session.$undoSelect = false; + this.rangeList.attach(this.session); + } + + return $blockChangeEvents || this.fromOrientedRange(range); + }; + + this.toSingleRange = function(range) { + range = range || this.ranges[0]; + var removed = this.rangeList.removeAll(); + if (removed.length) + this.$onRemoveRange(removed); + + range && this.fromOrientedRange(range); + }; + this.substractPoint = function(pos) { + var removed = this.rangeList.substractPoint(pos); + if (removed) { + this.$onRemoveRange(removed); + return removed[0]; + } + }; + this.mergeOverlappingRanges = function() { + var removed = this.rangeList.merge(); + if (removed.length) + this.$onRemoveRange(removed); + else if(this.ranges[0]) + this.fromOrientedRange(this.ranges[0]); + }; + + this.$onAddRange = function(range) { + this.rangeCount = this.rangeList.ranges.length; + this.ranges.unshift(range); + this._signal("addRange", {range: range}); + }; + + this.$onRemoveRange = function(removed) { + this.rangeCount = this.rangeList.ranges.length; + if (this.rangeCount == 1 && this.inMultiSelectMode) { + var lastRange = this.rangeList.ranges.pop(); + removed.push(lastRange); + this.rangeCount = 0; + } + + for (var i = removed.length; i--; ) { + var index = this.ranges.indexOf(removed[i]); + this.ranges.splice(index, 1); + } + + this._signal("removeRange", {ranges: removed}); + + if (this.rangeCount === 0 && this.inMultiSelectMode) { + this.inMultiSelectMode = false; + this._signal("singleSelect"); + this.session.$undoSelect = true; + this.rangeList.detach(this.session); + } + + lastRange = lastRange || this.ranges[0]; + if (lastRange && !lastRange.isEqual(this.getRange())) + this.fromOrientedRange(lastRange); + }; + this.$initRangeList = function() { + if (this.rangeList) + return; + + this.rangeList = new RangeList(); + this.ranges = []; + this.rangeCount = 0; + }; + this.getAllRanges = function() { + return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()]; + }; + + this.splitIntoLines = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var range = this.getRange(); + var isBackwards = this.isBackwards(); + var startRow = range.start.row; + var endRow = range.end.row; + if (startRow == endRow) { + if (isBackwards) + var start = range.end, end = range.start; + else + var start = range.start, end = range.end; + + this.addRange(Range.fromPoints(end, end)); + this.addRange(Range.fromPoints(start, start)); + return; + } + + var rectSel = []; + var r = this.getLineRange(startRow, true); + r.start.column = range.start.column; + rectSel.push(r); + + for (var i = startRow + 1; i < endRow; i++) + rectSel.push(this.getLineRange(i, true)); + + r = this.getLineRange(endRow, true); + r.end.column = range.end.column; + rectSel.push(r); + + rectSel.forEach(this.addRange, this); + } + }; + this.toggleBlockSelection = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var cursor = this.session.documentToScreenPosition(this.selectionLead); + var anchor = this.session.documentToScreenPosition(this.selectionAnchor); + + var rectSel = this.rectangularRangeBlock(cursor, anchor); + rectSel.forEach(this.addRange, this); + } + }; + this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { + var rectSel = []; + + var xBackwards = screenCursor.column < screenAnchor.column; + if (xBackwards) { + var startColumn = screenCursor.column; + var endColumn = screenAnchor.column; + var startOffsetX = screenCursor.offsetX; + var endOffsetX = screenAnchor.offsetX; + } else { + var startColumn = screenAnchor.column; + var endColumn = screenCursor.column; + var startOffsetX = screenAnchor.offsetX; + var endOffsetX = screenCursor.offsetX; + } + + var yBackwards = screenCursor.row < screenAnchor.row; + if (yBackwards) { + var startRow = screenCursor.row; + var endRow = screenAnchor.row; + } else { + var startRow = screenAnchor.row; + var endRow = screenCursor.row; + } + + if (startColumn < 0) + startColumn = 0; + if (startRow < 0) + startRow = 0; + + if (startRow == endRow) + includeEmptyLines = true; + + for (var row = startRow; row <= endRow; row++) { + var range = Range.fromPoints( + this.session.screenToDocumentPosition(row, startColumn, startOffsetX), + this.session.screenToDocumentPosition(row, endColumn, endOffsetX) + ); + if (range.isEmpty()) { + if (docEnd && isSamePoint(range.end, docEnd)) + break; + var docEnd = range.end; + } + range.cursor = xBackwards ? range.start : range.end; + rectSel.push(range); + } + + if (yBackwards) + rectSel.reverse(); + + if (!includeEmptyLines) { + var end = rectSel.length - 1; + while (rectSel[end].isEmpty() && end > 0) + end--; + if (end > 0) { + var start = 0; + while (rectSel[start].isEmpty()) + start++; + } + for (var i = end; i >= start; i--) { + if (rectSel[i].isEmpty()) + rectSel.splice(i, 1); + } + } + + return rectSel; + }; + }).call(Selection.prototype); + var Editor = acequire("./editor").Editor; + (function() { + this.updateSelectionMarkers = function() { + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + this.addSelectionMarker = function(orientedRange) { + if (!orientedRange.cursor) + orientedRange.cursor = orientedRange.end; + + var style = this.getSelectionStyle(); + orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style); + + this.session.$selectionMarkers.push(orientedRange); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + return orientedRange; + }; + this.removeSelectionMarker = function(range) { + if (!range.marker) + return; + this.session.removeMarker(range.marker); + var index = this.session.$selectionMarkers.indexOf(range); + if (index != -1) + this.session.$selectionMarkers.splice(index, 1); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + }; + + this.removeSelectionMarkers = function(ranges) { + var markerList = this.session.$selectionMarkers; + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (!range.marker) + continue; + this.session.removeMarker(range.marker); + var index = markerList.indexOf(range); + if (index != -1) + markerList.splice(index, 1); + } + this.session.selectionMarkerCount = markerList.length; + }; + + this.$onAddRange = function(e) { + this.addSelectionMarker(e.range); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onRemoveRange = function(e) { + this.removeSelectionMarkers(e.ranges); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onMultiSelect = function(e) { + if (this.inMultiSelectMode) + return; + this.inMultiSelectMode = true; + + this.setStyle("ace_multiselect"); + this.keyBinding.addKeyboardHandler(commands.keyboardHandler); + this.commands.setDefaultHandler("exec", this.$onMultiSelectExec); + + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onSingleSelect = function(e) { + if (this.session.multiSelect.inVirtualMode) + return; + this.inMultiSelectMode = false; + + this.unsetStyle("ace_multiselect"); + this.keyBinding.removeKeyboardHandler(commands.keyboardHandler); + + this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + this._emit("changeSelection"); + }; + + this.$onMultiSelectExec = function(e) { + var command = e.command; + var editor = e.editor; + if (!editor.multiSelect) + return; + if (!command.multiSelectAction) { + var result = command.exec(editor, e.args || {}); + editor.multiSelect.addRange(editor.multiSelect.toOrientedRange()); + editor.multiSelect.mergeOverlappingRanges(); + } else if (command.multiSelectAction == "forEach") { + result = editor.forEachSelection(command, e.args); + } else if (command.multiSelectAction == "forEachLine") { + result = editor.forEachSelection(command, e.args, true); + } else if (command.multiSelectAction == "single") { + editor.exitMultiSelectMode(); + result = command.exec(editor, e.args || {}); + } else { + result = command.multiSelectAction(editor, e.args || {}); + } + return result; + }; + this.forEachSelection = function(cmd, args, options) { + if (this.inVirtualSelectionMode) + return; + var keepOrder = options && options.keepOrder; + var $byLines = options == true || options && options.$byLines; + var session = this.session; + var selection = this.selection; + var rangeList = selection.rangeList; + var ranges = (keepOrder ? selection : rangeList).ranges; + var result; + + if (!ranges.length) + return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + + var reg = selection._eventRegistry; + selection._eventRegistry = {}; + + var tmpSel = new Selection(session); + this.inVirtualSelectionMode = true; + for (var i = ranges.length; i--;) { + if ($byLines) { + while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row) + i--; + } + tmpSel.fromOrientedRange(ranges[i]); + tmpSel.index = i; + this.selection = session.selection = tmpSel; + var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + if (!result && cmdResult !== undefined) + result = cmdResult; + tmpSel.toOrientedRange(ranges[i]); + } + tmpSel.detach(); + + this.selection = session.selection = selection; + this.inVirtualSelectionMode = false; + selection._eventRegistry = reg; + selection.mergeOverlappingRanges(); + + var anim = this.renderer.$scrollAnimation; + this.onCursorChange(); + this.onSelectionChange(); + if (anim && anim.from == anim.to) + this.renderer.animateScrolling(anim.from); + + return result; + }; + this.exitMultiSelectMode = function() { + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) + return; + this.multiSelect.toSingleRange(); + }; + + this.getSelectedText = function() { + var text = ""; + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var ranges = this.multiSelect.rangeList.ranges; + var buf = []; + for (var i = 0; i < ranges.length; i++) { + buf.push(this.session.getTextRange(ranges[i])); + } + var nl = this.session.getDocument().getNewLineCharacter(); + text = buf.join(nl); + if (text.length == (buf.length - 1) * nl.length) + text = ""; + } else if (!this.selection.isEmpty()) { + text = this.session.getTextRange(this.getSelectionRange()); + } + return text; + }; + + this.$checkMultiselectChange = function(e, anchor) { + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var range = this.multiSelect.ranges[0]; + if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor) + return; + var pos = anchor == this.multiSelect.anchor + ? range.cursor == range.start ? range.end : range.start + : range.cursor; + if (pos.row != anchor.row + || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) + this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); + } + }; + this.findAll = function(needle, options, additive) { + options = options || {}; + options.needle = needle || options.needle; + if (options.needle == undefined) { + var range = this.selection.isEmpty() + ? this.selection.getWordRange() + : this.selection.getRange(); + options.needle = this.session.getTextRange(range); + } + this.$search.set(options); + + var ranges = this.$search.findAll(this.session); + if (!ranges.length) + return 0; + + this.$blockScrolling += 1; + var selection = this.multiSelect; + + if (!additive) + selection.toSingleRange(ranges[0]); + + for (var i = ranges.length; i--; ) + selection.addRange(ranges[i], true); + if (range && selection.rangeList.rangeAtPoint(range.start)) + selection.addRange(range, true); + + this.$blockScrolling -= 1; + + return ranges.length; + }; + this.selectMoreLines = function(dir, skip) { + var range = this.selection.toOrientedRange(); + var isBackwards = range.cursor == range.end; + + var screenLead = this.session.documentToScreenPosition(range.cursor); + if (this.selection.$desiredColumn) + screenLead.column = this.selection.$desiredColumn; + + var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); + + if (!range.isEmpty()) { + var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start); + var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); + } else { + var anchor = lead; + } + + if (isBackwards) { + var newRange = Range.fromPoints(lead, anchor); + newRange.cursor = newRange.start; + } else { + var newRange = Range.fromPoints(anchor, lead); + newRange.cursor = newRange.end; + } + + newRange.desiredColumn = screenLead.column; + if (!this.selection.inMultiSelectMode) { + this.selection.addRange(range); + } else { + if (skip) + var toRemove = range.cursor; + } + + this.selection.addRange(newRange); + if (toRemove) + this.selection.substractPoint(toRemove); + }; + this.transposeSelections = function(dir) { + var session = this.session; + var sel = session.multiSelect; + var all = sel.ranges; + + for (var i = all.length; i--; ) { + var range = all[i]; + if (range.isEmpty()) { + var tmp = session.getWordRange(range.start.row, range.start.column); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + range.end.row = tmp.end.row; + range.end.column = tmp.end.column; + } + } + sel.mergeOverlappingRanges(); + + var words = []; + for (var i = all.length; i--; ) { + var range = all[i]; + words.unshift(session.getTextRange(range)); + } + + if (dir < 0) + words.unshift(words.pop()); + else + words.push(words.shift()); + + for (var i = all.length; i--; ) { + var range = all[i]; + var tmp = range.clone(); + session.replace(range, words[i]); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + } + }; + this.selectMore = function(dir, skip, stopAtFirst) { + var session = this.session; + var sel = session.multiSelect; + + var range = sel.toOrientedRange(); + if (range.isEmpty()) { + range = session.getWordRange(range.start.row, range.start.column); + range.cursor = dir == -1 ? range.start : range.end; + this.multiSelect.addRange(range); + if (stopAtFirst) + return; + } + var needle = session.getTextRange(range); + + var newRange = find(session, needle, dir); + if (newRange) { + newRange.cursor = dir == -1 ? newRange.start : newRange.end; + this.$blockScrolling += 1; + this.session.unfold(newRange); + this.multiSelect.addRange(newRange); + this.$blockScrolling -= 1; + this.renderer.scrollCursorIntoView(null, 0.5); + } + if (skip) + this.multiSelect.substractPoint(range.cursor); + }; + this.alignCursors = function() { + var session = this.session; + var sel = session.multiSelect; + var ranges = sel.ranges; + var row = -1; + var sameRowRanges = ranges.filter(function(r) { + if (r.cursor.row == row) + return true; + row = r.cursor.row; + }); + + if (!ranges.length || sameRowRanges.length == ranges.length - 1) { + var range = this.selection.getRange(); + var fr = range.start.row, lr = range.end.row; + var guessRange = fr == lr; + if (guessRange) { + var max = this.session.getLength(); + var line; + do { + line = this.session.getLine(lr); + } while (/[=:]/.test(line) && ++lr < max); + do { + line = this.session.getLine(fr); + } while (/[=:]/.test(line) && --fr > 0); + + if (fr < 0) fr = 0; + if (lr >= max) lr = max - 1; + } + var lines = this.session.removeFullLines(fr, lr); + lines = this.$reAlignText(lines, guessRange); + this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n"); + if (!guessRange) { + range.start.column = 0; + range.end.column = lines[lines.length - 1].length; + } + this.selection.setRange(range); + } else { + sameRowRanges.forEach(function(r) { + sel.substractPoint(r.cursor); + }); + + var maxCol = 0; + var minSpace = Infinity; + var spaceOffsets = ranges.map(function(r) { + var p = r.cursor; + var line = session.getLine(p.row); + var spaceOffset = line.substr(p.column).search(/\S/g); + if (spaceOffset == -1) + spaceOffset = 0; + + if (p.column > maxCol) + maxCol = p.column; + if (spaceOffset < minSpace) + minSpace = spaceOffset; + return spaceOffset; + }); + ranges.forEach(function(r, i) { + var p = r.cursor; + var l = maxCol - p.column; + var d = spaceOffsets[i] - minSpace; + if (l > d) + session.insert(p, lang.stringRepeat(" ", l - d)); + else + session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); + + r.start.column = r.end.column = maxCol; + r.start.row = r.end.row = p.row; + r.cursor = r.end; + }); + sel.fromOrientedRange(ranges[0]); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + } + }; + + this.$reAlignText = function(lines, forceLeft) { + var isLeftAligned = true, isRightAligned = true; + var startW, textW, endW; + + return lines.map(function(line) { + var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/); + if (!m) + return [line]; + + if (startW == null) { + startW = m[1].length; + textW = m[2].length; + endW = m[3].length; + return m; + } + + if (startW + textW + endW != m[1].length + m[2].length + m[3].length) + isRightAligned = false; + if (startW != m[1].length) + isLeftAligned = false; + + if (startW > m[1].length) + startW = m[1].length; + if (textW < m[2].length) + textW = m[2].length; + if (endW > m[3].length) + endW = m[3].length; + + return m; + }).map(forceLeft ? alignLeft : + isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign); + + function spaces(n) { + return lang.stringRepeat(" ", n); + } + + function alignLeft(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(textW - m[2].length + endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function alignRight(m) { + return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2] + + spaces(endW, " ") + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function unAlign(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + }; + }).call(Editor.prototype); + + + function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; + } + exports.onSessionChange = function(e) { + var session = e.session; + if (session && !session.multiSelect) { + session.$selectionMarkers = []; + session.selection.$initRangeList(); + session.multiSelect = session.selection; + } + this.multiSelect = session && session.multiSelect; + + var oldSession = e.oldSession; + if (oldSession) { + oldSession.multiSelect.off("addRange", this.$onAddRange); + oldSession.multiSelect.off("removeRange", this.$onRemoveRange); + oldSession.multiSelect.off("multiSelect", this.$onMultiSelect); + oldSession.multiSelect.off("singleSelect", this.$onSingleSelect); + oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange); + oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange); + } + + if (session) { + session.multiSelect.on("addRange", this.$onAddRange); + session.multiSelect.on("removeRange", this.$onRemoveRange); + session.multiSelect.on("multiSelect", this.$onMultiSelect); + session.multiSelect.on("singleSelect", this.$onSingleSelect); + session.multiSelect.lead.on("change", this.$checkMultiselectChange); + session.multiSelect.anchor.on("change", this.$checkMultiselectChange); + } + + if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) { + if (session.selection.inMultiSelectMode) + this.$onMultiSelect(); + else + this.$onSingleSelect(); + } + }; + function MultiSelect(editor) { + if (editor.$multiselectOnSessionChange) + return; + editor.$onAddRange = editor.$onAddRange.bind(editor); + editor.$onRemoveRange = editor.$onRemoveRange.bind(editor); + editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); + editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); + editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor); + editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor); + + editor.$multiselectOnSessionChange(editor); + editor.on("changeSession", editor.$multiselectOnSessionChange); + + editor.on("mousedown", onMouseDown); + editor.commands.addCommands(commands.defaultCommands); + + addAltCursorListeners(editor); + } + + function addAltCursorListeners(editor){ + var el = editor.textInput.getElement(); + var altCursor = false; + event.addListener(el, "keydown", function(e) { + var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey); + if (editor.$blockSelectEnabled && altDown) { + if (!altCursor) { + editor.renderer.setMouseCursor("crosshair"); + altCursor = true; + } + } else if (altCursor) { + reset(); + } + }); + + event.addListener(el, "keyup", reset); + event.addListener(el, "blur", reset); + function reset(e) { + if (altCursor) { + editor.renderer.setMouseCursor(""); + altCursor = false; + } + } + } + + exports.MultiSelect = MultiSelect; + + + acequire("./config").defineOptions(Editor.prototype, "editor", { + enableMultiselect: { + set: function(val) { + MultiSelect(this); + if (val) { + this.on("changeSession", this.$multiselectOnSessionChange); + this.on("mousedown", onMouseDown); + } else { + this.off("changeSession", this.$multiselectOnSessionChange); + this.off("mousedown", onMouseDown); + } + }, + value: true + }, + enableBlockSelect: { + set: function(val) { + this.$blockSelectEnabled = val; + }, + value: true + } + }); + + + + }); + + ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../../range").Range; + + var FoldMode = exports.FoldMode = function() {}; + + (function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = session.getFoldWidget(end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + + this.closingBracketBlock = function(session, bracket, row, column, typeRe) { + var end = {row: row, column: column}; + var start = session.$findOpeningBracket(bracket, end); + + if (!start) + return; + + start.column++; + end.column--; + + return Range.fromPoints(start, end); + }; + }).call(FoldMode.prototype); + + }); + + ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(acequire, exports, module) { + "use strict"; + + exports.isDark = false; + exports.cssClass = "ace-tm"; + exports.cssText = ".ace-tm .ace_gutter {\ + background: #f0f0f0;\ + color: #333;\ + }\ + .ace-tm .ace_print-margin {\ + width: 1px;\ + background: #e8e8e8;\ + }\ + .ace-tm .ace_fold {\ + background-color: #6B72E6;\ + }\ + .ace-tm {\ + background-color: #FFFFFF;\ + color: black;\ + }\ + .ace-tm .ace_cursor {\ + color: black;\ + }\ + .ace-tm .ace_invisible {\ + color: rgb(191, 191, 191);\ + }\ + .ace-tm .ace_storage,\ + .ace-tm .ace_keyword {\ + color: blue;\ + }\ + .ace-tm .ace_constant {\ + color: rgb(197, 6, 11);\ + }\ + .ace-tm .ace_constant.ace_buildin {\ + color: rgb(88, 72, 246);\ + }\ + .ace-tm .ace_constant.ace_language {\ + color: rgb(88, 92, 246);\ + }\ + .ace-tm .ace_constant.ace_library {\ + color: rgb(6, 150, 14);\ + }\ + .ace-tm .ace_invalid {\ + background-color: rgba(255, 0, 0, 0.1);\ + color: red;\ + }\ + .ace-tm .ace_support.ace_function {\ + color: rgb(60, 76, 114);\ + }\ + .ace-tm .ace_support.ace_constant {\ + color: rgb(6, 150, 14);\ + }\ + .ace-tm .ace_support.ace_type,\ + .ace-tm .ace_support.ace_class {\ + color: rgb(109, 121, 222);\ + }\ + .ace-tm .ace_keyword.ace_operator {\ + color: rgb(104, 118, 135);\ + }\ + .ace-tm .ace_string {\ + color: rgb(3, 106, 7);\ + }\ + .ace-tm .ace_comment {\ + color: rgb(76, 136, 107);\ + }\ + .ace-tm .ace_comment.ace_doc {\ + color: rgb(0, 102, 255);\ + }\ + .ace-tm .ace_comment.ace_doc.ace_tag {\ + color: rgb(128, 159, 191);\ + }\ + .ace-tm .ace_constant.ace_numeric {\ + color: rgb(0, 0, 205);\ + }\ + .ace-tm .ace_variable {\ + color: rgb(49, 132, 149);\ + }\ + .ace-tm .ace_xml-pe {\ + color: rgb(104, 104, 91);\ + }\ + .ace-tm .ace_entity.ace_name.ace_function {\ + color: #0000A2;\ + }\ + .ace-tm .ace_heading {\ + color: rgb(12, 7, 255);\ + }\ + .ace-tm .ace_list {\ + color:rgb(185, 6, 144);\ + }\ + .ace-tm .ace_meta.ace_tag {\ + color:rgb(0, 22, 142);\ + }\ + .ace-tm .ace_string.ace_regex {\ + color: rgb(255, 0, 0)\ + }\ + .ace-tm .ace_marker-layer .ace_selection {\ + background: rgb(181, 213, 255);\ + }\ + .ace-tm.ace_multiselect .ace_selection.ace_start {\ + box-shadow: 0 0 3px 0px white;\ + }\ + .ace-tm .ace_marker-layer .ace_step {\ + background: rgb(252, 255, 0);\ + }\ + .ace-tm .ace_marker-layer .ace_stack {\ + background: rgb(164, 229, 101);\ + }\ + .ace-tm .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid rgb(192, 192, 192);\ + }\ + .ace-tm .ace_marker-layer .ace_active-line {\ + background: rgba(0, 0, 0, 0.07);\ + }\ + .ace-tm .ace_gutter-active-line {\ + background-color : #dcdcdc;\ + }\ + .ace-tm .ace_marker-layer .ace_selected-word {\ + background: rgb(250, 250, 255);\ + border: 1px solid rgb(200, 200, 250);\ + }\ + .ace-tm .ace_indent-guide {\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ + }\ + "; + + var dom = acequire("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); + }); + + ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("./lib/oop"); + var dom = acequire("./lib/dom"); + var Range = acequire("./range").Range; + + + function LineWidgets(session) { + this.session = session; + this.session.widgetManager = this; + this.session.getRowLength = this.getRowLength; + this.session.$getWidgetScreenLength = this.$getWidgetScreenLength; + this.updateOnChange = this.updateOnChange.bind(this); + this.renderWidgets = this.renderWidgets.bind(this); + this.measureWidgets = this.measureWidgets.bind(this); + this.session._changedWidgets = []; + this.$onChangeEditor = this.$onChangeEditor.bind(this); + + this.session.on("change", this.updateOnChange); + this.session.on("changeFold", this.updateOnFold); + this.session.on("changeEditor", this.$onChangeEditor); + } + + (function() { + this.getRowLength = function(row) { + var h; + if (this.lineWidgets) + h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0; + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + + this.$getWidgetScreenLength = function() { + var screenRows = 0; + this.lineWidgets.forEach(function(w){ + if (w && w.rowCount && !w.hidden) + screenRows += w.rowCount; + }); + return screenRows; + }; + + this.$onChangeEditor = function(e) { + this.attach(e.editor); + }; + + this.attach = function(editor) { + if (editor && editor.widgetManager && editor.widgetManager != this) + editor.widgetManager.detach(); + + if (this.editor == editor) + return; + + this.detach(); + this.editor = editor; + + if (editor) { + editor.widgetManager = this; + editor.renderer.on("beforeRender", this.measureWidgets); + editor.renderer.on("afterRender", this.renderWidgets); + } + }; + this.detach = function(e) { + var editor = this.editor; + if (!editor) + return; + + this.editor = null; + editor.widgetManager = null; + + editor.renderer.off("beforeRender", this.measureWidgets); + editor.renderer.off("afterRender", this.renderWidgets); + var lineWidgets = this.session.lineWidgets; + lineWidgets && lineWidgets.forEach(function(w) { + if (w && w.el && w.el.parentNode) { + w._inDocument = false; + w.el.parentNode.removeChild(w.el); + } + }); + }; + + this.updateOnFold = function(e, session) { + var lineWidgets = session.lineWidgets; + if (!lineWidgets || !e.action) + return; + var fold = e.data; + var start = fold.start.row; + var end = fold.end.row; + var hide = e.action == "add"; + for (var i = start + 1; i < end; i++) { + if (lineWidgets[i]) + lineWidgets[i].hidden = hide; + } + if (lineWidgets[end]) { + if (hide) { + if (!lineWidgets[start]) + lineWidgets[start] = lineWidgets[end]; + else + lineWidgets[end].hidden = hide; + } else { + if (lineWidgets[start] == lineWidgets[end]) + lineWidgets[start] = undefined; + lineWidgets[end].hidden = hide; + } + } + }; + + this.updateOnChange = function(delta) { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + + var startRow = delta.start.row; + var len = delta.end.row - startRow; + + if (len === 0) { + } else if (delta.action == 'remove') { + var removed = lineWidgets.splice(startRow + 1, len); + removed.forEach(function(w) { + w && this.removeLineWidget(w); + }, this); + this.$updateRows(); + } else { + var args = new Array(len); + args.unshift(startRow, 0); + lineWidgets.splice.apply(lineWidgets, args); + this.$updateRows(); + } + }; + + this.$updateRows = function() { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + var noWidgets = true; + lineWidgets.forEach(function(w, i) { + if (w) { + noWidgets = false; + w.row = i; + while (w.$oldWidget) { + w.$oldWidget.row = i; + w = w.$oldWidget; + } + } + }); + if (noWidgets) + this.session.lineWidgets = null; + }; + + this.addLineWidget = function(w) { + if (!this.session.lineWidgets) + this.session.lineWidgets = new Array(this.session.getLength()); + + var old = this.session.lineWidgets[w.row]; + if (old) { + w.$oldWidget = old; + if (old.el && old.el.parentNode) { + old.el.parentNode.removeChild(old.el); + old._inDocument = false; + } + } + + this.session.lineWidgets[w.row] = w; + + w.session = this.session; + + var renderer = this.editor.renderer; + if (w.html && !w.el) { + w.el = dom.createElement("div"); + w.el.innerHTML = w.html; + } + if (w.el) { + dom.addCssClass(w.el, "ace_lineWidgetContainer"); + w.el.style.position = "absolute"; + w.el.style.zIndex = 5; + renderer.container.appendChild(w.el); + w._inDocument = true; + } + + if (!w.coverGutter) { + w.el.style.zIndex = 3; + } + if (w.pixelHeight == null) { + w.pixelHeight = w.el.offsetHeight; + } + if (w.rowCount == null) { + w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight; + } + + var fold = this.session.getFoldAt(w.row, 0); + w.$fold = fold; + if (fold) { + var lineWidgets = this.session.lineWidgets; + if (w.row == fold.end.row && !lineWidgets[fold.start.row]) + lineWidgets[fold.start.row] = w; + else + w.hidden = true; + } + + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + + this.$updateRows(); + this.renderWidgets(null, renderer); + this.onWidgetChanged(w); + return w; + }; + + this.removeLineWidget = function(w) { + w._inDocument = false; + w.session = null; + if (w.el && w.el.parentNode) + w.el.parentNode.removeChild(w.el); + if (w.editor && w.editor.destroy) try { + w.editor.destroy(); + } catch(e){} + if (this.session.lineWidgets) { + var w1 = this.session.lineWidgets[w.row]; + if (w1 == w) { + this.session.lineWidgets[w.row] = w.$oldWidget; + if (w.$oldWidget) + this.onWidgetChanged(w.$oldWidget); + } else { + while (w1) { + if (w1.$oldWidget == w) { + w1.$oldWidget = w.$oldWidget; + break; + } + w1 = w1.$oldWidget; + } + } + } + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + this.$updateRows(); + }; + + this.getWidgetsAtRow = function(row) { + var lineWidgets = this.session.lineWidgets; + var w = lineWidgets && lineWidgets[row]; + var list = []; + while (w) { + list.push(w); + w = w.$oldWidget; + } + return list; + }; + + this.onWidgetChanged = function(w) { + this.session._changedWidgets.push(w); + this.editor && this.editor.renderer.updateFull(); + }; + + this.measureWidgets = function(e, renderer) { + var changedWidgets = this.session._changedWidgets; + var config = renderer.layerConfig; + + if (!changedWidgets || !changedWidgets.length) return; + var min = Infinity; + for (var i = 0; i < changedWidgets.length; i++) { + var w = changedWidgets[i]; + if (!w || !w.el) continue; + if (w.session != this.session) continue; + if (!w._inDocument) { + if (this.session.lineWidgets[w.row] != w) + continue; + w._inDocument = true; + renderer.container.appendChild(w.el); + } + + w.h = w.el.offsetHeight; + + if (!w.fixedWidth) { + w.w = w.el.offsetWidth; + w.screenWidth = Math.ceil(w.w / config.characterWidth); + } + + var rowCount = w.h / config.lineHeight; + if (w.coverLine) { + rowCount -= this.session.getRowLineCount(w.row); + if (rowCount < 0) + rowCount = 0; + } + if (w.rowCount != rowCount) { + w.rowCount = rowCount; + if (w.row < min) + min = w.row; + } + } + if (min != Infinity) { + this.session._emit("changeFold", {data:{start:{row: min}}}); + this.session.lineWidgetWidth = null; + } + this.session._changedWidgets = []; + }; + + this.renderWidgets = function(e, renderer) { + var config = renderer.layerConfig; + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) + return; + var first = Math.min(this.firstRow, config.firstRow); + var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length); + + while (first > 0 && !lineWidgets[first]) + first--; + + this.firstRow = config.firstRow; + this.lastRow = config.lastRow; + + renderer.$cursorLayer.config = config; + for (var i = first; i <= last; i++) { + var w = lineWidgets[i]; + if (!w || !w.el) continue; + if (w.hidden) { + w.el.style.top = -100 - (w.pixelHeight || 0) + "px"; + continue; + } + if (!w._inDocument) { + w._inDocument = true; + renderer.container.appendChild(w.el); + } + var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top; + if (!w.coverLine) + top += config.lineHeight * this.session.getRowLineCount(w.row); + w.el.style.top = top - config.offset + "px"; + + var left = w.coverGutter ? 0 : renderer.gutterWidth; + if (!w.fixedWidth) + left -= renderer.scrollLeft; + w.el.style.left = left + "px"; + + if (w.fullWidth && w.screenWidth) { + w.el.style.minWidth = config.width + 2 * config.padding + "px"; + } + + if (w.fixedWidth) { + w.el.style.right = renderer.scrollBar.getWidth() + "px"; + } else { + w.el.style.right = ""; + } + } + }; + + }).call(LineWidgets.prototype); + + + exports.LineWidgets = LineWidgets; + + }); + + ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(acequire, exports, module) { + "use strict"; + var LineWidgets = acequire("../line_widgets").LineWidgets; + var dom = acequire("../lib/dom"); + var Range = acequire("../range").Range; + + function binarySearch(array, needle, comparator) { + var first = 0; + var last = array.length - 1; + + while (first <= last) { + var mid = (first + last) >> 1; + var c = comparator(needle, array[mid]); + if (c > 0) + first = mid + 1; + else if (c < 0) + last = mid - 1; + else + return mid; + } + return -(first + 1); + } + + function findAnnotations(session, row, dir) { + var annotations = session.getAnnotations().sort(Range.comparePoints); + if (!annotations.length) + return; + + var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints); + if (i < 0) + i = -i - 1; + + if (i >= annotations.length) + i = dir > 0 ? 0 : annotations.length - 1; + else if (i === 0 && dir < 0) + i = annotations.length - 1; + + var annotation = annotations[i]; + if (!annotation || !dir) + return; + + if (annotation.row === row) { + do { + annotation = annotations[i += dir]; + } while (annotation && annotation.row === row); + if (!annotation) + return annotations.slice(); + } + + + var matched = []; + row = annotation.row; + do { + matched[dir < 0 ? "unshift" : "push"](annotation); + annotation = annotations[i += dir]; + } while (annotation && annotation.row == row); + return matched.length && matched; + } + + exports.showErrorMarker = function(editor, dir) { + var session = editor.session; + if (!session.widgetManager) { + session.widgetManager = new LineWidgets(session); + session.widgetManager.attach(editor); + } + + var pos = editor.getCursorPosition(); + var row = pos.row; + var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) { + return w.type == "errorMarker"; + })[0]; + if (oldWidget) { + oldWidget.destroy(); + } else { + row -= dir; + } + var annotations = findAnnotations(session, row, dir); + var gutterAnno; + if (annotations) { + var annotation = annotations[0]; + pos.column = (annotation.pos && typeof annotation.column != "number" + ? annotation.pos.sc + : annotation.column) || 0; + pos.row = annotation.row; + gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row]; + } else if (oldWidget) { + return; + } else { + gutterAnno = { + text: ["Looks good!"], + className: "ace_ok" + }; + } + editor.session.unfold(pos.row); + editor.selection.moveToPosition(pos); + + var w = { + row: pos.row, + fixedWidth: true, + coverGutter: true, + el: dom.createElement("div"), + type: "errorMarker" + }; + var el = w.el.appendChild(dom.createElement("div")); + var arrow = w.el.appendChild(dom.createElement("div")); + arrow.className = "error_widget_arrow " + gutterAnno.className; + + var left = editor.renderer.$cursorLayer + .getPixelPosition(pos).left; + arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px"; + + w.el.className = "error_widget_wrapper"; + el.className = "error_widget " + gutterAnno.className; + el.innerHTML = gutterAnno.text.join("
"); + + el.appendChild(dom.createElement("div")); + + var kb = function(_, hashId, keyString) { + if (hashId === 0 && (keyString === "esc" || keyString === "return")) { + w.destroy(); + return {command: "null"}; + } + }; + + w.destroy = function() { + if (editor.$mouseHandler.isMousePressed) + return; + editor.keyBinding.removeKeyboardHandler(kb); + session.widgetManager.removeLineWidget(w); + editor.off("changeSelection", w.destroy); + editor.off("changeSession", w.destroy); + editor.off("mouseup", w.destroy); + editor.off("change", w.destroy); + }; + + editor.keyBinding.addKeyboardHandler(kb); + editor.on("changeSelection", w.destroy); + editor.on("changeSession", w.destroy); + editor.on("mouseup", w.destroy); + editor.on("change", w.destroy); + + editor.session.widgetManager.addLineWidget(w); + + w.el.onmousedown = editor.focus.bind(editor); + + editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight}); + }; + + + dom.importCssString("\ + .error_widget_wrapper {\ + background: inherit;\ + color: inherit;\ + border:none\ + }\ + .error_widget {\ + border-top: solid 2px;\ + border-bottom: solid 2px;\ + margin: 5px 0;\ + padding: 10px 40px;\ + white-space: pre-wrap;\ + }\ + .error_widget.ace_error, .error_widget_arrow.ace_error{\ + border-color: #ff5a5a\ + }\ + .error_widget.ace_warning, .error_widget_arrow.ace_warning{\ + border-color: #F1D817\ + }\ + .error_widget.ace_info, .error_widget_arrow.ace_info{\ + border-color: #5a5a5a\ + }\ + .error_widget.ace_ok, .error_widget_arrow.ace_ok{\ + border-color: #5aaa5a\ + }\ + .error_widget_arrow {\ + position: absolute;\ + border: solid 5px;\ + border-top-color: transparent!important;\ + border-right-color: transparent!important;\ + border-left-color: transparent!important;\ + top: -5px;\ + }\ + ", ""); + + }); + + ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(acequire, exports, module) { + "use strict"; + + acequire("./lib/fixoldbrowsers"); + + var dom = acequire("./lib/dom"); + var event = acequire("./lib/event"); + + var Editor = acequire("./editor").Editor; + var EditSession = acequire("./edit_session").EditSession; + var UndoManager = acequire("./undomanager").UndoManager; + var Renderer = acequire("./virtual_renderer").VirtualRenderer; + acequire("./worker/worker_client"); + acequire("./keyboard/hash_handler"); + acequire("./placeholder"); + acequire("./multi_select"); + acequire("./mode/folding/fold_mode"); + acequire("./theme/textmate"); + acequire("./ext/error_marker"); + + exports.config = acequire("./config"); + exports.acequire = acequire; + + if (true) + exports.define = __webpack_require__(67); + exports.edit = function(el) { + if (typeof el == "string") { + var _id = el; + el = document.getElementById(_id); + if (!el) + throw new Error("ace.edit can't find div #" + _id); + } + + if (el && el.env && el.env.editor instanceof Editor) + return el.env.editor; + + var value = ""; + if (el && /input|textarea/i.test(el.tagName)) { + var oldNode = el; + value = oldNode.value; + el = dom.createElement("pre"); + oldNode.parentNode.replaceChild(el, oldNode); + } else if (el) { + value = dom.getInnerText(el); + el.innerHTML = ""; + } + + var doc = exports.createEditSession(value); + + var editor = new Editor(new Renderer(el)); + editor.setSession(doc); + + var env = { + document: doc, + editor: editor, + onResize: editor.resize.bind(editor, null) + }; + if (oldNode) env.textarea = oldNode; + event.addListener(window, "resize", env.onResize); + editor.on("destroy", function() { + event.removeListener(window, "resize", env.onResize); + env.editor.container.env = null; // prevent memory leak on old ie + }); + editor.container.env = editor.env = env; + return editor; + }; + exports.createEditSession = function(text, mode) { + var doc = new EditSession(text, mode); + doc.setUndoManager(new UndoManager()); + return doc; + }; + exports.EditSession = EditSession; + exports.UndoManager = UndoManager; + exports.version = "1.2.9"; + }); + (function() { + ace.acequire(["ace/ace"], function(a) { + if (a) { + a.config.init(true); + a.define = ace.define; + } + if (!window.ace) + window.ace = a; + for (var key in a) if (a.hasOwnProperty(key)) + window.ace[key] = a[key]; + }); + })(); + + module.exports = window.ace.acequire("ace/ace"); + +/***/ }, +/* 67 */ +/***/ function(module, exports) { + + module.exports = function() { throw new Error("define cannot be used indirect"); }; + + +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { + + ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules; + + var JsonHighlightRules = function() { + this.$rules = { + "start" : [ + { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { + token : "string", // single line + regex : '"', + next : "string" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "text", // single quoted strings are not allowed + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "comment", // comments are not allowed, but who cares? + regex : "\\/\\/.*$" + }, { + token : "comment.start", // comments are not allowed, but who cares? + regex : "\\/\\*", + next : "comment" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ + }, { + token : "string", + regex : '"|$', + next : "start" + }, { + defaultToken : "string" + } + ], + "comment" : [ + { + token : "comment.end", // comments are not allowed, but who cares? + regex : "\\*\\/", + next : "start" + }, { + defaultToken: "comment" + } + ] + }; + + }; + + oop.inherits(JsonHighlightRules, TextHighlightRules); + + exports.JsonHighlightRules = JsonHighlightRules; + }); + + ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(acequire, exports, module) { + "use strict"; + + var Range = acequire("../range").Range; + + var MatchingBraceOutdent = function() {}; + + (function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + }).call(MatchingBraceOutdent.prototype); + + exports.MatchingBraceOutdent = MatchingBraceOutdent; + }); + + ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../../lib/oop"); + var Range = acequire("../../range").Range; + var BaseFoldMode = acequire("./fold_mode").FoldMode; + + var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } + }; + oop.inherits(FoldMode, BaseFoldMode); + + (function() { + + this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + + }).call(FoldMode.prototype); + + }); + + ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"], function(acequire, exports, module) { + "use strict"; + + var oop = acequire("../lib/oop"); + var TextMode = acequire("./text").Mode; + var HighlightRules = acequire("./json_highlight_rules").JsonHighlightRules; + var MatchingBraceOutdent = acequire("./matching_brace_outdent").MatchingBraceOutdent; + var CstyleBehaviour = acequire("./behaviour/cstyle").CstyleBehaviour; + var CStyleFoldMode = acequire("./folding/cstyle").FoldMode; + var WorkerClient = acequire("../worker/worker_client").WorkerClient; + + var Mode = function() { + this.HighlightRules = HighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); + }; + oop.inherits(Mode, TextMode); + + (function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], __webpack_require__(69), "JsonWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + + this.$id = "ace/mode/json"; + }).call(Mode.prototype); + + exports.Mode = Mode; + }); + + +/***/ }, +/* 69 */ +/***/ function(module, exports) { + + module.exports.id = 'ace/mode/json_worker'; + module.exports.src = "\"no use strict\";!function(window){function resolveModuleId(id,paths){for(var testPath=id,tail=\"\";testPath;){var alias=paths[testPath];if(\"string\"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,\"/\")+(tail||alias.main||alias.name);if(alias===!1)return\"\";var i=testPath.lastIndexOf(\"/\");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:\"log\",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:\"error\",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf(\"!\")){var chunks=moduleName.split(\"!\");return window.normalizeModule(parentId,chunks[0])+\"!\"+window.normalizeModule(parentId,chunks[1])}if(\".\"==moduleName.charAt(0)){var base=parentId.split(\"/\").slice(0,-1).join(\"/\");for(moduleName=(base?base+\"/\":\"\")+moduleName;-1!==moduleName.indexOf(\".\")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,\"\").replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error(\"worker.js acequire() accepts only (parentId, id) as arguments\");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log(\"unable to load \"+id);var path=resolveModuleId(id,window.acequire.tlns);return\".js\"!=path.slice(-3)&&(path+=\".js\"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,\"string\"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),\"function\"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=[\"require\",\"exports\",\"module\"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case\"require\":return req;case\"exports\":return module.exports;case\"module\":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire(\"ace/lib/event_emitter\").EventEmitter,oop=window.acequire(\"ace/lib/oop\"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:\"call\",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:\"event\",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error(\"Unknown command:\"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire(\"ace/lib/es5-shim\"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}}(this),ace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){\"object\"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){\"object\"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||\"\";switch(delta.action){case\"insert\":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case\"remove\":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){\"object\"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?\"unshift\":\"push\"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal(\"change\",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(acequire,exports){\"use strict\";var oop=acequire(\"./lib/oop\"),applyDelta=acequire(\"./apply_delta\").applyDelta,EventEmitter=acequire(\"./lib/event_emitter\").EventEmitter,Range=acequire(\"./range\").Range,Anchor=acequire(\"./anchor\").Anchor,Document=function(textOrLines){this.$lines=[\"\"],0===textOrLines.length?this.$lines=[\"\"]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0===\"aaa\".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal(\"changeNewLineMode\"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return\"\\r\\n\"==text||\"\\r\"==text||\"\\n\"==text},this.getLine=function(row){return this.$lines[row]||\"\"},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||\"\").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(position,[\"\",\"\"])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:\"insert\",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([\"\"]),column=0):(lines=[\"\"].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:\"insert\",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:\"remove\",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:\"remove\",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert=\"insert\"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal(\"change\",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(\"\"),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:\"insert\"==delta.action?\"remove\":\"insert\",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(acequire,exports){\"use strict\";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split(\"\").reverse().join(\"\")},exports.stringRepeat=function(string,count){for(var result=\"\";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,\"\")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,\"\")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&\"object\"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if(\"object\"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}if(\"[object Object]\"!==Object.prototype.toString.call(obj))return obj;copy={};for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},exports.escapeHTML=function(str){return str.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(/'/g,\"'\").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:\"insert\",start:data[i],lines:data[i+1]};else var d={action:\"remove\",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define(\"ace/mode/json/json_parse\",[\"require\",\"exports\",\"module\"],function(){\"use strict\";var at,ch,text,value,escapee={'\"':'\"',\"\\\\\":\"\\\\\",\"/\":\"/\",b:\"\\b\",f:\"\\f\",n:\"\\n\",r:\"\\r\",t:\"\t\"},error=function(m){throw{name:\"SyntaxError\",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error(\"Expected '\"+c+\"' instead of '\"+ch+\"'\"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string=\"\";for(\"-\"===ch&&(string=\"-\",next(\"-\"));ch>=\"0\"&&\"9\">=ch;)string+=ch,next();if(\".\"===ch)for(string+=\".\";next()&&ch>=\"0\"&&\"9\">=ch;)string+=ch;if(\"e\"===ch||\"E\"===ch)for(string+=ch,next(),(\"-\"===ch||\"+\"===ch)&&(string+=ch,next());ch>=\"0\"&&\"9\">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error(\"Bad number\"),void 0):number},string=function(){var hex,i,uffff,string=\"\";if('\"'===ch)for(;next();){if('\"'===ch)return next(),string;if(\"\\\\\"===ch)if(next(),\"u\"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if(\"string\"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error(\"Bad string\")},white=function(){for(;ch&&\" \">=ch;)next()},word=function(){switch(ch){case\"t\":return next(\"t\"),next(\"r\"),next(\"u\"),next(\"e\"),!0;case\"f\":return next(\"f\"),next(\"a\"),next(\"l\"),next(\"s\"),next(\"e\"),!1;case\"n\":return next(\"n\"),next(\"u\"),next(\"l\"),next(\"l\"),null}error(\"Unexpected '\"+ch+\"'\")},array=function(){var array=[];if(\"[\"===ch){if(next(\"[\"),white(),\"]\"===ch)return next(\"]\"),array;for(;ch;){if(array.push(value()),white(),\"]\"===ch)return next(\"]\"),array;next(\",\"),white()}}error(\"Bad array\")},object=function(){var key,object={};if(\"{\"===ch){if(next(\"{\"),white(),\"}\"===ch)return next(\"}\"),object;for(;ch;){if(key=string(),white(),next(\":\"),Object.hasOwnProperty.call(object,key)&&error('Duplicate key \"'+key+'\"'),object[key]=value(),white(),\"}\"===ch)return next(\"}\"),object;next(\",\"),white()}}error(\"Bad object\")};return value=function(){switch(white(),ch){case\"{\":return object();case\"[\":return array();case'\"':return string();case\"-\":return number();default:return ch>=\"0\"&&\"9\">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=\" \",result=value(),white(),ch&&error(\"Syntax error\"),\"function\"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&\"object\"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({\"\":result},\"\"):result}}),ace.define(\"ace/mode/json_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/json/json_parse\"],function(acequire,exports){\"use strict\";var oop=acequire(\"../lib/oop\"),Mirror=acequire(\"../worker/mirror\").Mirror,parse=acequire(\"./json/json_parse\"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:\"error\"})}this.sender.emit(\"annotate\",errors)}}.call(JsonWorker.prototype)}),ace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,\"sentinel\",{}),\"sentinel\"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if(\"function\"!=typeof target)throw new TypeError(\"Function.prototype.bind called on incompatible \"+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,\"__defineGetter__\"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,\"XXX\"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return\"[object Array]\"==_toString(obj)});var boxedString=Object(\"a\"),splitString=\"a\"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,result=[],thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0,thisp=arguments[1];if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduce of empty array with no initial value\");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError(\"reduce of empty array with no initial value\")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):object,length=self.length>>>0;if(\"[object Function]\"!=_toString(fun))throw new TypeError(fun+\" is not a function\");if(!length&&1==arguments.length)throw new TypeError(\"reduceRight of empty array with no initial value\");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError(\"reduceRight of empty array with no initial value\")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&\"[object String]\"==_toString(this)?this.split(\"\"):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(object,property){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if(\"object\"!=typeof prototype)throw new TypeError(\"typeof prototype[\"+typeof prototype+\"] != 'object'\");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom=\"undefined\"==typeof document||doesDefinePropertyWork(document.createElement(\"div\"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR=\"Property description must be an object: \",ERR_NON_OBJECT_TARGET=\"Object.defineProperty called on non-object: \",ERR_ACCESSORS_NOT_SUPPORTED=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(object,property,descriptor){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if(\"object\"!=typeof descriptor&&\"function\"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,\"value\"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,\"get\")&&defineGetter(object,property,descriptor.get),owns(descriptor,\"set\")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return\"function\"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name=\"\";owns(object,name);)name+=\"?\";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if(\"object\"!=typeof object&&\"function\"!=typeof object||null===object)throw new TypeError(\"Object.keys called on a non-object\");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=\"\t\\n\u000b\\f\\r   ᠎              \\u2028\\u2029\";if(!String.prototype.trim||ws.trim()){ws=\"[\"+ws+\"]\";var trimBeginRegexp=RegExp(\"^\"+ws+ws+\"*\"),trimEndRegexp=RegExp(ws+ws+\"*$\");String.prototype.trim=function(){return(this+\"\").replace(trimBeginRegexp,\"\").replace(trimEndRegexp,\"\")}}var toObject=function(o){if(null==o)throw new TypeError(\"can't convert \"+o+\" to object\");return Object(o)}});"; + +/***/ }, +/* 70 */ +/***/ function(module, exports) { + + ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(acequire, exports, module) { + "use strict"; + + var dom = acequire("../lib/dom"); + var lang = acequire("../lib/lang"); + var event = acequire("../lib/event"); + var searchboxCss = "\ + .ace_search {\ + background-color: #ddd;\ + color: #666;\ + border: 1px solid #cbcbcb;\ + border-top: 0 none;\ + overflow: hidden;\ + margin: 0;\ + padding: 4px 6px 0 4px;\ + position: absolute;\ + top: 0;\ + z-index: 99;\ + white-space: normal;\ + }\ + .ace_search.left {\ + border-left: 0 none;\ + border-radius: 0px 0px 5px 0px;\ + left: 0;\ + }\ + .ace_search.right {\ + border-radius: 0px 0px 0px 5px;\ + border-right: 0 none;\ + right: 0;\ + }\ + .ace_search_form, .ace_replace_form {\ + margin: 0 20px 4px 0;\ + overflow: hidden;\ + line-height: 1.9;\ + }\ + .ace_replace_form {\ + margin-right: 0;\ + }\ + .ace_search_form.ace_nomatch {\ + outline: 1px solid red;\ + }\ + .ace_search_field {\ + border-radius: 3px 0 0 3px;\ + background-color: white;\ + color: black;\ + border: 1px solid #cbcbcb;\ + border-right: 0 none;\ + box-sizing: border-box!important;\ + outline: 0;\ + padding: 0;\ + font-size: inherit;\ + margin: 0;\ + line-height: inherit;\ + padding: 0 6px;\ + min-width: 17em;\ + vertical-align: top;\ + }\ + .ace_searchbtn {\ + border: 1px solid #cbcbcb;\ + line-height: inherit;\ + display: inline-block;\ + padding: 0 6px;\ + background: #fff;\ + border-right: 0 none;\ + border-left: 1px solid #dcdcdc;\ + cursor: pointer;\ + margin: 0;\ + position: relative;\ + box-sizing: content-box!important;\ + color: #666;\ + }\ + .ace_searchbtn:last-child {\ + border-radius: 0 3px 3px 0;\ + border-right: 1px solid #cbcbcb;\ + }\ + .ace_searchbtn:disabled {\ + background: none;\ + cursor: default;\ + }\ + .ace_searchbtn:hover {\ + background-color: #eef1f6;\ + }\ + .ace_searchbtn.prev, .ace_searchbtn.next {\ + padding: 0px 0.7em\ + }\ + .ace_searchbtn.prev:after, .ace_searchbtn.next:after {\ + content: \"\";\ + border: solid 2px #888;\ + width: 0.5em;\ + height: 0.5em;\ + border-width: 2px 0 0 2px;\ + display:inline-block;\ + transform: rotate(-45deg);\ + }\ + .ace_searchbtn.next:after {\ + border-width: 0 2px 2px 0 ;\ + }\ + .ace_searchbtn_close {\ + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ + border-radius: 50%;\ + border: 0 none;\ + color: #656565;\ + cursor: pointer;\ + font: 16px/16px Arial;\ + padding: 0;\ + height: 14px;\ + width: 14px;\ + top: 9px;\ + right: 7px;\ + position: absolute;\ + }\ + .ace_searchbtn_close:hover {\ + background-color: #656565;\ + background-position: 50% 100%;\ + color: white;\ + }\ + .ace_button {\ + margin-left: 2px;\ + cursor: pointer;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + overflow: hidden;\ + opacity: 0.7;\ + border: 1px solid rgba(100,100,100,0.23);\ + padding: 1px;\ + box-sizing: border-box!important;\ + color: black;\ + }\ + .ace_button:hover {\ + background-color: #eee;\ + opacity:1;\ + }\ + .ace_button:active {\ + background-color: #ddd;\ + }\ + .ace_button.checked {\ + border-color: #3399ff;\ + opacity:1;\ + }\ + .ace_search_options{\ + margin-bottom: 3px;\ + text-align: right;\ + -webkit-user-select: none;\ + -moz-user-select: none;\ + -o-user-select: none;\ + -ms-user-select: none;\ + user-select: none;\ + clear: both;\ + }\ + .ace_search_counter {\ + float: left;\ + font-family: arial;\ + padding: 0 8px;\ + }"; + var HashHandler = acequire("../keyboard/hash_handler").HashHandler; + var keyUtil = acequire("../lib/keys"); + + var MAX_COUNT = 999; + + dom.importCssString(searchboxCss, "ace_searchbox"); + + var html = ''.replace(/> +/g, ">"); + + var SearchBox = function(editor, range, showReplaceForm) { + var div = dom.createElement("div"); + div.innerHTML = html; + this.element = div.firstChild; + + this.setSession = this.setSession.bind(this); + + this.$init(); + this.setEditor(editor); + }; + + (function() { + this.setEditor = function(editor) { + editor.searchBox = this; + editor.renderer.scroller.appendChild(this.element); + this.editor = editor; + }; + + this.setSession = function(e) { + this.searchRange = null; + this.$syncOptions(true); + }; + + this.$initElements = function(sb) { + this.searchBox = sb.querySelector(".ace_search_form"); + this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOption = sb.querySelector("[action=searchInSelection]"); + this.replaceOption = sb.querySelector("[action=toggleReplace]"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); + this.searchInput = this.searchBox.querySelector(".ace_search_field"); + this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); + this.searchCounter = sb.querySelector(".ace_search_counter"); + }; + + this.$init = function() { + var sb = this.element; + + this.$initElements(sb); + + var _this = this; + event.addListener(sb, "mousedown", function(e) { + setTimeout(function(){ + _this.activeInput.focus(); + }, 0); + event.stopPropagation(e); + }); + event.addListener(sb, "click", function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute("action"); + if (action && _this[action]) + _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); + event.stopPropagation(e); + }); + + event.addCommandKeyListener(sb, function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); + if (command && command.exec) { + command.exec(_this); + event.stopEvent(e); + } + }); + + this.$onChange = lang.delayedCall(function() { + _this.find(false, false); + }); + + event.addListener(this.searchInput, "input", function() { + _this.$onChange.schedule(20); + }); + event.addListener(this.searchInput, "focus", function() { + _this.activeInput = _this.searchInput; + _this.searchInput.value && _this.highlight(); + }); + event.addListener(this.replaceInput, "focus", function() { + _this.activeInput = _this.replaceInput; + _this.searchInput.value && _this.highlight(); + }); + }; + this.$closeSearchBarKb = new HashHandler([{ + bindKey: "Esc", + name: "closeSearchBar", + exec: function(editor) { + editor.searchBox.hide(); + } + }]); + this.$searchBarKb = new HashHandler(); + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f": function(sb) { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? "" : "none"; + sb.replaceOption.checked = false; + sb.$syncOptions(); + sb.searchInput.focus(); + }, + "Ctrl-H|Command-Option-F": function(sb) { + sb.replaceOption.checked = true; + sb.$syncOptions(); + sb.replaceInput.focus(); + }, + "Ctrl-G|Command-G": function(sb) { + sb.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function(sb) { + sb.findPrev(); + }, + "esc": function(sb) { + setTimeout(function() { sb.hide();}); + }, + "Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + "Shift-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + "Tab": function(sb) { + (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); + } + }); + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleReplace", + exec: function(sb) { + sb.replaceOption.checked = !sb.replaceOption.checked; + sb.$syncOptions(); + } + }, { + name: "searchInSelection", + exec: function(sb) { + sb.searchOption.checked = !sb.searchRange; + sb.setSearchRange(sb.searchOption.checked && sb.editor.getSelectionRange()); + sb.$syncOptions(); + } + }]); + + this.setSearchRange = function(range) { + this.searchRange = range; + if (range) { + this.searchRangeMarker = this.editor.session.addMarker(range, "ace_active-line"); + } else if (this.searchRangeMarker) { + this.editor.session.removeMarker(this.searchRangeMarker); + this.searchRangeMarker = null; + } + }; + + this.$syncOptions = function(preventScroll) { + dom.setCssClass(this.replaceOption, "checked", this.searchRange); + dom.setCssClass(this.searchOption, "checked", this.searchOption.checked); + this.replaceOption.textContent = this.replaceOption.checked ? "-" : "+"; + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.replaceBox.style.display = this.replaceOption.checked ? "" : "none"; + this.find(false, false, preventScroll); + }; + + this.highlight = function(re) { + this.editor.session.highlight(re || this.editor.$search.$options.re); + this.editor.renderer.updateBackMarkers(); + }; + this.find = function(skipCurrent, backwards, preventScroll) { + var range = this.editor.find(this.searchInput.value, { + skipCurrent: skipCurrent, + backwards: backwards, + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked, + preventScroll: preventScroll, + range: this.searchRange + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.updateCounter(); + }; + this.updateCounter = function() { + var editor = this.editor; + var regex = editor.$search.$options.re; + var all = 0; + var before = 0; + if (regex) { + var value = this.searchRange + ? editor.session.getTextRange(this.searchRange) + : editor.getValue(); + + var offset = editor.session.doc.positionToIndex(editor.selection.anchor); + if (this.searchRange) + offset -= editor.session.doc.positionToIndex(this.searchRange.start); + + var last = regex.lastIndex = 0; + var m; + while ((m = regex.exec(value))) { + all++; + last = m.index; + if (last <= offset) + before++; + if (all > MAX_COUNT) + break; + if (!m[0]) { + regex.lastIndex = last += 1; + if (last >= value.length) + break; + } + } + } + this.searchCounter.textContent = before + " of " + (all > MAX_COUNT ? MAX_COUNT + "+" : all); + }; + this.findNext = function() { + this.find(true, false); + }; + this.findPrev = function() { + this.find(true, true); + }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; + this.replace = function() { + if (!this.editor.getReadOnly()) + this.editor.replace(this.replaceInput.value); + }; + this.replaceAndFindNext = function() { + if (!this.editor.getReadOnly()) { + this.editor.replace(this.replaceInput.value); + this.findNext(); + } + }; + this.replaceAll = function() { + if (!this.editor.getReadOnly()) + this.editor.replaceAll(this.replaceInput.value); + }; + + this.hide = function() { + this.active = false; + this.setSearchRange(null); + this.editor.off("changeSession", this.setSession); + + this.element.style.display = "none"; + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); + this.editor.focus(); + }; + this.show = function(value, isReplace) { + this.active = true; + this.editor.on("changeSession", this.setSession); + this.element.style.display = ""; + this.replaceOption.checked = isReplace; + + if (value) + this.searchInput.value = value; + + this.searchInput.focus(); + this.searchInput.select(); + + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); + + this.$syncOptions(true); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + }; + }).call(SearchBox.prototype); + + exports.SearchBox = SearchBox; + + exports.Search = function(editor, isReplace) { + var sb = editor.searchBox || new SearchBox(editor); + sb.show(editor.session.getTextRange(), isReplace); + }; + + }); + (function() { + ace.acequire(["ace/ext/searchbox"], function() {}); + })(); + + +/***/ }, +/* 71 */ +/***/ function(module, exports) { + + /* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + + ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { + + exports.isDark = false; + exports.cssClass = "ace-jsoneditor"; + exports.cssText = ".ace-jsoneditor .ace_gutter {\ + background: #ebebeb;\ + color: #333\ + }\ + \ + .ace-jsoneditor.ace_editor {\ + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\ + line-height: 1.3;\ + background-color: #fff;\ + }\ + .ace-jsoneditor .ace_print-margin {\ + width: 1px;\ + background: #e8e8e8\ + }\ + .ace-jsoneditor .ace_scroller {\ + background-color: #FFFFFF\ + }\ + .ace-jsoneditor .ace_text-layer {\ + color: gray\ + }\ + .ace-jsoneditor .ace_variable {\ + color: #1a1a1a\ + }\ + .ace-jsoneditor .ace_cursor {\ + border-left: 2px solid #000000\ + }\ + .ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ + border-left: 0px;\ + border-bottom: 1px solid #000000\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selection {\ + background: lightgray\ + }\ + .ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ + box-shadow: 0 0 3px 0px #FFFFFF;\ + border-radius: 2px\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_step {\ + background: rgb(255, 255, 0)\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_bracket {\ + margin: -1px 0 0 -1px;\ + border: 1px solid #BFBFBF\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_active-line {\ + background: #FFFBD1\ + }\ + .ace-jsoneditor .ace_gutter-active-line {\ + background-color : #dcdcdc\ + }\ + .ace-jsoneditor .ace_marker-layer .ace_selected-word {\ + border: 1px solid lightgray\ + }\ + .ace-jsoneditor .ace_invisible {\ + color: #BFBFBF\ + }\ + .ace-jsoneditor .ace_keyword,\ + .ace-jsoneditor .ace_meta,\ + .ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ + color: #AF956F\ + }\ + .ace-jsoneditor .ace_keyword.ace_operator {\ + color: #484848\ + }\ + .ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ + color: #96DC5F\ + }\ + .ace-jsoneditor .ace_constant.ace_language {\ + color: darkorange\ + }\ + .ace-jsoneditor .ace_constant.ace_numeric {\ + color: red\ + }\ + .ace-jsoneditor .ace_constant.ace_character.ace_entity {\ + color: #BF78CC\ + }\ + .ace-jsoneditor .ace_invalid {\ + color: #FFFFFF;\ + background-color: #FF002A;\ + }\ + .ace-jsoneditor .ace_fold {\ + background-color: #AF956F;\ + border-color: #000000\ + }\ + .ace-jsoneditor .ace_storage,\ + .ace-jsoneditor .ace_support.ace_class,\ + .ace-jsoneditor .ace_support.ace_function,\ + .ace-jsoneditor .ace_support.ace_other,\ + .ace-jsoneditor .ace_support.ace_type {\ + color: #C52727\ + }\ + .ace-jsoneditor .ace_string {\ + color: green\ + }\ + .ace-jsoneditor .ace_comment {\ + color: #BCC8BA\ + }\ + .ace-jsoneditor .ace_entity.ace_name.ace_tag,\ + .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ + color: #606060\ + }\ + .ace-jsoneditor .ace_markup.ace_underline {\ + text-decoration: underline\ + }\ + .ace-jsoneditor .ace_indent-guide {\ + background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ + }"; + + var dom = acequire("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); + }); + + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/main/webapp/modules/core/langs/translation-en.json b/main/webapp/modules/core/langs/translation-en.json index 07ce3d8b7..b04e73197 100644 --- a/main/webapp/modules/core/langs/translation-en.json +++ b/main/webapp/modules/core/langs/translation-en.json @@ -79,6 +79,7 @@ "warning-data-file": "You must specify a data file to import.", "uploading-data": "Uploading data ...", "web-address": "Web Addresses (URLs)", + "data-package": "Data Package (JSON URL)", "warning-web-address": "You must specify a web address (URL) to import.", "downloading-data": "Downloading data ...", "clipboard": "Clipboard", @@ -101,6 +102,7 @@ "name": "Name", "rename": "Rename", "edit-meta-data": "About", + "edit-data-package": "Data package", "creator": "Creator", "contributors": "Contributors", "subject": "Subject", @@ -331,6 +333,7 @@ "clear-selection": "Clear selection in all facets", "remove-all": "Remove all facets", "export-project": "Export project", + "project-data-package": "Project data package", "tab-value": "Tab-separated value", "comma-sep": "Comma-separated value", "html-table": "HTML table", @@ -575,6 +578,7 @@ "next": "next", "last": "last", "all": "All", + "table-schema-validate": "Validate", "facet-star": "Facet by star", "starred-rows": "Starred Rows", "facet-flag": "Facet by flag", diff --git a/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js b/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js index 07c245e1c..ed336bec2 100644 --- a/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js +++ b/main/webapp/modules/core/scripts/index/default-importing-controller/file-selection-panel.js @@ -158,7 +158,9 @@ Refine.DefaultImportingController.prototype._renderFileSelectionPanelFileTable = } self._updateFileSelectionSummary(); }); - if (fileRecord.selected) { + if (fileRecord.metaDataFormat) { + checkbox.removeAttr("checked").attr("disabled", "disabled"); + } else if (fileRecord.selected) { // Initial selection determined on server side. checkbox.attr("checked", "checked"); self._selectedMap[fileRecord.location] = fileRecord; diff --git a/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html b/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html new file mode 100644 index 000000000..638e0cd84 --- /dev/null +++ b/main/webapp/modules/core/scripts/index/default-importing-sources/import-from-data-package-form.html @@ -0,0 +1,7 @@ +
+ + + + + +
\ No newline at end of file diff --git a/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js b/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js index 59e5c62f0..ed7b75190 100644 --- a/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js +++ b/main/webapp/modules/core/scripts/index/default-importing-sources/sources.js @@ -128,4 +128,37 @@ ClipboardImportingSourceUI.prototype.attachUI = function(bodyDiv) { ClipboardImportingSourceUI.prototype.focus = function() { this._elmts.textInput.focus(); -}; \ No newline at end of file +}; + +// data package source: +function DataPackageImportingSourceUI(controller) { + this._controller = controller; + } + Refine.DefaultImportingController.sources.push({ + "label": $.i18n._('core-index-import')["data-package"], + "id": "data-package", + "uiClass": DataPackageImportingSourceUI + }); + + DataPackageImportingSourceUI.prototype.attachUI = function(bodyDiv) { + var self = this; + + bodyDiv.html(DOM.loadHTML("core", "scripts/index/default-importing-sources/import-from-data-package-form.html")); + + this._elmts = DOM.bind(bodyDiv); + + $('#or-import-enterurl').text($.i18n._('core-index-import')["enter-url"]); + this._elmts.nextButton.html($.i18n._('core-buttons')["next"]); + + this._elmts.nextButton.click(function(evt) { + if ($.trim(self._elmts.urlInput[0].value).length === 0) { + window.alert($.i18n._('core-index-import')["warning-web-address"]); + } else { + self._controller.startImportJob(self._elmts.form, $.i18n._('core-index-import')["data-package"]); + } + }); + }; + + DataPackageImportingSourceUI.prototype.focus = function() { + this._elmts.urlInput.focus(); + }; diff --git a/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js b/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js index 2fb0f08d2..88eb674d5 100644 --- a/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js +++ b/main/webapp/modules/core/scripts/index/edit-metadata-dialog.js @@ -12,24 +12,23 @@ function EditMetadataDialog(metaData, targetRowElem) { } var td0 = tr.insertCell(0); - - var keyLable = $.i18n._('core-index')[key] || key; - $(td0).text(keyLable); var td1 = tr.insertCell(1); - $(td1).text((value !== null) ? value : ""); + var keyLable = $.i18n._('core-index')[key] || key; + $(td1).text(keyLable); var td2 = tr.insertCell(2); + $(td2).text((value !== null) ? value : ""); if(key==="tags"){ - $('