From a6465c4ed5b7e27f975d0c32172b444ff3bec06b Mon Sep 17 00:00:00 2001 From: Lauren McCarthy Date: Tue, 19 Mar 2019 12:26:06 -0700 Subject: [PATCH 01/36] adding korean translation base --- Gruntfile.js | 6 + package.json | 1 + .../ko/00_Structure/00_Coordinates.js | 39 + .../ko/00_Structure/01_Width_and_Height.js | 20 + .../ko/00_Structure/02_Setup_and_Draw.js | 27 + .../examples/ko/00_Structure/03_No_Loop.js | 30 + src/data/examples/ko/00_Structure/04_Loop.js | 26 + .../examples/ko/00_Structure/05_Redraw.js | 33 + .../examples/ko/00_Structure/06_Functions.js | 28 + .../examples/ko/00_Structure/07_Recursion.js | 27 + .../ko/00_Structure/08_Create_Graphics.js | 29 + .../ko/01_Form/00_Points_and_Lines.js | 36 + .../ko/01_Form/01_Shape_Primitives.js | 31 + src/data/examples/ko/01_Form/02_Pie_Chart.js | 34 + .../examples/ko/01_Form/03_Regular_Polygon.js | 43 + src/data/examples/ko/01_Form/04_Star.js | 46 + .../examples/ko/01_Form/05_Triangle_Strip.js | 38 + src/data/examples/ko/01_Form/06_Bezier.js | 28 + .../examples/ko/01_Form/07_3D_Primitives.js | 30 + src/data/examples/ko/02_Data/00_Variables.js | 37 + .../examples/ko/02_Data/01_True_and_False.js | 31 + .../examples/ko/02_Data/03_Variable_Scope.js | 48 + src/data/examples/ko/02_Data/04_Numbers.js | 31 + src/data/examples/ko/03_Arrays/00_Array.js | 44 + src/data/examples/ko/03_Arrays/01_Array_2d.js | 38 + .../examples/ko/03_Arrays/02_Array_Objects.js | 71 + .../examples/ko/04_Control/00_Iteration.js | 41 + .../ko/04_Control/01_Embedded_Iteration.js | 21 + .../ko/04_Control/02_Conditionals_1.js | 26 + .../ko/04_Control/03_Conditionals_2.js | 28 + .../ko/04_Control/04_Logical_Operators.js | 42 + .../ko/05_Image/00_Load_and_Display_Image.js | 22 + .../ko/05_Image/01_Background_Image.js | 31 + .../examples/ko/05_Image/02_Transparency.js | 25 + .../examples/ko/05_Image/03_Alpha_Mask.js | 28 + .../examples/ko/05_Image/04_Create_Image.js | 25 + .../examples/ko/05_Image/05_Pointillism.js | 34 + src/data/examples/ko/07_Color/00_Hue.js | 25 + .../examples/ko/07_Color/01_Saturation.js | 25 + .../examples/ko/07_Color/02_Brightness.js | 46 + .../ko/07_Color/03_Color_Variables.js | 40 + .../examples/ko/07_Color/04_Relativity.js | 34 + .../ko/07_Color/05_Linear_Gradient.js | 52 + .../ko/07_Color/06_Radial_Gradient.js | 33 + .../examples/ko/07_Color/07_Lerp_Color.js | 49 + .../ko/08_Math/00_incrementdecrement.js | 42 + .../ko/08_Math/01_operatorprecedence.js | 54 + src/data/examples/ko/08_Math/02_distance1d.js | 65 + src/data/examples/ko/08_Math/03_distance2d.js | 25 + src/data/examples/ko/08_Math/04_sine.js | 27 + src/data/examples/ko/08_Math/05_sincosine.js | 43 + src/data/examples/ko/08_Math/06_sinewave.js | 48 + .../examples/ko/08_Math/07_additivewave.js | 70 + .../ko/08_Math/08_polartocartesian.js | 44 + src/data/examples/ko/08_Math/09_arctangent.js | 45 + .../examples/ko/08_Math/10_Interpolate.js | 34 + .../examples/ko/08_Math/11_doubleRandom.js | 24 + src/data/examples/ko/08_Math/12_random.js | 19 + src/data/examples/ko/08_Math/13_noise1D.js | 31 + src/data/examples/ko/08_Math/14_noisewave.js | 42 + src/data/examples/ko/08_Math/15_Noise2D.js | 42 + src/data/examples/ko/08_Math/16_Noise3D.js | 48 + .../examples/ko/08_Math/17_Randomchords.js | 35 + src/data/examples/ko/08_Math/18_Map.js | 22 + src/data/examples/ko/09_Simulate/00_Forces.js | 148 ++ .../ko/09_Simulate/01_ParticleSystem.js | 69 + .../examples/ko/09_Simulate/02_Flocking.js | 229 +++ .../examples/ko/09_Simulate/03_WolframCA.js | 73 + .../examples/ko/09_Simulate/04_GameOfLife.js | 94 + .../09_Simulate/05_MultipleParticleSystems.js | 138 ++ .../examples/ko/09_Simulate/06_Spirograph.js | 73 + .../examples/ko/09_Simulate/07_LSystems.js | 106 + src/data/examples/ko/09_Simulate/08_Spring.js | 92 + .../examples/ko/09_Simulate/09_Springs.js | 147 ++ .../examples/ko/09_Simulate/10_SoftBody.js | 110 ++ .../ko/09_Simulate/11_SmokeParticleSystem.js | 180 ++ .../ko/09_Simulate/12_BrownianMotion.js | 46 + src/data/examples/ko/09_Simulate/13_Chain.js | 55 + .../09_Simulate/14_SnowflakeParticleSystem.js | 63 + .../ko/09_Simulate/15_penrose_tiles.js | 125 ++ .../ko/09_Simulate/16_Recursive_Tree.js | 55 + .../examples/ko/09_Simulate/17_Mandelbrot.js | 86 + .../examples/ko/10_Interaction/10_Tickle.js | 48 + .../examples/ko/10_Interaction/20_Follow1.js | 37 + .../examples/ko/10_Interaction/21_Follow2.js | 39 + .../examples/ko/10_Interaction/22_Follow3.js | 47 + .../examples/ko/10_Interaction/23_snake.js | 172 ++ .../ko/10_Interaction/24_Wavemaker.js | 37 + .../examples/ko/10_Interaction/25_reach1.js | 57 + .../examples/ko/10_Interaction/26_reach2.js | 65 + .../examples/ko/10_Interaction/27_reach3.js | 81 + src/data/examples/ko/11_Objects/01_Objects.js | 39 + .../ko/11_Objects/02_Multiple_Objects.js | 50 + .../ko/11_Objects/03_Objects_Array.js | 42 + .../03_Objects_Optional_Arguments.js | 65 + .../examples/ko/11_Objects/04_Inheritance.js | 71 + .../examples/ko/12_Lights/02_Directional.js | 27 + src/data/examples/ko/12_Lights/05_Mixture.js | 26 + .../13_Motion/01_non_orthogonal_reflection.js | 110 ++ .../examples/ko/13_Motion/02_Linear_Motion.js | 24 + src/data/examples/ko/13_Motion/03_Bounce.js | 44 + .../ko/13_Motion/04_Bouncy_Bubbles.js | 95 + src/data/examples/ko/13_Motion/05_Morph.js | 93 + .../ko/13_Motion/06_Moving_On_Curves.js | 47 + .../ko/15_Instance_Mode/01_Instantiating.js | 35 + .../15_Instance_Mode/02_Instance_Container.js | 94 + .../examples/ko/16_Dom/03_Input_Button.js | 41 + src/data/examples/ko/16_Dom/04_Slider.js | 33 + src/data/examples/ko/16_Dom/07_Modify_DOM.js | 56 + src/data/examples/ko/16_Dom/08_Video.js | 31 + .../examples/ko/16_Dom/09_Video_Canvas.js | 28 + .../examples/ko/16_Dom/10_Video_Pixels.js | 33 + src/data/examples/ko/16_Dom/11_Capture.js | 25 + src/data/examples/ko/16_Dom/12_Drop.js | 36 + .../ko/17_Drawing/00_Continuous_Lines.js | 15 + src/data/examples/ko/17_Drawing/01_Pattern.js | 27 + src/data/examples/ko/17_Drawing/02_Pulses.js | 31 + .../examples/ko/18_Transform/00_Translate.js | 40 + src/data/examples/ko/18_Transform/01_Scale.js | 46 + .../examples/ko/18_Transform/02_Rotate.js | 43 + src/data/examples/ko/18_Transform/03_Arm.js | 49 + .../examples/ko/19_Typography/00_Letters.js | 64 + .../examples/ko/19_Typography/01_Words.js | 59 + src/data/examples/ko/20_3D/00_geometries.js | 60 + .../examples/ko/20_3D/01_sine_cosine_in_3D.js | 28 + .../examples/ko/20_3D/02_multiple_lights.js | 30 + src/data/examples/ko/20_3D/03_materials.js | 65 + src/data/examples/ko/20_3D/04_textures.js | 40 + .../examples/ko/20_3D/07_orbit_control.js | 36 + src/data/examples/ko/21_Input/00_Clock.js | 62 + src/data/examples/ko/21_Input/01_Constrain.js | 36 + src/data/examples/ko/21_Input/02_Easing.js | 30 + src/data/examples/ko/21_Input/03_Keyboard.js | 38 + src/data/examples/ko/21_Input/04_Mouse1D.js | 24 + src/data/examples/ko/21_Input/05_Mouse2D.js | 20 + .../examples/ko/21_Input/06_MouseIsPressed.js | 20 + .../ko/21_Input/07_Mouse_Functions.js | 66 + .../examples/ko/21_Input/08_Mouse_Signals.js | 52 + .../examples/ko/21_Input/09_Storing_Input.js | 38 + .../ko/22_Advanced_Data/00_Load_Saved_JSON.js | 104 + .../ko/33_Sound/00_Load_and_Play_Sound.js | 25 + .../examples/ko/33_Sound/01_Preload_Sound.js | 34 + .../examples/ko/33_Sound/02_soundFormats.js | 54 + src/data/examples/ko/33_Sound/03_Play_Mode.js | 42 + .../examples/ko/33_Sound/04_Pan_SoundFile.js | 34 + .../examples/ko/33_Sound/05_Sound_Effect.js | 68 + .../ko/33_Sound/06_Manipulate_Sound.js | 49 + .../ko/33_Sound/07_Amplitude_Analysis.js | 50 + .../examples/ko/33_Sound/08_Noise_Envelope.js | 54 + .../examples/ko/33_Sound/09_Note_Envelope.js | 61 + .../ko/33_Sound/10_Oscillator_Waveform.js | 40 + .../examples/ko/33_Sound/11_Live_Input.js | 36 + .../examples/ko/33_Sound/12_FFT_Spectrum.js | 30 + .../examples/ko/33_Sound/13_Mic_Threshold.js | 49 + .../examples/ko/33_Sound/14_Filter_LowPass.js | 62 + .../ko/33_Sound/15_Filter_BandPass.js | 51 + src/data/examples/ko/33_Sound/16_Delay.js | 56 + src/data/examples/ko/33_Sound/17_Reverb.js | 36 + .../ko/33_Sound/18_Convolution_Reverb.js | 87 + .../examples/ko/33_Sound/19_Record_Save.js | 58 + .../examples/ko/33_Sound/21_FreqModulation.js | 148 ++ .../ko/33_Sound/22_AmplitudeModulation.js | 95 + .../35_Mobile/00_Acceleration_Ball_Bounce.js | 58 + .../examples/ko/35_Mobile/01_Simple_Draw.js | 15 + .../ko/35_Mobile/02_Acceleration_Color.js | 24 + .../ko/35_Mobile/03_Shake_Ball_Bounce.js | 114 ++ .../examples/ko/35_Mobile/04_Tilted_3D_Box.js | 15 + src/data/examples/ko/90_Hello_P5/01_shapes.js | 28 + .../ko/90_Hello_P5/02_interactivity.js | 40 + .../ko/90_Hello_P5/03_interactivity.js | 29 + .../examples/ko/90_Hello_P5/04_animate.js | 33 + .../examples/ko/90_Hello_P5/04_flocking.js | 185 ++ .../examples/ko/90_Hello_P5/05_weather.js | 73 + .../examples/ko/90_Hello_P5/06_drawing.js | 132 ++ src/data/examples/ko/90_Hello_P5/07_song.js | 119 ++ src/data/ko.yml | 501 +++++ src/data/reference/ko.json | 1726 +++++++++++++++++ src/templates/pages/reference/index.hbs | 2 +- 178 files changed, 11291 insertions(+), 1 deletion(-) create mode 100644 src/data/examples/ko/00_Structure/00_Coordinates.js create mode 100644 src/data/examples/ko/00_Structure/01_Width_and_Height.js create mode 100644 src/data/examples/ko/00_Structure/02_Setup_and_Draw.js create mode 100644 src/data/examples/ko/00_Structure/03_No_Loop.js create mode 100644 src/data/examples/ko/00_Structure/04_Loop.js create mode 100644 src/data/examples/ko/00_Structure/05_Redraw.js create mode 100644 src/data/examples/ko/00_Structure/06_Functions.js create mode 100644 src/data/examples/ko/00_Structure/07_Recursion.js create mode 100644 src/data/examples/ko/00_Structure/08_Create_Graphics.js create mode 100644 src/data/examples/ko/01_Form/00_Points_and_Lines.js create mode 100644 src/data/examples/ko/01_Form/01_Shape_Primitives.js create mode 100644 src/data/examples/ko/01_Form/02_Pie_Chart.js create mode 100644 src/data/examples/ko/01_Form/03_Regular_Polygon.js create mode 100644 src/data/examples/ko/01_Form/04_Star.js create mode 100644 src/data/examples/ko/01_Form/05_Triangle_Strip.js create mode 100644 src/data/examples/ko/01_Form/06_Bezier.js create mode 100644 src/data/examples/ko/01_Form/07_3D_Primitives.js create mode 100644 src/data/examples/ko/02_Data/00_Variables.js create mode 100644 src/data/examples/ko/02_Data/01_True_and_False.js create mode 100644 src/data/examples/ko/02_Data/03_Variable_Scope.js create mode 100644 src/data/examples/ko/02_Data/04_Numbers.js create mode 100644 src/data/examples/ko/03_Arrays/00_Array.js create mode 100644 src/data/examples/ko/03_Arrays/01_Array_2d.js create mode 100644 src/data/examples/ko/03_Arrays/02_Array_Objects.js create mode 100644 src/data/examples/ko/04_Control/00_Iteration.js create mode 100644 src/data/examples/ko/04_Control/01_Embedded_Iteration.js create mode 100644 src/data/examples/ko/04_Control/02_Conditionals_1.js create mode 100644 src/data/examples/ko/04_Control/03_Conditionals_2.js create mode 100644 src/data/examples/ko/04_Control/04_Logical_Operators.js create mode 100644 src/data/examples/ko/05_Image/00_Load_and_Display_Image.js create mode 100644 src/data/examples/ko/05_Image/01_Background_Image.js create mode 100644 src/data/examples/ko/05_Image/02_Transparency.js create mode 100644 src/data/examples/ko/05_Image/03_Alpha_Mask.js create mode 100644 src/data/examples/ko/05_Image/04_Create_Image.js create mode 100644 src/data/examples/ko/05_Image/05_Pointillism.js create mode 100644 src/data/examples/ko/07_Color/00_Hue.js create mode 100644 src/data/examples/ko/07_Color/01_Saturation.js create mode 100644 src/data/examples/ko/07_Color/02_Brightness.js create mode 100644 src/data/examples/ko/07_Color/03_Color_Variables.js create mode 100644 src/data/examples/ko/07_Color/04_Relativity.js create mode 100644 src/data/examples/ko/07_Color/05_Linear_Gradient.js create mode 100644 src/data/examples/ko/07_Color/06_Radial_Gradient.js create mode 100644 src/data/examples/ko/07_Color/07_Lerp_Color.js create mode 100644 src/data/examples/ko/08_Math/00_incrementdecrement.js create mode 100644 src/data/examples/ko/08_Math/01_operatorprecedence.js create mode 100644 src/data/examples/ko/08_Math/02_distance1d.js create mode 100644 src/data/examples/ko/08_Math/03_distance2d.js create mode 100644 src/data/examples/ko/08_Math/04_sine.js create mode 100644 src/data/examples/ko/08_Math/05_sincosine.js create mode 100644 src/data/examples/ko/08_Math/06_sinewave.js create mode 100644 src/data/examples/ko/08_Math/07_additivewave.js create mode 100644 src/data/examples/ko/08_Math/08_polartocartesian.js create mode 100644 src/data/examples/ko/08_Math/09_arctangent.js create mode 100644 src/data/examples/ko/08_Math/10_Interpolate.js create mode 100644 src/data/examples/ko/08_Math/11_doubleRandom.js create mode 100644 src/data/examples/ko/08_Math/12_random.js create mode 100644 src/data/examples/ko/08_Math/13_noise1D.js create mode 100644 src/data/examples/ko/08_Math/14_noisewave.js create mode 100644 src/data/examples/ko/08_Math/15_Noise2D.js create mode 100644 src/data/examples/ko/08_Math/16_Noise3D.js create mode 100644 src/data/examples/ko/08_Math/17_Randomchords.js create mode 100644 src/data/examples/ko/08_Math/18_Map.js create mode 100644 src/data/examples/ko/09_Simulate/00_Forces.js create mode 100644 src/data/examples/ko/09_Simulate/01_ParticleSystem.js create mode 100644 src/data/examples/ko/09_Simulate/02_Flocking.js create mode 100644 src/data/examples/ko/09_Simulate/03_WolframCA.js create mode 100644 src/data/examples/ko/09_Simulate/04_GameOfLife.js create mode 100644 src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js create mode 100644 src/data/examples/ko/09_Simulate/06_Spirograph.js create mode 100644 src/data/examples/ko/09_Simulate/07_LSystems.js create mode 100644 src/data/examples/ko/09_Simulate/08_Spring.js create mode 100644 src/data/examples/ko/09_Simulate/09_Springs.js create mode 100644 src/data/examples/ko/09_Simulate/10_SoftBody.js create mode 100644 src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js create mode 100755 src/data/examples/ko/09_Simulate/12_BrownianMotion.js create mode 100644 src/data/examples/ko/09_Simulate/13_Chain.js create mode 100755 src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js create mode 100644 src/data/examples/ko/09_Simulate/15_penrose_tiles.js create mode 100644 src/data/examples/ko/09_Simulate/16_Recursive_Tree.js create mode 100644 src/data/examples/ko/09_Simulate/17_Mandelbrot.js create mode 100644 src/data/examples/ko/10_Interaction/10_Tickle.js create mode 100644 src/data/examples/ko/10_Interaction/20_Follow1.js create mode 100644 src/data/examples/ko/10_Interaction/21_Follow2.js create mode 100644 src/data/examples/ko/10_Interaction/22_Follow3.js create mode 100644 src/data/examples/ko/10_Interaction/23_snake.js create mode 100644 src/data/examples/ko/10_Interaction/24_Wavemaker.js create mode 100644 src/data/examples/ko/10_Interaction/25_reach1.js create mode 100644 src/data/examples/ko/10_Interaction/26_reach2.js create mode 100644 src/data/examples/ko/10_Interaction/27_reach3.js create mode 100644 src/data/examples/ko/11_Objects/01_Objects.js create mode 100644 src/data/examples/ko/11_Objects/02_Multiple_Objects.js create mode 100644 src/data/examples/ko/11_Objects/03_Objects_Array.js create mode 100644 src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js create mode 100644 src/data/examples/ko/11_Objects/04_Inheritance.js create mode 100755 src/data/examples/ko/12_Lights/02_Directional.js create mode 100644 src/data/examples/ko/12_Lights/05_Mixture.js create mode 100644 src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js create mode 100644 src/data/examples/ko/13_Motion/02_Linear_Motion.js create mode 100644 src/data/examples/ko/13_Motion/03_Bounce.js create mode 100644 src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js create mode 100644 src/data/examples/ko/13_Motion/05_Morph.js create mode 100644 src/data/examples/ko/13_Motion/06_Moving_On_Curves.js create mode 100644 src/data/examples/ko/15_Instance_Mode/01_Instantiating.js create mode 100644 src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js create mode 100644 src/data/examples/ko/16_Dom/03_Input_Button.js create mode 100644 src/data/examples/ko/16_Dom/04_Slider.js create mode 100644 src/data/examples/ko/16_Dom/07_Modify_DOM.js create mode 100644 src/data/examples/ko/16_Dom/08_Video.js create mode 100644 src/data/examples/ko/16_Dom/09_Video_Canvas.js create mode 100644 src/data/examples/ko/16_Dom/10_Video_Pixels.js create mode 100644 src/data/examples/ko/16_Dom/11_Capture.js create mode 100644 src/data/examples/ko/16_Dom/12_Drop.js create mode 100644 src/data/examples/ko/17_Drawing/00_Continuous_Lines.js create mode 100644 src/data/examples/ko/17_Drawing/01_Pattern.js create mode 100644 src/data/examples/ko/17_Drawing/02_Pulses.js create mode 100644 src/data/examples/ko/18_Transform/00_Translate.js create mode 100644 src/data/examples/ko/18_Transform/01_Scale.js create mode 100644 src/data/examples/ko/18_Transform/02_Rotate.js create mode 100644 src/data/examples/ko/18_Transform/03_Arm.js create mode 100644 src/data/examples/ko/19_Typography/00_Letters.js create mode 100644 src/data/examples/ko/19_Typography/01_Words.js create mode 100644 src/data/examples/ko/20_3D/00_geometries.js create mode 100644 src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js create mode 100644 src/data/examples/ko/20_3D/02_multiple_lights.js create mode 100644 src/data/examples/ko/20_3D/03_materials.js create mode 100644 src/data/examples/ko/20_3D/04_textures.js create mode 100644 src/data/examples/ko/20_3D/07_orbit_control.js create mode 100644 src/data/examples/ko/21_Input/00_Clock.js create mode 100644 src/data/examples/ko/21_Input/01_Constrain.js create mode 100644 src/data/examples/ko/21_Input/02_Easing.js create mode 100644 src/data/examples/ko/21_Input/03_Keyboard.js create mode 100644 src/data/examples/ko/21_Input/04_Mouse1D.js create mode 100644 src/data/examples/ko/21_Input/05_Mouse2D.js create mode 100644 src/data/examples/ko/21_Input/06_MouseIsPressed.js create mode 100644 src/data/examples/ko/21_Input/07_Mouse_Functions.js create mode 100644 src/data/examples/ko/21_Input/08_Mouse_Signals.js create mode 100644 src/data/examples/ko/21_Input/09_Storing_Input.js create mode 100644 src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js create mode 100644 src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js create mode 100644 src/data/examples/ko/33_Sound/01_Preload_Sound.js create mode 100644 src/data/examples/ko/33_Sound/02_soundFormats.js create mode 100644 src/data/examples/ko/33_Sound/03_Play_Mode.js create mode 100644 src/data/examples/ko/33_Sound/04_Pan_SoundFile.js create mode 100644 src/data/examples/ko/33_Sound/05_Sound_Effect.js create mode 100644 src/data/examples/ko/33_Sound/06_Manipulate_Sound.js create mode 100644 src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js create mode 100644 src/data/examples/ko/33_Sound/08_Noise_Envelope.js create mode 100644 src/data/examples/ko/33_Sound/09_Note_Envelope.js create mode 100644 src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js create mode 100644 src/data/examples/ko/33_Sound/11_Live_Input.js create mode 100644 src/data/examples/ko/33_Sound/12_FFT_Spectrum.js create mode 100644 src/data/examples/ko/33_Sound/13_Mic_Threshold.js create mode 100644 src/data/examples/ko/33_Sound/14_Filter_LowPass.js create mode 100644 src/data/examples/ko/33_Sound/15_Filter_BandPass.js create mode 100644 src/data/examples/ko/33_Sound/16_Delay.js create mode 100644 src/data/examples/ko/33_Sound/17_Reverb.js create mode 100644 src/data/examples/ko/33_Sound/18_Convolution_Reverb.js create mode 100644 src/data/examples/ko/33_Sound/19_Record_Save.js create mode 100644 src/data/examples/ko/33_Sound/21_FreqModulation.js create mode 100644 src/data/examples/ko/33_Sound/22_AmplitudeModulation.js create mode 100644 src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js create mode 100644 src/data/examples/ko/35_Mobile/01_Simple_Draw.js create mode 100644 src/data/examples/ko/35_Mobile/02_Acceleration_Color.js create mode 100644 src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js create mode 100644 src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js create mode 100644 src/data/examples/ko/90_Hello_P5/01_shapes.js create mode 100644 src/data/examples/ko/90_Hello_P5/02_interactivity.js create mode 100644 src/data/examples/ko/90_Hello_P5/03_interactivity.js create mode 100644 src/data/examples/ko/90_Hello_P5/04_animate.js create mode 100644 src/data/examples/ko/90_Hello_P5/04_flocking.js create mode 100644 src/data/examples/ko/90_Hello_P5/05_weather.js create mode 100644 src/data/examples/ko/90_Hello_P5/06_drawing.js create mode 100644 src/data/examples/ko/90_Hello_P5/07_song.js create mode 100644 src/data/ko.yml create mode 100644 src/data/reference/ko.json diff --git a/Gruntfile.js b/Gruntfile.js index 8a14a87b83..82a0f3225d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -243,6 +243,12 @@ module.exports = function(grunt) { src: ['**'], dest: '<%= config.dist %>/es/reference' }, + reference_ko: { + expand: true, + cwd: '<%= config.dist %>/reference', + src: ['**'], + dest: '<%= config.dist %>/ko/reference' + }, reference_zh_Hans: { expand: true, cwd: '<%= config.dist %>/reference', diff --git a/package.json b/package.json index 7fdadc6e52..ff63f72767 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "languages": [ "en", "es", + "ko", "zh-Hans" ], "homepage": "https://github.com/processing/p5.js-website", diff --git a/src/data/examples/ko/00_Structure/00_Coordinates.js b/src/data/examples/ko/00_Structure/00_Coordinates.js new file mode 100644 index 0000000000..b783e1c093 --- /dev/null +++ b/src/data/examples/ko/00_Structure/00_Coordinates.js @@ -0,0 +1,39 @@ +/* + * @name Coordinates + * @description All shapes drawn to the screen have a position that is + * specified as a coordinate. All coordinates are measured as the distance from + * the origin in units of pixels. The origin [0, 0] is the coordinate in the + * upper left of the window and the coordinate in the lower right is [width-1, + * height-1]. + */ +function setup() { + // Sets the screen to be 720 pixels wide and 400 pixels high + createCanvas(720, 400); +} + +function draw() { + // Set the background to black and turn off the fill color + background(0); + noFill(); + + // The two parameters of the point() method each specify + // coordinates. + // The first parameter is the x-coordinate and the second is the Y + stroke(255); + point(width * 0.5, height * 0.5); + point(width * 0.5, height * 0.25); + + // Coordinates are used for drawing all shapes, not just points. + // Parameters for different functions are used for different + // purposes. For example, the first two parameters to line() + // specify the coordinates of the first endpoint and the second + // two parameters specify the second endpoint + stroke(0, 153, 255); + line(0, height * 0.33, width, height * 0.33); + + // By default, the first two parameters to rect() are the + // coordinates of the upper-left corner and the second pair + // is the width and height + stroke(255, 153, 0); + rect(width * 0.25, height * 0.1, width * 0.5, height * 0.8); +} diff --git a/src/data/examples/ko/00_Structure/01_Width_and_Height.js b/src/data/examples/ko/00_Structure/01_Width_and_Height.js new file mode 100644 index 0000000000..2c98de592e --- /dev/null +++ b/src/data/examples/ko/00_Structure/01_Width_and_Height.js @@ -0,0 +1,20 @@ +/* + * @name Width and Height + * @description The 'width' and 'height' variables contain the + * width and height of the display window as defined in the createCanvas() + * function. + */ +function setup() { + createCanvas(720, 400); +} + +function draw() { + background(127); + noStroke(); + for (let i = 0; i < height; i += 20) { + fill(129, 206, 15); + rect(0, i, width, 10); + fill(255); + rect(i, 0, 10, height); + } +} diff --git a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js new file mode 100644 index 0000000000..4f20978143 --- /dev/null +++ b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js @@ -0,0 +1,27 @@ +/* + * @name Setup and Draw + * @description The code inside the draw() function runs continuously from top + * to bottom until the program is stopped. + */ +let y = 100; + +// The statements in the setup() function +// execute once when the program begins +function setup() { + // createCanvas must be the first statement + createCanvas(720, 400); + stroke(255); // Set line drawing color to white + frameRate(30); +} +// The statements in draw() are executed until the +// program is stopped. Each statement is executed in +// sequence and after the last line is read, the first +// line is executed again. +function draw() { + background(0); // Set the background to black + y = y - 1; + if (y < 0) { + y = height; + } + line(0, y, width, y); +} diff --git a/src/data/examples/ko/00_Structure/03_No_Loop.js b/src/data/examples/ko/00_Structure/03_No_Loop.js new file mode 100644 index 0000000000..063073be5e --- /dev/null +++ b/src/data/examples/ko/00_Structure/03_No_Loop.js @@ -0,0 +1,30 @@ +/* + * @name No Loop + * @description The noLoop() function causes draw() to only execute once. + * Without calling noLoop(), the code inside draw() is run continually. + */ +let y; + +// The statements in the setup() function +// execute once when the program begins +function setup() { + // createCanvas should be the first statement + createCanvas(720, 400); + stroke(255); // Set line drawing color to white + noLoop(); + + y = height * 0.5; +} + +// The statements in draw() are executed until the +// program is stopped. Each statement is executed in +// sequence and after the last line is read, the first +// line is executed again. +function draw() { + background(0); // Set the background to black + y = y - 1; + if (y < 0) { + y = height; + } + line(0, y, width, y); +} diff --git a/src/data/examples/ko/00_Structure/04_Loop.js b/src/data/examples/ko/00_Structure/04_Loop.js new file mode 100644 index 0000000000..bc79823793 --- /dev/null +++ b/src/data/examples/ko/00_Structure/04_Loop.js @@ -0,0 +1,26 @@ +/* + * @name Loop + * @description The code inside the draw() function runs continuously from top + * to bottom until the program is stopped. + */ +let y = 100; + +// The statements in the setup() function +// execute once when the program begins +function setup() { + createCanvas(720, 400); // Size must be the first statement + stroke(255); // Set line drawing color to white + frameRate(30); +} +// The statements in draw() are executed until the +// program is stopped. Each statement is executed in +// sequence and after the last line is read, the first +// line is executed again. +function draw() { + background(0); // Set the background to black + y = y - 1; + if (y < 0) { + y = height; + } + line(0, y, width, y); +} diff --git a/src/data/examples/ko/00_Structure/05_Redraw.js b/src/data/examples/ko/00_Structure/05_Redraw.js new file mode 100644 index 0000000000..0d23d6bfb8 --- /dev/null +++ b/src/data/examples/ko/00_Structure/05_Redraw.js @@ -0,0 +1,33 @@ +/* + * @name Redraw + * @description The redraw() function makes draw() execute once. In this example, + * draw() is executed once every time the mouse is clicked. + */ + +let y; + +// The statements in the setup() function +// execute once when the program begins +function setup() { + createCanvas(720, 400); + stroke(255); + noLoop(); + y = height * 0.5; +} + +// The statements in draw() are executed until the +// program is stopped. Each statement is executed in +// sequence and after the last line is read, the first +// line is executed again. +function draw() { + background(0); + y = y - 4; + if (y < 0) { + y = height; + } + line(0, y, width, y); +} + +function mousePressed() { + redraw(); +} diff --git a/src/data/examples/ko/00_Structure/06_Functions.js b/src/data/examples/ko/00_Structure/06_Functions.js new file mode 100644 index 0000000000..24422e123b --- /dev/null +++ b/src/data/examples/ko/00_Structure/06_Functions.js @@ -0,0 +1,28 @@ +/* + *@name Functions + *@description The drawTarget() function makes it easy to draw many distinct + *targets. Each call to drawTarget() specifies the position, size, and number of + *rings for each target. + */ + +function setup() { + createCanvas(720, 400); + background(51); + noStroke(); + noLoop(); +} + +function draw() { + drawTarget(width * 0.25, height * 0.4, 200, 4); + drawTarget(width * 0.5, height * 0.5, 300, 10); + drawTarget(width * 0.75, height * 0.3, 120, 6); +} + +function drawTarget(xloc, yloc, size, num) { + const grayvalues = 255 / num; + const steps = size / num; + for (let i = 0; i < num; i++) { + fill(i * grayvalues); + ellipse(xloc, yloc, size - i * steps, size - i * steps); + } +} diff --git a/src/data/examples/ko/00_Structure/07_Recursion.js b/src/data/examples/ko/00_Structure/07_Recursion.js new file mode 100644 index 0000000000..61935af193 --- /dev/null +++ b/src/data/examples/ko/00_Structure/07_Recursion.js @@ -0,0 +1,27 @@ +/* + *@name Recursion + *@description A demonstration of recursion, which means functions call themselves. + * Notice how the drawCircle() function calls itself at the end of its block. + * It continues to do this until the variable "level" is equal to 1. + */ + +function setup() { + createCanvas(720, 400); + noStroke(); + noLoop(); +} + +function draw() { + drawCircle(width / 2, 280, 6); +} + +function drawCircle(x, radius, level) { + const tt = (126 * level) / 4.0; + fill(tt); + ellipse(x, height / 2, radius * 2, radius * 2); + if (level > 1) { + level = level - 1; + drawCircle(x - radius / 2, radius / 2, level); + drawCircle(x + radius / 2, radius / 2, level); + } +} diff --git a/src/data/examples/ko/00_Structure/08_Create_Graphics.js b/src/data/examples/ko/00_Structure/08_Create_Graphics.js new file mode 100644 index 0000000000..763c899cf2 --- /dev/null +++ b/src/data/examples/ko/00_Structure/08_Create_Graphics.js @@ -0,0 +1,29 @@ +/* + * @name Create Graphics + * @description Creates and returns a new p5.Renderer object. Use this + * class if you need to draw into an off-screen graphics buffer. The two parameters + * define the width and height in pixels. + */ + +let pg; + +function setup() { + createCanvas(710, 400); + pg = createGraphics(400, 250); +} + +function draw() { + fill(0, 12); + rect(0, 0, width, height); + fill(255); + noStroke(); + ellipse(mouseX, mouseY, 60, 60); + + pg.background(51); + pg.noFill(); + pg.stroke(255); + pg.ellipse(mouseX - 150, mouseY - 75, 60, 60); + + //Draw the offscreen buffer to the screen with image() + image(pg, 150, 75); +} diff --git a/src/data/examples/ko/01_Form/00_Points_and_Lines.js b/src/data/examples/ko/01_Form/00_Points_and_Lines.js new file mode 100644 index 0000000000..6871e34110 --- /dev/null +++ b/src/data/examples/ko/01_Form/00_Points_and_Lines.js @@ -0,0 +1,36 @@ +/* + * @name Points and Lines + * @description Points and lines can be used to draw basic geometry. + * Change the value of the variable 'd' to scale the form. The four + * variables set the positions based on the value of 'd'. + */ +function setup() { + let d = 70; + let p1 = d; + let p2 = p1 + d; + let p3 = p2 + d; + let p4 = p3 + d; + + // Sets the screen to be 720 pixels wide and 400 pixels high + createCanvas(720, 400); + background(0); + noSmooth(); + + translate(140, 0); + + // Draw gray box + stroke(153); + line(p3, p3, p2, p3); + line(p2, p3, p2, p2); + line(p2, p2, p3, p2); + line(p3, p2, p3, p3); + + // Draw white points + stroke(255); + point(p1, p1); + point(p1, p3); + point(p2, p4); + point(p3, p1); + point(p4, p2); + point(p4, p4); +} diff --git a/src/data/examples/ko/01_Form/01_Shape_Primitives.js b/src/data/examples/ko/01_Form/01_Shape_Primitives.js new file mode 100644 index 0000000000..728236f9f1 --- /dev/null +++ b/src/data/examples/ko/01_Form/01_Shape_Primitives.js @@ -0,0 +1,31 @@ +/* + * @name Shape Primitives + * @description The basic shape primitive functions are triangle(), + * rect(), quad(), ellipse(), and arc(). Squares are made with rect() + * and circles are made with ellipse(). Each of these functions requires + * a number of parameters to determine the shape's position and size. + */ +function setup() { + // Sets the screen to be 720 pixels wide and 400 pixels high + createCanvas(720, 400); + background(0); + noStroke(); + + fill(204); + triangle(18, 18, 18, 360, 81, 360); + + fill(102); + rect(81, 81, 63, 63); + + fill(204); + quad(189, 18, 216, 18, 216, 360, 144, 360); + + fill(255); + ellipse(252, 144, 72, 72); + + fill(204); + triangle(288, 18, 351, 360, 288, 360); + + fill(255); + arc(479, 300, 280, 280, PI, TWO_PI); +} diff --git a/src/data/examples/ko/01_Form/02_Pie_Chart.js b/src/data/examples/ko/01_Form/02_Pie_Chart.js new file mode 100644 index 0000000000..9e5a538d42 --- /dev/null +++ b/src/data/examples/ko/01_Form/02_Pie_Chart.js @@ -0,0 +1,34 @@ +/* + * @name Pie Chart + * @description Uses the arc() function to generate a pie chart from the data + * stored in an array. + */ +let angles = [30, 10, 45, 35, 60, 38, 75, 67]; + +function setup() { + createCanvas(720, 400); + noStroke(); + noLoop(); // Run once and stop +} + +function draw() { + background(100); + pieChart(300, angles); +} + +function pieChart(diameter, data) { + let lastAngle = 0; + for (let i = 0; i < data.length; i++) { + let gray = map(i, 0, data.length, 0, 255); + fill(gray); + arc( + width / 2, + height / 2, + diameter, + diameter, + lastAngle, + lastAngle + radians(angles[i]) + ); + lastAngle += radians(angles[i]); + } +} diff --git a/src/data/examples/ko/01_Form/03_Regular_Polygon.js b/src/data/examples/ko/01_Form/03_Regular_Polygon.js new file mode 100644 index 0000000000..b282c64494 --- /dev/null +++ b/src/data/examples/ko/01_Form/03_Regular_Polygon.js @@ -0,0 +1,43 @@ +/* + * @name Regular Polygon + * @description What is your favorite? Pentagon? Hexagon? Heptagon? No? + * What about the icosagon? The polygon() function created for this example is + * capable of drawing any regular polygon. Try placing different numbers into + * the polygon() function calls within draw() to explore. + */ +function setup() { + createCanvas(720, 400); +} + +function draw() { + background(102); + + push(); + translate(width * 0.2, height * 0.5); + rotate(frameCount / 200.0); + polygon(0, 0, 82, 3); + pop(); + + push(); + translate(width * 0.5, height * 0.5); + rotate(frameCount / 50.0); + polygon(0, 0, 80, 20); + pop(); + + push(); + translate(width * 0.8, height * 0.5); + rotate(frameCount / -100.0); + polygon(0, 0, 70, 7); + pop(); +} + +function polygon(x, y, radius, npoints) { + let angle = TWO_PI / npoints; + beginShape(); + for (let a = 0; a < TWO_PI; a += angle) { + let sx = x + cos(a) * radius; + let sy = y + sin(a) * radius; + vertex(sx, sy); + } + endShape(CLOSE); +} diff --git a/src/data/examples/ko/01_Form/04_Star.js b/src/data/examples/ko/01_Form/04_Star.js new file mode 100644 index 0000000000..f546a5b0d2 --- /dev/null +++ b/src/data/examples/ko/01_Form/04_Star.js @@ -0,0 +1,46 @@ +/* + * @name Star + * @description The star() function created for this example is capable of + * drawing a wide range of different forms. Try placing different numbers + * into the star() function calls within draw() to explore. + */ +function setup() { + createCanvas(720, 400); +} + +function draw() { + background(102); + + push(); + translate(width * 0.2, height * 0.5); + rotate(frameCount / 200.0); + star(0, 0, 5, 70, 3); + pop(); + + push(); + translate(width * 0.5, height * 0.5); + rotate(frameCount / 50.0); + star(0, 0, 80, 100, 40); + pop(); + + push(); + translate(width * 0.8, height * 0.5); + rotate(frameCount / -100.0); + star(0, 0, 30, 70, 5); + pop(); +} + +function star(x, y, radius1, radius2, npoints) { + let angle = TWO_PI / npoints; + let halfAngle = angle / 2.0; + beginShape(); + for (let a = 0; a < TWO_PI; a += angle) { + let sx = x + cos(a) * radius2; + let sy = y + sin(a) * radius2; + vertex(sx, sy); + sx = x + cos(a + halfAngle) * radius1; + sy = y + sin(a + halfAngle) * radius1; + vertex(sx, sy); + } + endShape(CLOSE); +} diff --git a/src/data/examples/ko/01_Form/05_Triangle_Strip.js b/src/data/examples/ko/01_Form/05_Triangle_Strip.js new file mode 100644 index 0000000000..3d7ed3622b --- /dev/null +++ b/src/data/examples/ko/01_Form/05_Triangle_Strip.js @@ -0,0 +1,38 @@ +/* + * @name Triangle Strip + * @description Example by Ira Greenberg. Generate a closed ring using the + * vertex() function and beginShape(TRIANGLE_STRIP) mode. The outsideRadius + * and insideRadius variables control ring's radii respectively. + */ +let x; +let y; +let outsideRadius = 150; +let insideRadius = 100; + +function setup() { + createCanvas(720, 400); + background(204); + x = width / 2; + y = height / 2; +} + +function draw() { + background(204); + + let numPoints = int(map(mouseX, 0, width, 6, 60)); + let angle = 0; + let angleStep = 180.0 / numPoints; + + beginShape(TRIANGLE_STRIP); + for (let i = 0; i <= numPoints; i++) { + let px = x + cos(radians(angle)) * outsideRadius; + let py = y + sin(radians(angle)) * outsideRadius; + angle += angleStep; + vertex(px, py); + px = x + cos(radians(angle)) * insideRadius; + py = y + sin(radians(angle)) * insideRadius; + vertex(px, py); + angle += angleStep; + } + endShape(); +} diff --git a/src/data/examples/ko/01_Form/06_Bezier.js b/src/data/examples/ko/01_Form/06_Bezier.js new file mode 100644 index 0000000000..40325a9858 --- /dev/null +++ b/src/data/examples/ko/01_Form/06_Bezier.js @@ -0,0 +1,28 @@ +/* + * @name Bezier + * @description The first two parameters for the bezier() function specify the + * first point in the curve and the last two parameters specify the last point. + * The middle parameters set the control points that define the shape of the + * curve. + */ +function setup() { + createCanvas(720, 400); + stroke(255); + noFill(); +} + +function draw() { + background(0); + for (let i = 0; i < 200; i += 20) { + bezier( + mouseX - i / 2.0, + 40 + i, + 410, + 20, + 440, + 300, + 240 - i / 16.0, + 300 + i / 8.0 + ); + } +} diff --git a/src/data/examples/ko/01_Form/07_3D_Primitives.js b/src/data/examples/ko/01_Form/07_3D_Primitives.js new file mode 100644 index 0000000000..bf925b71ee --- /dev/null +++ b/src/data/examples/ko/01_Form/07_3D_Primitives.js @@ -0,0 +1,30 @@ +/* + * @name 3D Primitives + * @frame 720,400 (optional) + * @description Placing mathematically 3D objects in synthetic space. + * The box() and sphere() functions take at least one parameter to specify their + * size. These shapes are positioned using the translate() function. + */ +function setup() { + createCanvas(710, 400, WEBGL); +} + +function draw() { + background(100); + + noStroke(); + fill(50); + push(); + translate(-275, 175); + rotateY(1.25); + rotateX(-0.9); + box(100); + pop(); + + noFill(); + stroke(255); + push(); + translate(500, height * 0.35, -200); + sphere(300); + pop(); +} diff --git a/src/data/examples/ko/02_Data/00_Variables.js b/src/data/examples/ko/02_Data/00_Variables.js new file mode 100644 index 0000000000..d30fbd12d5 --- /dev/null +++ b/src/data/examples/ko/02_Data/00_Variables.js @@ -0,0 +1,37 @@ +/* + * @name Variables + * @description Variables are used for storing values. In this example, change + * the values of variables to affect the composition. + */ +function setup() { + createCanvas(720, 400); + background(0); + stroke(153); + strokeWeight(4); + strokeCap(SQUARE); + + let a = 50; + let b = 120; + let c = 180; + + line(a, b, a + c, b); + line(a, b + 10, a + c, b + 10); + line(a, b + 20, a + c, b + 20); + line(a, b + 30, a + c, b + 30); + + a = a + c; + b = height - b; + + line(a, b, a + c, b); + line(a, b + 10, a + c, b + 10); + line(a, b + 20, a + c, b + 20); + line(a, b + 30, a + c, b + 30); + + a = a + c; + b = height - b; + + line(a, b, a + c, b); + line(a, b + 10, a + c, b + 10); + line(a, b + 20, a + c, b + 20); + line(a, b + 30, a + c, b + 30); +} diff --git a/src/data/examples/ko/02_Data/01_True_and_False.js b/src/data/examples/ko/02_Data/01_True_and_False.js new file mode 100644 index 0000000000..ca32f3c0cf --- /dev/null +++ b/src/data/examples/ko/02_Data/01_True_and_False.js @@ -0,0 +1,31 @@ +/* + * @name True and False + * @description A Boolean variable has only two possible values: true or false. + * It is common to use Booleans with control statements to determine the flow + * of a program. In this example, when the boolean value "b" is true, vertical + * lines are drawn and when the boolean value "b" is false, horizontal + * lines are drawn. + */ +function setup() { + createCanvas(720, 400); + background(0); + stroke(255); + + let b = false; + let d = 20; + let middle = width / 2; + + for (let i = d; i <= width; i += d) { + b = i < middle; + + if (b === true) { + // Vertical line + line(i, d, i, height - d); + } + + if (b === false) { + // Horizontal line + line(middle, i - middle + d, width - d, i - middle + d); + } + } +} diff --git a/src/data/examples/ko/02_Data/03_Variable_Scope.js b/src/data/examples/ko/02_Data/03_Variable_Scope.js new file mode 100644 index 0000000000..a9e262c39e --- /dev/null +++ b/src/data/examples/ko/02_Data/03_Variable_Scope.js @@ -0,0 +1,48 @@ +/* + * @name Variable Scope + * @description Variables have a global or function "scope". For example, + * variables declared within either the setup() or draw() functions may be + * only used in these functions. Global variables, variables declared outside + * of setup() and draw(), may be used anywhere within the program. If a function + * variable is declared with the same name as a global variable, the program + * will use the function variable to make its calculations within the current + * scope. + */ +let a = 80; // Create a global variable "a" + +function setup() { + createCanvas(720, 400); + background(0); + stroke(255); + noLoop(); +} + +function draw() { + // Draw a line using the global variable "a" + line(a, 0, a, height); + + // Use a local variable a in for loop + for (let a = 120; a < 200; a += 3) { + line(a, 0, a, height); + } + + // Make a call to the custom function drawAnotherLine() + drawAnotherLine(); + + // Make a call to the custom function drawYetAnotherLine() + drawYetAnotherLine(); +} + +function drawAnotherLine() { + // Create a new variable "a" local to this function + let a = 320; + // Draw a line using the local variable "a" + line(a, 0, a, height); +} + +function drawYetAnotherLine() { + // Because no new local variable "a" is set, + // this line draws using the original global + // variable "a" which is set to the value 20. + line(a + 3, 0, a + 3, height); +} diff --git a/src/data/examples/ko/02_Data/04_Numbers.js b/src/data/examples/ko/02_Data/04_Numbers.js new file mode 100644 index 0000000000..de4d0ea147 --- /dev/null +++ b/src/data/examples/ko/02_Data/04_Numbers.js @@ -0,0 +1,31 @@ +/* + * @name Numbers + * @frame 720,400 + * @description Numbers can be written with or without decimals. An integer + * (more commonly called an int) is a number without a decimal point. A float + * is a floating-point number, which means it is a number that has a decimal + * place. + */ +let a = 0; // Create a global variable "a" of type Number +let b = 0; // Create a global variable "b" of type Number + +function setup() { + createCanvas(720, 400); + stroke(255); +} + +function draw() { + background(0); + + a = a + 1; // Increment a with an integer + b = b + 0.2; //Increment b with a float + line(a, 0, a, height / 2); + line(b, height / 2, b, height); + + if (a > width) { + a = 0; + } + if (b > width) { + b = 0; + } +} diff --git a/src/data/examples/ko/03_Arrays/00_Array.js b/src/data/examples/ko/03_Arrays/00_Array.js new file mode 100644 index 0000000000..cfee6876d5 --- /dev/null +++ b/src/data/examples/ko/03_Arrays/00_Array.js @@ -0,0 +1,44 @@ +/* + * @name Array + * @description An array is a list of data. Each piece of data in an array + * is identified by an index number representing its position in + * the array. Arrays are zero based, which means that the first + * element in the array is [0], the second element is [1], and so on. + * In this example, an array named "coswave" is created and + * filled with the cosine values. This data is displayed three + * separate ways on the screen. + */ +let coswave = []; + +function setup() { + createCanvas(720, 360); + for (let i = 0; i < width; i++) { + let amount = map(i, 0, width, 0, PI); + coswave[i] = abs(cos(amount)); + } + background(255); + noLoop(); +} + +function draw() { + let y1 = 0; + let y2 = height / 3; + for (let i = 0; i < width; i += 3) { + stroke(coswave[i] * 255); + line(i, y1, i, y2); + } + + y1 = y2; + y2 = y1 + y1; + for (let i = 0; i < width; i += 3) { + stroke((coswave[i] * 255) / 4); + line(i, y1, i, y2); + } + + y1 = y2; + y2 = height; + for (let i = 0; i < width; i += 3) { + stroke(255 - coswave[i] * 255); + line(i, y1, i, y2); + } +} diff --git a/src/data/examples/ko/03_Arrays/01_Array_2d.js b/src/data/examples/ko/03_Arrays/01_Array_2d.js new file mode 100644 index 0000000000..87809b11ab --- /dev/null +++ b/src/data/examples/ko/03_Arrays/01_Array_2d.js @@ -0,0 +1,38 @@ +/* + * @name Array 2D + * @description Demonstrates the syntax for creating a two-dimensional (2D) + * array. Values in a 2D array are accessed through two index values. + * 2D arrays are useful for storing images. In this example, each dot + * is colored in relation to its distance from the center of the image. + */ +let distances = []; +let maxDistance; +let spacer; + +function setup() { + createCanvas(720, 360); + maxDistance = dist(width / 2, height / 2, width, height); + for (let x = 0; x < width; x++) { + distances[x] = []; // create nested array + for (let y = 0; y < height; y++) { + let distance = dist(width / 2, height / 2, x, y); + distances[x][y] = (distance / maxDistance) * 255; + } + } + spacer = 10; + noLoop(); // Run once and stop +} + +function draw() { + background(0); + // This embedded loop skips over values in the arrays based on + // the spacer variable, so there are more values in the array + // than are drawn here. Change the value of the spacer variable + // to change the density of the points + for (let x = 0; x < width; x += spacer) { + for (let y = 0; y < height; y += spacer) { + stroke(distances[x][y]); + point(x + spacer / 2, y + spacer / 2); + } + } +} diff --git a/src/data/examples/ko/03_Arrays/02_Array_Objects.js b/src/data/examples/ko/03_Arrays/02_Array_Objects.js new file mode 100644 index 0000000000..417b5c49a7 --- /dev/null +++ b/src/data/examples/ko/03_Arrays/02_Array_Objects.js @@ -0,0 +1,71 @@ +/* + * @name Array Objects + * @description Demonstrates the syntax for creating an array of custom objects. + */ + +class Module { + constructor(xOff, yOff, x, y, speed, unit) { + this.xOff = xOff; + this.yOff = yOff; + this.x = x; + this.y = y; + this.speed = speed; + this.unit = unit; + this.xDir = 1; + this.yDir = 1; + } + + // Custom method for updating the variables + update() { + this.x = this.x + this.speed * this.xDir; + if (this.x >= this.unit || this.x <= 0) { + this.xDir *= -1; + this.x = this.x + 1 * this.xDir; + this.y = this.y + 1 * this.yDir; + } + if (this.y >= this.unit || this.y <= 0) { + this.yDir *= -1; + this.y = this.y + 1 * this.yDir; + } + } + + // Custom method for drawing the object + draw() { + fill(255); + ellipse(this.xOff + this.x, this.yOff + this.y, 6, 6); + } +} + +let unit = 40; +let count; +let mods = []; + +function setup() { + createCanvas(720, 360); + noStroke(); + let wideCount = width / unit; + let highCount = height / unit; + count = wideCount * highCount; + + let index = 0; + for (let y = 0; y < highCount; y++) { + for (let x = 0; x < wideCount; x++) { + mods[index++] = new Module( + x * unit, + y * unit, + unit / 2, + unit / 2, + random(0.05, 0.8), + unit + ); + } + } +} + +function draw() { + background(0); + for (let i = 0; i < count; i++) { + mods[i].update(); + mods[i].draw(); + } +} diff --git a/src/data/examples/ko/04_Control/00_Iteration.js b/src/data/examples/ko/04_Control/00_Iteration.js new file mode 100644 index 0000000000..6d940fbb85 --- /dev/null +++ b/src/data/examples/ko/04_Control/00_Iteration.js @@ -0,0 +1,41 @@ +/* + * @name Iteration + * @description Iteration with a "for" structure to construct repetitive forms. + */ +let y; +let num = 14; + +function setup() { + createCanvas(720, 360); + background(102); + noStroke(); + + // Draw white bars + fill(255); + y = 60; + for (let i = 0; i < num / 3; i++) { + rect(50, y, 475, 10); + y += 20; + } + + // Gray bars + fill(51); + y = 40; + for (let i = 0; i < num; i++) { + rect(405, y, 30, 10); + y += 20; + } + y = 50; + for (let i = 0; i < num; i++) { + rect(425, y, 30, 10); + y += 20; + } + + // Thin lines + y = 45; + fill(0); + for (let i = 0; i < num - 1; i++) { + rect(120, y, 40, 1); + y += 20; + } +} diff --git a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js new file mode 100644 index 0000000000..58163705a6 --- /dev/null +++ b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js @@ -0,0 +1,21 @@ +/* + * @name Embedded Iteration + * @description Embedding "for" structures allows repetition in two dimensions. + */ +function setup() { + createCanvas(720, 360); + background(0); + noStroke(); + + let gridSize = 35; + + for (let x = gridSize; x <= width - gridSize; x += gridSize) { + for (let y = gridSize; y <= height - gridSize; y += gridSize) { + noStroke(); + fill(255); + rect(x - 1, y - 1, 3, 3); + stroke(255, 50); + line(x, y, width / 2, height / 2); + } + } +} diff --git a/src/data/examples/ko/04_Control/02_Conditionals_1.js b/src/data/examples/ko/04_Control/02_Conditionals_1.js new file mode 100644 index 0000000000..935bbbc919 --- /dev/null +++ b/src/data/examples/ko/04_Control/02_Conditionals_1.js @@ -0,0 +1,26 @@ +/* + * @name Conditionals 1 + * @description Conditions are like questions. + * They allow a program to decide to take one action if + * the answer to a question is true or to do another action + * if the answer to the question is false. + * The questions asked within a program are always logical + * or relational statements. For example, if the variable 'i' is + * equal to zero then draw a line. + */ +function setup() { + createCanvas(720, 360); + background(0); + + for (let i = 10; i < width; i += 10) { + // If 'i' divides by 20 with no remainder draw the first line + // else draw the second line + if (i % 20 === 0) { + stroke(255); + line(i, 80, i, height / 2); + } else { + stroke(153); + line(i, 20, i, 180); + } + } +} diff --git a/src/data/examples/ko/04_Control/03_Conditionals_2.js b/src/data/examples/ko/04_Control/03_Conditionals_2.js new file mode 100644 index 0000000000..71487dc708 --- /dev/null +++ b/src/data/examples/ko/04_Control/03_Conditionals_2.js @@ -0,0 +1,28 @@ +/* + * @name Conditionals 2 + * @description We extend the language of conditionals from the previous + * example by adding the keyword "else". This allows conditionals + * to ask two or more sequential questions, each with a different + * action. + */ +function setup() { + createCanvas(720, 360); + background(0); + + for (let i = 2; i < width - 2; i += 4) { + // If 'i' divides by 20 with no remainder + if (i % 20 === 0) { + stroke(255); + line(i, 80, i, height / 2); + // If 'i' divides by 10 with no remainder + } else if (i % 10 === 0) { + stroke(153); + line(i, 20, i, 180); + // If neither of the above two conditions are met + // then draw this line + } else { + stroke(102); + line(i, height / 2, i, height - 20); + } + } +} diff --git a/src/data/examples/ko/04_Control/04_Logical_Operators.js b/src/data/examples/ko/04_Control/04_Logical_Operators.js new file mode 100644 index 0000000000..aef6f2f0ff --- /dev/null +++ b/src/data/examples/ko/04_Control/04_Logical_Operators.js @@ -0,0 +1,42 @@ +/* + * @name Logical Operators + * @description The logical operators for AND (&&) and OR (||) are used to + * combine simple relational statements into more complex expressions. + * The NOT (!) operator is used to negate a boolean statement. + */ +let test = false; + +function setup() { + createCanvas(720, 360); + background(126); + + for (let i = 5; i <= height; i += 5) { + // Logical AND + stroke(0); + if (i > 35 && i < 100) { + line(width / 4, i, width / 2, i); + test = false; + } + + // Logical OR + stroke(76); + if (i <= 35 || i >= 100) { + line(width / 2, i, width, i); + test = true; + } + + // Testing if a boolean value is "true" + // The expression "if(test)" is equivalent to "if(test == true)" + if (test) { + stroke(0); + point(width / 3, i); + } + + // Testing if a boolean value is "false" + // The expression "if(!test)" is equivalent to "if(test == false)" + if (!test) { + stroke(255); + point(width / 4, i); + } + } +} diff --git a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js new file mode 100644 index 0000000000..9824b68d46 --- /dev/null +++ b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js @@ -0,0 +1,22 @@ +/* + * @name Load and Display Image + * @description Images can be loaded and displayed to the screen at their + * actual size or any other size. + *

To run this example locally, you will need an + * image file, and a running + * local server.

+ + */ +let img; // Declare variable 'img'. + +function setup() { + createCanvas(720, 400); + img = loadImage('assets/moonwalk.jpg'); // Load the image +} + +function draw() { + // Displays the image at its actual size at point (0,0) + image(img, 0, 0); + // Displays the image at point (0, height/2) at half size + image(img, 0, height / 2, img.width / 2, img.height / 2); +} diff --git a/src/data/examples/ko/05_Image/01_Background_Image.js b/src/data/examples/ko/05_Image/01_Background_Image.js new file mode 100644 index 0000000000..80a63e461a --- /dev/null +++ b/src/data/examples/ko/05_Image/01_Background_Image.js @@ -0,0 +1,31 @@ +/* + * @name Background Image + * @description This example presents the fastest way to load a + * background image. To load an image as the background, + * it must be the same width and height as the program. + *

To run this example locally, you will need an + * image file, and a running + * local server.

+ */ +let bg; +let y = 0; + +function setup() { + // The background image must be the same size as the parameters + // into the createCanvas() method. In this program, the size of + // the image is 720x400 pixels. + bg = loadImage('assets/moonwalk.jpg'); + createCanvas(720, 400); +} + +function draw() { + background(bg); + + stroke(226, 204, 0); + line(0, y, width, y); + + y++; + if (y > height) { + y = 0; + } +} diff --git a/src/data/examples/ko/05_Image/02_Transparency.js b/src/data/examples/ko/05_Image/02_Transparency.js new file mode 100644 index 0000000000..39cb96bb6a --- /dev/null +++ b/src/data/examples/ko/05_Image/02_Transparency.js @@ -0,0 +1,25 @@ +/* + * @name Transparency + * @description Move the pointer left and right across the image to change its + * position. This program overlays one image over another by modifying the + * alpha value of the image with the tint() function. + *

To run this example locally, you will need an + * image file, and a running + * local server.

+ */ +let img; +let offset = 0; +let easing = 0.05; + +function setup() { + createCanvas(720, 400); + img = loadImage('assets/moonwalk.jpg'); // Load an image into the program +} + +function draw() { + image(img, 0, 0); // Display at full opacity + let dx = mouseX - img.width / 2 - offset; + offset += dx * easing; + tint(255, 127); // Display at half opacity + image(img, offset, 0); +} diff --git a/src/data/examples/ko/05_Image/03_Alpha_Mask.js b/src/data/examples/ko/05_Image/03_Alpha_Mask.js new file mode 100644 index 0000000000..0e57e3533c --- /dev/null +++ b/src/data/examples/ko/05_Image/03_Alpha_Mask.js @@ -0,0 +1,28 @@ +/* + * @name Alpha Mask + * @description Loads a "mask" for an image to specify the transparency in + * different parts of the image. The two images are blended together using + * the mask() method of p5.Image. + *

To run this example locally, you will need two + * image files, and a running + * local server.

+ */ +let img; +let imgMask; + +function preload() { + img = loadImage('assets/moonwalk.jpg'); + imgMask = loadImage('assets/mask.png'); +} + +function setup() { + createCanvas(720, 400); + img.mask(imgMask); + imageMode(CENTER); +} + +function draw() { + background(0, 102, 153); + image(img, width / 2, height / 2); + image(img, mouseX, mouseY); +} diff --git a/src/data/examples/ko/05_Image/04_Create_Image.js b/src/data/examples/ko/05_Image/04_Create_Image.js new file mode 100644 index 0000000000..481f4b0ce4 --- /dev/null +++ b/src/data/examples/ko/05_Image/04_Create_Image.js @@ -0,0 +1,25 @@ +/* + * @name Create Image + * @description The createImage() function provides a fresh buffer of pixels to + * play with. This example creates an image gradient. + */ +let img; // Declare variable 'img'. + +function setup() { + createCanvas(720, 400); + img = createImage(230, 230); + img.loadPixels(); + for (let x = 0; x < img.width; x++) { + for (let y = 0; y < img.height; y++) { + let a = map(y, 0, img.height, 255, 0); + img.set(x, y, [0, 153, 204, a]); + } + } + img.updatePixels(); +} + +function draw() { + background(0); + image(img, 90, 80); + image(img, mouseX - img.width / 2, mouseY - img.height / 2); +} diff --git a/src/data/examples/ko/05_Image/05_Pointillism.js b/src/data/examples/ko/05_Image/05_Pointillism.js new file mode 100644 index 0000000000..e256756c9e --- /dev/null +++ b/src/data/examples/ko/05_Image/05_Pointillism.js @@ -0,0 +1,34 @@ +/* + * @name Pointillism + * @description By Dan Shiffman. Mouse horizontal location controls size of + * dots. Creates a simple pointillist effect using ellipses colored according + * to pixels in an image. + *

To run this example locally, you will need an + * image file, and a running + * local server.

+ */ +let img; +let smallPoint, largePoint; + +function preload() { + img = loadImage('assets/moonwalk.jpg'); +} + +function setup() { + createCanvas(720, 400); + smallPoint = 4; + largePoint = 40; + imageMode(CENTER); + noStroke(); + background(255); + img.loadPixels(); +} + +function draw() { + let pointillize = map(mouseX, 0, width, smallPoint, largePoint); + let x = floor(random(img.width)); + let y = floor(random(img.height)); + let pix = img.get(x, y); + fill(pix, 128); + ellipse(x, y, pointillize, pointillize); +} diff --git a/src/data/examples/ko/07_Color/00_Hue.js b/src/data/examples/ko/07_Color/00_Hue.js new file mode 100644 index 0000000000..bb1e02ed95 --- /dev/null +++ b/src/data/examples/ko/07_Color/00_Hue.js @@ -0,0 +1,25 @@ +/* + * @name Hue + * @description Hue is the color reflected from or transmitted through an + * object and is typically referred to as the name of the color (red, blue, + * yellow, etc.) Move the cursor vertically over each bar to alter its hue. + */ +const barWidth = 20; +let lastBar = -1; + +function setup() { + createCanvas(720, 400); + colorMode(HSB, height, height, height); + noStroke(); + background(0); +} + +function draw() { + let whichBar = mouseX / barWidth; + if (whichBar !== lastBar) { + let barX = whichBar * barWidth; + fill(mouseY, height, height); + rect(barX, 0, barWidth, height); + lastBar = whichBar; + } +} diff --git a/src/data/examples/ko/07_Color/01_Saturation.js b/src/data/examples/ko/07_Color/01_Saturation.js new file mode 100644 index 0000000000..7394cf7dbf --- /dev/null +++ b/src/data/examples/ko/07_Color/01_Saturation.js @@ -0,0 +1,25 @@ +/* + * @name Saturation + * @description Saturation is the strength or purity of the color and + * represents the amount of gray in proportion to the hue. A "saturated" + * color is pure and an "unsaturated" color has a large percentage of gray. + * Move the cursor vertically over each bar to alter its saturation. + */ +const barWidth = 20; +let lastBar = -1; + +function setup() { + createCanvas(720, 400); + colorMode(HSB, width, height, 100); + noStroke(); +} + +function draw() { + let whichBar = mouseX / barWidth; + if (whichBar !== lastBar) { + let barX = whichBar * barWidth; + fill(barX, mouseY, 66); + rect(barX, 0, barWidth, height); + lastBar = whichBar; + } +} diff --git a/src/data/examples/ko/07_Color/02_Brightness.js b/src/data/examples/ko/07_Color/02_Brightness.js new file mode 100644 index 0000000000..17f29af7f2 --- /dev/null +++ b/src/data/examples/ko/07_Color/02_Brightness.js @@ -0,0 +1,46 @@ +/* + * @name Brightness + * @description By Dan Shiffman. This program adjusts the brightness of a part + * of the image by calculating the distance of each pixel to the mouse. + *

To run this example locally, you will need + * at least an image file and a running local server.

+ */ +let img; + +function preload() { + img = loadImage('assets/moonwalk.jpg'); +} + +function setup() { + createCanvas(720, 200); + pixelDensity(1); + img.loadPixels(); + loadPixels(); +} + +function draw() { + for (let x = 0; x < img.width; x++) { + for (let y = 0; y < img.height; y++) { + // Calculate the 1D location from a 2D grid + let loc = (x + y * img.width) * 4; + // Get the R,G,B values from image + let r, g, b; + r = img.pixels[loc]; + // Calculate an amount to change brightness based on proximity to the mouse + let maxdist = 50; + let d = dist(x, y, mouseX, mouseY); + let adjustbrightness = (255 * (maxdist - d)) / maxdist; + r += adjustbrightness; + // Constrain RGB to make sure they are within 0-255 color range + r = constrain(r, 0, 255); + // Make a new color and set pixel in the window + //color c = color(r, g, b); + let pixloc = (y * width + x) * 4; + pixels[pixloc] = r; + pixels[pixloc + 1] = r; + pixels[pixloc + 2] = r; + pixels[pixloc + 3] = 255; + } + } + updatePixels(); +} diff --git a/src/data/examples/ko/07_Color/03_Color_Variables.js b/src/data/examples/ko/07_Color/03_Color_Variables.js new file mode 100644 index 0000000000..2151681561 --- /dev/null +++ b/src/data/examples/ko/07_Color/03_Color_Variables.js @@ -0,0 +1,40 @@ +/* + * @name Color Variables + * @description (Homage to Albers.) This example creates variables for colors + * that may be referred to in the program by a name, rather than a number. + */ +function setup() { + createCanvas(710, 400); + noStroke(); + background(51, 0, 0); + + let inside = color(204, 102, 0); + let middle = color(204, 153, 0); + let outside = color(153, 51, 0); + + // These statements are equivalent to the statements above. + // Programmers may use the format they prefer. + //let inside = color('#CC6600'); + //let middle = color('#CC9900'); + //let outside = color('#993300'); + + push(); + translate(80, 80); + fill(outside); + rect(0, 0, 200, 200); + fill(middle); + rect(40, 60, 120, 120); + fill(inside); + rect(60, 90, 80, 80); + pop(); + + push(); + translate(360, 80); + fill(inside); + rect(0, 0, 200, 200); + fill(outside); + rect(40, 60, 120, 120); + fill(middle); + rect(60, 90, 80, 80); + pop(); +} diff --git a/src/data/examples/ko/07_Color/04_Relativity.js b/src/data/examples/ko/07_Color/04_Relativity.js new file mode 100644 index 0000000000..010ef7489f --- /dev/null +++ b/src/data/examples/ko/07_Color/04_Relativity.js @@ -0,0 +1,34 @@ +/* + * @name Relativity + * @description Each color is perceived in relation to other colors. The top + * and bottom bars each contain the same component colors, but a different + * display order causes individual colors to appear differently. + */ +let a, b, c, d, e; + +function setup() { + createCanvas(710, 400); + noStroke(); + a = color(165, 167, 20); + b = color(77, 86, 59); + c = color(42, 106, 105); + d = color(165, 89, 20); + e = color(146, 150, 127); + noLoop(); // Draw only one time +} + +function draw() { + drawBand(a, b, c, d, e, 0, width / 128); + drawBand(c, a, d, b, e, height / 2, width / 128); +} + +function drawBand(v, w, x, y, z, ypos, barWidth) { + let num = 5; + let colorOrder = [v, w, x, y, z]; + for (let i = 0; i < width; i += barWidth * num) { + for (let j = 0; j < num; j++) { + fill(colorOrder[j]); + rect(i + j * barWidth, ypos, barWidth, height / 2); + } + } +} diff --git a/src/data/examples/ko/07_Color/05_Linear_Gradient.js b/src/data/examples/ko/07_Color/05_Linear_Gradient.js new file mode 100644 index 0000000000..a99dcbbdf7 --- /dev/null +++ b/src/data/examples/ko/07_Color/05_Linear_Gradient.js @@ -0,0 +1,52 @@ +/* + * @name Linear Gradient + * @description The lerpColor() function is useful for interpolating between + * two colors. + */ +// Constants +const Y_AXIS = 1; +const X_AXIS = 2; +let b1, b2, c1, c2; + +function setup() { + createCanvas(710, 400); + + // Define colors + b1 = color(255); + b2 = color(0); + c1 = color(204, 102, 0); + c2 = color(0, 102, 153); + + noLoop(); +} + +function draw() { + // Background + setGradient(0, 0, width / 2, height, b1, b2, X_AXIS); + setGradient(width / 2, 0, width / 2, height, b2, b1, X_AXIS); + // Foreground + setGradient(50, 90, 540, 80, c1, c2, Y_AXIS); + setGradient(50, 190, 540, 80, c2, c1, X_AXIS); +} + +function setGradient(x, y, w, h, c1, c2, axis) { + noFill(); + + if (axis === Y_AXIS) { + // Top to bottom gradient + for (let i = y; i <= y + h; i++) { + let inter = map(i, y, y + h, 0, 1); + let c = lerpColor(c1, c2, inter); + stroke(c); + line(x, i, x + w, i); + } + } else if (axis === X_AXIS) { + // Left to right gradient + for (let i = x; i <= x + w; i++) { + let inter = map(i, x, x + w, 0, 1); + let c = lerpColor(c1, c2, inter); + stroke(c); + line(i, y, i, y + h); + } + } +} diff --git a/src/data/examples/ko/07_Color/06_Radial_Gradient.js b/src/data/examples/ko/07_Color/06_Radial_Gradient.js new file mode 100644 index 0000000000..51e1f37404 --- /dev/null +++ b/src/data/examples/ko/07_Color/06_Radial_Gradient.js @@ -0,0 +1,33 @@ +/* + * @name Radial Gradient + * @description Draws a series of concentric circles to create a gradient + * from one color to another. + */ +let dim; + +function setup() { + createCanvas(710, 400); + dim = width / 2; + background(0); + colorMode(HSB, 360, 100, 100); + noStroke(); + ellipseMode(RADIUS); + frameRate(1); +} + +function draw() { + background(0); + for (let x = 0; x <= width; x += dim) { + drawGradient(x, height / 2); + } +} + +function drawGradient(x, y) { + let radius = dim / 2; + let h = random(0, 360); + for (let r = radius; r > 0; --r) { + fill(h, 90, 90); + ellipse(x, y, r, r); + h = (h + 1) % 360; + } +} diff --git a/src/data/examples/ko/07_Color/07_Lerp_Color.js b/src/data/examples/ko/07_Color/07_Lerp_Color.js new file mode 100644 index 0000000000..471a2df17e --- /dev/null +++ b/src/data/examples/ko/07_Color/07_Lerp_Color.js @@ -0,0 +1,49 @@ +/* + * @name Lerp Color + * @description Loop random shapes, + * lerp color from red to blue. + */ +function setup() { + createCanvas(720, 400); + background(255); + noStroke(); +} + +function draw() { + background(255); + from = color(255, 0, 0, 0.2 * 255); + to = color(0, 0, 255, 0.2 * 255); + c1 = lerpColor(from, to, 0.33); + c2 = lerpColor(from, to, 0.66); + for (let i = 0; i < 15; i++) { + fill(from); + quad( + random(-40, 220), random(height), + random(-40, 220), random(height), + random(-40, 220), random(height), + random(-40, 220), random(height) + ); + fill(c1); + quad( + random(140, 380), random(height), + random(140, 380), random(height), + random(140, 380), random(height), + random(140, 380), random(height) + ); + fill(c2); + quad( + random(320, 580), random(height), + random(320, 580), random(height), + random(320, 580), random(height), + random(320, 580), random(height) + ); + fill(to); + quad( + random(500, 760), random(height), + random(500, 760), random(height), + random(500, 760), random(height), + random(500, 760), random(height) + ); + } + frameRate(5); +} diff --git a/src/data/examples/ko/08_Math/00_incrementdecrement.js b/src/data/examples/ko/08_Math/00_incrementdecrement.js new file mode 100644 index 0000000000..0b3d64d6e6 --- /dev/null +++ b/src/data/examples/ko/08_Math/00_incrementdecrement.js @@ -0,0 +1,42 @@ +/* + * @name Increment Decrement + * @description Writing "a++" is equivalent to "a = a + 1". + * Writing "a--" is equivalent to "a = a - 1". + */ +let a; +let b; +let direction; + +function setup() { + createCanvas(710, 400); + colorMode(RGB, width); + a = 0; + b = width; + direction = true; + frameRate(30); +} + +function draw() { + a++; + if (a > width) { + a = 0; + direction = !direction; + } + if (direction === true) { + stroke(a); + } else { + stroke(width - a); + } + line(a, 0, a, height / 2); + + b--; + if (b < 0) { + b = width; + } + if (direction == true) { + stroke(width - b); + } else { + stroke(b); + } + line(b, height / 2 + 1, b, height); +} diff --git a/src/data/examples/ko/08_Math/01_operatorprecedence.js b/src/data/examples/ko/08_Math/01_operatorprecedence.js new file mode 100644 index 0000000000..175054f692 --- /dev/null +++ b/src/data/examples/ko/08_Math/01_operatorprecedence.js @@ -0,0 +1,54 @@ +/* + * @name Operator Precedence + * @description If you don't explicitly state the order in which an + * expression is evaluated, they are evaluated based on the operator + * precedence. For example, in the statement "4+2*8", the 2 will + * first be multiplied by 8 and then the result will be added to 4. + * This is because the "*" has a higher precedence than the "+". To avoid + * ambiguity in reading the program, it is recommended that is statement + * is written as "4+(2*8)". The order of evaluation can be controlled + * through placement of parenthesis in the code. A table of operator + * precedence follows below. + */ +// The highest precedence is at the top of the list and +// the lowest is at the bottom. +// Multiplicative: * / % +// Additive: + - +// Relational: < > <= >= +// Equality: == != +// Logical AND: && +// Logical OR: || +// Assignment: = += -= *= /= %= +function setup() { + createCanvas(710, 400); + background(51); + noFill(); + stroke(51); + + stroke(204); + for (let i = 0; i < width - 20; i += 4) { + // The 30 is added to 70 and then evaluated + // if it is greater than the current value of "i" + // For clarity, write as "if (i > (30 + 70)) {" + if (i > 30 + 70) { + line(i, 0, i, 50); + } + } + + stroke(255); + // The 2 is multiplied by the 8 and the result is added to the 4 + // For clarity, write as "rect(5 + (2 * 8), 0, 90, 20);" + rect(4 + 2 * 8, 52, 290, 48); + rect((4 + 2) * 8, 100, 290, 49); + + stroke(153); + for (let i = 0; i < width; i += 2) { + // The relational statements are evaluated + // first, and then the logical AND statements and + // finally the logical OR. For clarity, write as: + // "if(((i > 20) && (i < 50)) || ((i > 100) && (i < width-20))) {" + if ((i > 20 && i < 50) || (i > 100 && i < width - 20)) { + line(i, 151, i, height - 1); + } + } +} diff --git a/src/data/examples/ko/08_Math/02_distance1d.js b/src/data/examples/ko/08_Math/02_distance1d.js new file mode 100644 index 0000000000..7005d3a17b --- /dev/null +++ b/src/data/examples/ko/08_Math/02_distance1d.js @@ -0,0 +1,65 @@ +/* + * @name Distance 1D + * @description Move the mouse left and right to control + * the speed and direction of the moving shapes. + */ +let xpos1; +let xpos2; +let xpos3; +let xpos4; +let thin = 8; +let thick = 36; + +function setup() { + createCanvas(710, 400); + noStroke(); + xpos1 = width / 2; + xpos2 = width / 2; + xpos3 = width / 2; + xpos4 = width / 2; +} + +function draw() { + background(0); + + let mx = mouseX * 0.4 - width / 5.0; + + fill(102); + rect(xpos2, 0, thick, height / 2); + fill(204); + rect(xpos1, 0, thin, height / 2); + fill(102); + rect(xpos4, height / 2, thick, height / 2); + fill(204); + rect(xpos3, height / 2, thin, height / 2); + + xpos1 += mx / 16; + xpos2 += mx / 64; + xpos3 -= mx / 16; + xpos4 -= mx / 64; + + if (xpos1 < -thin) { + xpos1 = width; + } + if (xpos1 > width) { + xpos1 = -thin; + } + if (xpos2 < -thick) { + xpos2 = width; + } + if (xpos2 > width) { + xpos2 = -thick; + } + if (xpos3 < -thin) { + xpos3 = width; + } + if (xpos3 > width) { + xpos3 = -thin; + } + if (xpos4 < -thick) { + xpos4 = width; + } + if (xpos4 > width) { + xpos4 = -thick; + } +} diff --git a/src/data/examples/ko/08_Math/03_distance2d.js b/src/data/examples/ko/08_Math/03_distance2d.js new file mode 100644 index 0000000000..22bfcc1853 --- /dev/null +++ b/src/data/examples/ko/08_Math/03_distance2d.js @@ -0,0 +1,25 @@ +/* + * @name Distance 2D + * @description Move the mouse across the image to obscure + * and reveal the matrix. Measures the distance from the mouse + * to each circle and sets the size proportionally. + */ +let max_distance; + +function setup() { + createCanvas(710, 400); + noStroke(); + max_distance = dist(0, 0, width, height); +} + +function draw() { + background(0); + + for (let i = 0; i <= width; i += 20) { + for (let j = 0; j <= height; j += 20) { + let size = dist(mouseX, mouseY, i, j); + size = (size / max_distance) * 66; + ellipse(i, j, size, size); + } + } +} diff --git a/src/data/examples/ko/08_Math/04_sine.js b/src/data/examples/ko/08_Math/04_sine.js new file mode 100644 index 0000000000..810d8a27be --- /dev/null +++ b/src/data/examples/ko/08_Math/04_sine.js @@ -0,0 +1,27 @@ +/* + * @name Sine + * @description Smoothly scaling size with the sin() function. + */ +let diameter; +let angle = 0; + +function setup() { + createCanvas(710, 400); + diameter = height - 10; + noStroke(); + fill(255, 204, 0); +} + +function draw() { + background(0); + + let d1 = 10 + (sin(angle) * diameter) / 2 + diameter / 2; + let d2 = 10 + (sin(angle + PI / 2) * diameter) / 2 + diameter / 2; + let d3 = 10 + (sin(angle + PI) * diameter) / 2 + diameter / 2; + + ellipse(0, height / 2, d1, d1); + ellipse(width / 2, height / 2, d2, d2); + ellipse(width, height / 2, d3, d3); + + angle += 0.02; +} diff --git a/src/data/examples/ko/08_Math/05_sincosine.js b/src/data/examples/ko/08_Math/05_sincosine.js new file mode 100644 index 0000000000..82e9e42cf7 --- /dev/null +++ b/src/data/examples/ko/08_Math/05_sincosine.js @@ -0,0 +1,43 @@ +/* + * @name Sine Cosine + * @description Linear movement with sin() and cos(). + * Numbers between 0 and PI*2 (TWO_PI which angles roughly 6.28) + * are put into these functions and numbers between -1 and 1 are returned. + * These values are then scaled to produce larger movements. + */ +let angle1 = 0; +let angle2 = 0; +let scalar = 70; + +function setup() { + createCanvas(710, 400); + noStroke(); + rectMode(CENTER); +} + +function draw() { + background(0); + + let ang1 = radians(angle1); + let ang2 = radians(angle2); + + let x1 = width / 2 + scalar * cos(ang1); + let x2 = width / 2 + scalar * cos(ang2); + + let y1 = height / 2 + scalar * sin(ang1); + let y2 = height / 2 + scalar * sin(ang2); + + fill(255); + rect(width * 0.5, height * 0.5, 140, 140); + + fill(0, 102, 153); + ellipse(x1, height * 0.5 - 120, scalar, scalar); + ellipse(x2, height * 0.5 + 120, scalar, scalar); + + fill(255, 204, 0); + ellipse(width * 0.5 - 120, y1, scalar, scalar); + ellipse(width * 0.5 + 120, y2, scalar, scalar); + + angle1 += 2; + angle2 += 3; +} diff --git a/src/data/examples/ko/08_Math/06_sinewave.js b/src/data/examples/ko/08_Math/06_sinewave.js new file mode 100644 index 0000000000..f52d7b1368 --- /dev/null +++ b/src/data/examples/ko/08_Math/06_sinewave.js @@ -0,0 +1,48 @@ +/* + * @name Sine Wave + * @description Render a simple sine wave. + * Original by Daniel Shiffman. + */ + +let xspacing = 16; // Distance between each horizontal location +let w; // Width of entire wave +let theta = 0.0; // Start angle at 0 +let amplitude = 75.0; // Height of wave +let period = 500.0; // How many pixels before the wave repeats +let dx; // Value for incrementing x +let yvalues; // Using an array to store height values for the wave + +function setup() { + createCanvas(710, 400); + w = width + 16; + dx = (TWO_PI / period) * xspacing; + yvalues = new Array(floor(w / xspacing)); +} + +function draw() { + background(0); + calcWave(); + renderWave(); +} + +function calcWave() { + // Increment theta (try different values for + // 'angular velocity' here) + theta += 0.02; + + // For every x value, calculate a y value with sine function + let x = theta; + for (let i = 0; i < yvalues.length; i++) { + yvalues[i] = sin(x) * amplitude; + x += dx; + } +} + +function renderWave() { + noStroke(); + fill(255); + // A simple way to draw the wave with an ellipse at each location + for (let x = 0; x < yvalues.length; x++) { + ellipse(x * xspacing, height / 2 + yvalues[x], 16, 16); + } +} diff --git a/src/data/examples/ko/08_Math/07_additivewave.js b/src/data/examples/ko/08_Math/07_additivewave.js new file mode 100644 index 0000000000..ade6a96075 --- /dev/null +++ b/src/data/examples/ko/08_Math/07_additivewave.js @@ -0,0 +1,70 @@ +/* + * @name Additive Wave + * @description Create a more complex wave by adding two waves together. + * Original by Daniel Shiffman + */ +let xspacing = 8; // Distance between each horizontal location +let w; // Width of entire wave +let maxwaves = 4; // total # of waves to add together + +let theta = 0.0; +let amplitude = new Array(maxwaves); // Height of wave +// Value for incrementing X, to be calculated +// as a function of period and xspacing +let dx = new Array(maxwaves); +// Using an array to store height values +// for the wave (not entirely necessary) +let yvalues; + +function setup() { + createCanvas(710, 400); + frameRate(30); + colorMode(RGB, 255, 255, 255, 100); + w = width + 16; + + for (let i = 0; i < maxwaves; i++) { + amplitude[i] = random(10, 30); + let period = random(100, 300); // Num pixels before wave repeats + dx[i] = (TWO_PI / period) * xspacing; + } + + yvalues = new Array(floor(w / xspacing)); +} + +function draw() { + background(0); + calcWave(); + renderWave(); +} + +function calcWave() { + // Increment theta (try different values + // for 'angular velocity' here + theta += 0.02; + + // Set all height values to zero + for (let i = 0; i < yvalues.length; i++) { + yvalues[i] = 0; + } + + // Accumulate wave height values + for (let j = 0; j < maxwaves; j++) { + let x = theta; + for (let i = 0; i < yvalues.length; i++) { + // Every other wave is cosine instead of sine + if (j % 2 == 0) yvalues[i] += sin(x) * amplitude[j]; + else yvalues[i] += cos(x) * amplitude[j]; + x += dx[j]; + } + } +} + +function renderWave() { + // A simple way to draw the wave with an ellipse at each location + noStroke(); + fill(255, 50); + ellipseMode(CENTER); + for (let x = 0; x < yvalues.length; x++) { + ellipse(x * xspacing, width / 2 + yvalues[x], 16, 16); + } +} diff --git a/src/data/examples/ko/08_Math/08_polartocartesian.js b/src/data/examples/ko/08_Math/08_polartocartesian.js new file mode 100644 index 0000000000..c1be3f305d --- /dev/null +++ b/src/data/examples/ko/08_Math/08_polartocartesian.js @@ -0,0 +1,44 @@ +/* + * @name PolarToCartesian + * @description Convert a polar coordinate (r,theta) + * to cartesian (x,y): x = rcos(theta) y = rsin(theta) + * Original by Daniel Shiffman. + */ +let r; + +// Angle and angular velocity, accleration +let theta; +let theta_vel; +let theta_acc; + +function setup() { + createCanvas(710, 400); + + // Initialize all values + r = height * 0.45; + theta = 0; + theta_vel = 0; + theta_acc = 0.0001; +} + +function draw() { + background(0); + + // Translate the origin point to the center of the screen + translate(width / 2, height / 2); + + // Convert polar to cartesian + let x = r * cos(theta); + let y = r * sin(theta); + + // Draw the ellipse at the cartesian coordinate + ellipseMode(CENTER); + noStroke(); + fill(200); + ellipse(x, y, 32, 32); + + // Apply acceleration and velocity to angle + // (r remains static in this example) + theta_vel += theta_acc; + theta += theta_vel; +} diff --git a/src/data/examples/ko/08_Math/09_arctangent.js b/src/data/examples/ko/08_Math/09_arctangent.js new file mode 100644 index 0000000000..cc90d4499b --- /dev/null +++ b/src/data/examples/ko/08_Math/09_arctangent.js @@ -0,0 +1,45 @@ +/* + * @name Arctangent + * @description Move the mouse to change the direction of the eyes.
The atan2() function computes the angle from each eye to the cursor. + */ +let e1, e2, e3; + +function setup() { + createCanvas(720, 400); + noStroke(); + e1 = new Eye(250, 16, 120); + e2 = new Eye(164, 185, 80); + e3 = new Eye(420, 230, 220); +} + +function draw() { + background(102); + e1.update(mouseX, mouseY); + e2.update(mouseX, mouseY); + e3.update(mouseX, mouseY); + e1.display(); + e2.display(); + e3.display(); +} + +function Eye(tx, ty, ts) { + this.x = tx; + this.y = ty; + this.size = ts; + this.angle = 0; + + this.update = function(mx, my) { + this.angle = atan2(my - this.y, mx - this.x); + }; + + this.display = function() { + push(); + translate(this.x, this.y); + fill(255); + ellipse(0, 0, this.size, this.size); + rotate(this.angle); + fill(153, 204, 0); + ellipse(this.size / 4, 0, this.size / 2, this.size / 2); + pop(); + }; +} diff --git a/src/data/examples/ko/08_Math/10_Interpolate.js b/src/data/examples/ko/08_Math/10_Interpolate.js new file mode 100644 index 0000000000..27ec95ef92 --- /dev/null +++ b/src/data/examples/ko/08_Math/10_Interpolate.js @@ -0,0 +1,34 @@ +/* + * @name Linear Interpolation + * @frame 720, 400 + * @description Move the mouse across the screen and the symbol will follow. + * Between drawing each frame of the animation, the ellipse moves part + * of the distance (0.05) from its current position toward the cursor using + * the lerp() function. + * This is the same as the Easing under input only with lerp() instead.. + */ + +let x = 0; +let y = 0; + +function setup() { + createCanvas(720, 400); + noStroke(); +} + +function draw() { + background(51); + + // lerp() calculates a number between two numbers at a specific increment. + // The amt parameter is the amount to interpolate between the two values + // where 0.0 equal to the first point, 0.1 is very near the first point, 0.5 + // is half-way in between, etc. + + // Here we are moving 5% of the way to the mouse location each frame + x = lerp(x, mouseX, 0.05); + y = lerp(y, mouseY, 0.05); + + fill(255); + stroke(255); + ellipse(x, y, 66, 66); +} diff --git a/src/data/examples/ko/08_Math/11_doubleRandom.js b/src/data/examples/ko/08_Math/11_doubleRandom.js new file mode 100644 index 0000000000..5abd9f7b01 --- /dev/null +++ b/src/data/examples/ko/08_Math/11_doubleRandom.js @@ -0,0 +1,24 @@ +/* + * @name Double Random + * @frame 720,400 (optional) + * @description Using two random() calls and the point() + * function to create an irregular sawtooth line. + * Original by by Ira Greenberg. + */ +let totalPts = 300; +let steps = totalPts + 1; + +function setup() { + createCanvas(710, 400); + stroke(255); + frameRate(1); +} + +function draw() { + background(0); + let rand = 0; + for (let i = 1; i < steps; i++) { + point((width / steps) * i, height / 2 + random(-rand, rand)); + rand += random(-5, 5); + } +} diff --git a/src/data/examples/ko/08_Math/12_random.js b/src/data/examples/ko/08_Math/12_random.js new file mode 100644 index 0000000000..6475297be5 --- /dev/null +++ b/src/data/examples/ko/08_Math/12_random.js @@ -0,0 +1,19 @@ +/* + * @name Random + * @description Random numbers create the basis of this image. + * Each time the program is loaded the result is different. + */ +function setup() { + createCanvas(710, 400); + background(0); + strokeWeight(20); + frameRate(2); +} + +function draw() { + for (let i = 0; i < width; i++) { + let r = random(255); + stroke(r); + line(i, 0, i, height); + } +} diff --git a/src/data/examples/ko/08_Math/13_noise1D.js b/src/data/examples/ko/08_Math/13_noise1D.js new file mode 100644 index 0000000000..a9704cd9fe --- /dev/null +++ b/src/data/examples/ko/08_Math/13_noise1D.js @@ -0,0 +1,31 @@ +/* + * @name Noise1D + * @description Using 1D Perlin Noise to assign location. + */ +let xoff = 0.0; +let xincrement = 0.01; + +function setup() { + createCanvas(710, 400); + background(0); + noStroke(); +} + +function draw() { + // Create an alpha blended background + fill(0, 10); + rect(0, 0, width, height); + + //let n = random(0,width); // Try this line instead of noise + + // Get a noise value based on xoff and scale + // it according to the window's width + let n = noise(xoff) * width; + + // With each cycle, increment xoff + xoff += xincrement; + + // Draw the ellipse at the value produced by perlin noise + fill(200); + ellipse(n, height / 2, 64, 64); +} diff --git a/src/data/examples/ko/08_Math/14_noisewave.js b/src/data/examples/ko/08_Math/14_noisewave.js new file mode 100644 index 0000000000..df1b1e0a24 --- /dev/null +++ b/src/data/examples/ko/08_Math/14_noisewave.js @@ -0,0 +1,42 @@ +/* + * @name Noise Wave + * @description Using Perlin Noise to generate a wave-like pattern. + * Original by Daniel Shiffman. + */ +let yoff = 0.0; // 2nd dimension of perlin noise + +function setup() { + createCanvas(710, 400); +} + +function draw() { + background(51); + + fill(255); + // We are going to draw a polygon out of the wave points + beginShape(); + + let xoff = 0; // Option #1: 2D Noise + // let xoff = yoff; // Option #2: 1D Noise + + // Iterate over horizontal pixels + for (let x = 0; x <= width; x += 10) { + // Calculate a y value according to noise, map to + + // Option #1: 2D Noise + let y = map(noise(xoff, yoff), 0, 1, 200, 300); + + // Option #2: 1D Noise + // let y = map(noise(xoff), 0, 1, 200,300); + + // Set the vertex + vertex(x, y); + // Increment x dimension for noise + xoff += 0.05; + } + // increment y dimension for noise + yoff += 0.01; + vertex(width, height); + vertex(0, height); + endShape(CLOSE); +} diff --git a/src/data/examples/ko/08_Math/15_Noise2D.js b/src/data/examples/ko/08_Math/15_Noise2D.js new file mode 100644 index 0000000000..2aec0d5690 --- /dev/null +++ b/src/data/examples/ko/08_Math/15_Noise2D.js @@ -0,0 +1,42 @@ +/* + * @name Noise2D + * @frame 710,400 (optional) + * @description Create a 2D noise with different parameters. + * + */ + +let noiseVal; +let noiseScale = 0.02; + +function setup() { + createCanvas(640, 360); +} + +function draw() { + background(0); + // Draw the left half of image + for (let y = 0; y < height - 30; y++) { + for (let x = 0; x < width / 2; x++) { + // noiceDetail of the pixels octave count and falloff value + noiseDetail(2, 0.2); + noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale); + stroke(noiseVal * 255); + point(x, y); + } + } + // Draw the right half of image + for (let y = 0; y < height - 30; y++) { + for (let x = width / 2; x < width; x++) { + // noiceDetail of the pixels octave count and falloff value + noiseDetail(5, 0.5); + noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale); + stroke(noiseVal * 255); + point(x, y); + } + } + //Show the details of two partitions + textSize(18); + fill(255, 255, 255); + text('Noice2D with 2 octaves and 0.2 falloff', 10, 350); + text('Noice2D with 1 octaves and 0.7 falloff', 330, 350); +} diff --git a/src/data/examples/ko/08_Math/16_Noise3D.js b/src/data/examples/ko/08_Math/16_Noise3D.js new file mode 100644 index 0000000000..94bd75841d --- /dev/null +++ b/src/data/examples/ko/08_Math/16_Noise3D.js @@ -0,0 +1,48 @@ +/* + * @name Noise3D + * @frame 710,400 (optional) + * @description Using 3D noise to create simple animated texture. + */ + +let noiseVal; +//Increment x by 0.01 +let x_increment = 0.01; +//Increment z by 0.02 every draw() cycle +let z_increment = 0.02; + +//Offset values +let z_off, y_off, x_off; + +function setup() { + //Create the Canvas + createCanvas(640, 360); + //Define frame rate + frameRate(20); + //Initial value of z_off + z_off = 0; +} + +function draw() { + x_off = 0; + y_off = 0; + //Make the background black + background(0); + //Adjust the noice detail + noiseDetail(8, 0.65); + + //For each x,y calculate noice value + for (let y = 0; y < height; y++) { + x_off += x_increment; + y_off = 0; + + for (let x = 0; x < width; x++) { + //Calculate and Draw each pixel + noiseVal = noise(x_off, y_off, z_off); + stroke(noiseVal * 255); + y_off += x_increment; + point(x, y); + } + } + + z_off += z_increment; +} diff --git a/src/data/examples/ko/08_Math/17_Randomchords.js b/src/data/examples/ko/08_Math/17_Randomchords.js new file mode 100644 index 0000000000..709a148655 --- /dev/null +++ b/src/data/examples/ko/08_Math/17_Randomchords.js @@ -0,0 +1,35 @@ +/* + * @name Random Chords + * @description Accumulates random chords of a circle. Each chord in translucent + * so they accumulate to give the illusion of a shaded sphere. + * Contributed by Aatish Bhatia, inspired by Anders Hoff + */ + +function setup() { + createCanvas(400, 400); + background(255, 255, 255); + + // translucent stroke using alpha value + stroke(0, 0, 0, 15); +} + +function draw() { + // draw two random chords each frame + randomChord(); + randomChord(); +} + +function randomChord() { + // find a random point on a circle + let angle1 = random(0, 2 * PI); + let xpos1 = 200 + 200 * cos(angle1); + let ypos1 = 200 + 200 * sin(angle1); + + // find another random point on the circle + let angle2 = random(0, 2 * PI); + let xpos2 = 200 + 200 * cos(angle2); + let ypos2 = 200 + 200 * sin(angle2); + + // draw a line between them + line(xpos1, ypos1, xpos2, ypos2); +} diff --git a/src/data/examples/ko/08_Math/18_Map.js b/src/data/examples/ko/08_Math/18_Map.js new file mode 100644 index 0000000000..a7b4d86058 --- /dev/null +++ b/src/data/examples/ko/08_Math/18_Map.js @@ -0,0 +1,22 @@ +/* + * @name Map + * @description Use the map() function to take any number and scale it to a + * new number that is more useful for the project that you are working on. + * For example, use the numbers from the mouse position to control the size or color of a shape. + * In this example, the mouse’s x-coordinate (numbers between 0 and 360) are scaled to new numbers + * to define the color and size of a circle. + */ +function setup() { + createCanvas(640, 400); + noStroke(); +} + +function draw() { + background(0); + // Scale the mouseX value from 0 to 640 to a range between 0 and 175 + let c = map(mouseX, 0, width, 0, 175); + // Scale the mouseX value from 0 to 640 to a range between 40 and 300 + let d = map(mouseX, 0, width, 40, 300); + fill(255, c, 0); + ellipse(width/2, height/2, d, d); +} diff --git a/src/data/examples/ko/09_Simulate/00_Forces.js b/src/data/examples/ko/09_Simulate/00_Forces.js new file mode 100644 index 0000000000..653c3992a1 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/00_Forces.js @@ -0,0 +1,148 @@ +/* + * @name Forces + * @description Demonstration of multiple force acting on bodies + * (natureofcode.com) + */ +// Demonstration of multiple force acting on +// bodies (Mover class) +// Bodies experience gravity continuously +// Bodies experience fluid resistance when in "water" + +// Five moving bodies +let movers = []; + +// Liquid +let liquid; + +function setup() { + createCanvas(640, 360); + reset(); + // Create liquid object + liquid = new Liquid(0, height / 2, width, height / 2, 0.1); +} + +function draw() { + background(127); + + // Draw water + liquid.display(); + + for (let i = 0; i < movers.length; i++) { + + // Is the Mover in the liquid? + if (liquid.contains(movers[i])) { + // Calculate drag force + let dragForce = liquid.calculateDrag(movers[i]); + // Apply drag force to Mover + movers[i].applyForce(dragForce); + } + + // Gravity is scaled by mass here! + let gravity = createVector(0, 0.1 * movers[i].mass); + // Apply gravity + movers[i].applyForce(gravity); + + // Update and display + movers[i].update(); + movers[i].display(); + movers[i].checkEdges(); + } + +} + + +function mousePressed() { + reset(); +} + +// Restart all the Mover objects randomly +function reset() { + for (let i = 0; i < 9; i++) { + movers[i] = new Mover(random(0.5, 3), 40 + i * 70, 0); + } +} + +let Liquid = function(x, y, w, h, c) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.c = c; +}; + +// Is the Mover in the Liquid? +Liquid.prototype.contains = function(m) { + let l = m.position; + return l.x > this.x && l.x < this.x + this.w && + l.y > this.y && l.y < this.y + this.h; +}; + +// Calculate drag force +Liquid.prototype.calculateDrag = function(m) { + // Magnitude is coefficient * speed squared + let speed = m.velocity.mag(); + let dragMagnitude = this.c * speed * speed; + + // Direction is inverse of velocity + let dragForce = m.velocity.copy(); + dragForce.mult(-1); + + // Scale according to magnitude + // dragForce.setMag(dragMagnitude); + dragForce.normalize(); + dragForce.mult(dragMagnitude); + return dragForce; +}; + +Liquid.prototype.display = function() { + noStroke(); + fill(50); + rect(this.x, this.y, this.w, this.h); +}; + +function Mover(m, x, y) { + this.mass = m; + this.position = createVector(x, y); + this.velocity = createVector(0, 0); + this.acceleration = createVector(0, 0); +} + +// Newton's 2nd law: F = M * A +// or A = F / M +Mover.prototype.applyForce = function(force) { + let f = p5.Vector.div(force, this.mass); + this.acceleration.add(f); +}; + +Mover.prototype.update = function() { + // Velocity changes according to acceleration + this.velocity.add(this.acceleration); + // position changes by velocity + this.position.add(this.velocity); + // We must clear acceleration each frame + this.acceleration.mult(0); +}; + +Mover.prototype.display = function() { + stroke(0); + strokeWeight(2); + fill(255,127); + ellipse(this.position.x, this.position.y, this.mass * 16, this.mass * 16); +}; + +// Bounce off bottom of window +Mover.prototype.checkEdges = function() { + if (this.position.y > (height - this.mass * 8)) { + // A little dampening when hitting the bottom + this.velocity.y *= -0.9; + this.position.y = (height - this.mass * 8); + } +}; + + + + + + + + diff --git a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js new file mode 100644 index 0000000000..a026e4623c --- /dev/null +++ b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js @@ -0,0 +1,69 @@ +/* + * @name Particle System + * @description This is a basic Particle System + * (natureofcode.com) + */ +let system; + +function setup() { + createCanvas(720, 400); + system = new ParticleSystem(createVector(width / 2, 50)); +} + +function draw() { + background(51); + system.addParticle(); + system.run(); +} + +// A simple Particle class +let Particle = function(position) { + this.acceleration = createVector(0, 0.05); + this.velocity = createVector(random(-1, 1), random(-1, 0)); + this.position = position.copy(); + this.lifespan = 255; +}; + +Particle.prototype.run = function() { + this.update(); + this.display(); +}; + +// Method to update position +Particle.prototype.update = function(){ + this.velocity.add(this.acceleration); + this.position.add(this.velocity); + this.lifespan -= 2; +}; + +// Method to display +Particle.prototype.display = function() { + stroke(200, this.lifespan); + strokeWeight(2); + fill(127, this.lifespan); + ellipse(this.position.x, this.position.y, 12, 12); +}; + +// Is the particle still useful? +Particle.prototype.isDead = function(){ + return this.lifespan < 0; +}; + +let ParticleSystem = function(position) { + this.origin = position.copy(); + this.particles = []; +}; + +ParticleSystem.prototype.addParticle = function() { + this.particles.push(new Particle(this.origin)); +}; + +ParticleSystem.prototype.run = function() { + for (let i = this.particles.length-1; i >= 0; i--) { + let p = this.particles[i]; + p.run(); + if (p.isDead()) { + this.particles.splice(i, 1); + } + } +}; diff --git a/src/data/examples/ko/09_Simulate/02_Flocking.js b/src/data/examples/ko/09_Simulate/02_Flocking.js new file mode 100644 index 0000000000..345a22721d --- /dev/null +++ b/src/data/examples/ko/09_Simulate/02_Flocking.js @@ -0,0 +1,229 @@ +/* + * @name Flocking + * @description Demonstration of Craig Reynolds' "Flocking" behavior. + * See: http://www.red3d.com/cwr/ + * Rules: Cohesion, Separation, Alignment + * (from natureofcode.com). + * Drag mouse to add boids into the system. + */ + + +let flock; + +function setup() { + createCanvas(640, 360); + createP("Drag the mouse to generate new boids."); + + flock = new Flock(); + // Add an initial set of boids into the system + for (let i = 0; i < 100; i++) { + let b = new Boid(width / 2,height / 2); + flock.addBoid(b); + } +} + +function draw() { + background(51); + flock.run(); +} + +// Add a new boid into the System +function mouseDragged() { + flock.addBoid(new Boid(mouseX, mouseY)); +} + +// The Nature of Code +// Daniel Shiffman +// http://natureofcode.com + +// Flock object +// Does very little, simply manages the array of all the boids + +function Flock() { + // An array for all the boids + this.boids = []; // Initialize the array +} + +Flock.prototype.run = function() { + for (let i = 0; i < this.boids.length; i++) { + this.boids[i].run(this.boids); // Passing the entire list of boids to each boid individually + } +} + +Flock.prototype.addBoid = function(b) { + this.boids.push(b); +} + +// The Nature of Code +// Daniel Shiffman +// http://natureofcode.com + +// Boid class +// Methods for Separation, Cohesion, Alignment added + +function Boid(x, y) { + this.acceleration = createVector(0, 0); + this.velocity = createVector(random(-1, 1), random(-1, 1)); + this.position = createVector(x, y); + this.r = 3.0; + this.maxspeed = 3; // Maximum speed + this.maxforce = 0.05; // Maximum steering force +} + +Boid.prototype.run = function(boids) { + this.flock(boids); + this.update(); + this.borders(); + this.render(); +} + +Boid.prototype.applyForce = function(force) { + // We could add mass here if we want A = F / M + this.acceleration.add(force); +} + +// We accumulate a new acceleration each time based on three rules +Boid.prototype.flock = function(boids) { + let sep = this.separate(boids); // Separation + let ali = this.align(boids); // Alignment + let coh = this.cohesion(boids); // Cohesion + // Arbitrarily weight these forces + sep.mult(1.5); + ali.mult(1.0); + coh.mult(1.0); + // Add the force vectors to acceleration + this.applyForce(sep); + this.applyForce(ali); + this.applyForce(coh); +} + +// Method to update location +Boid.prototype.update = function() { + // Update velocity + this.velocity.add(this.acceleration); + // Limit speed + this.velocity.limit(this.maxspeed); + this.position.add(this.velocity); + // Reset accelertion to 0 each cycle + this.acceleration.mult(0); +} + +// A method that calculates and applies a steering force towards a target +// STEER = DESIRED MINUS VELOCITY +Boid.prototype.seek = function(target) { + let desired = p5.Vector.sub(target,this.position); // A vector pointing from the location to the target + // Normalize desired and scale to maximum speed + desired.normalize(); + desired.mult(this.maxspeed); + // Steering = Desired minus Velocity + let steer = p5.Vector.sub(desired,this.velocity); + steer.limit(this.maxforce); // Limit to maximum steering force + return steer; +} + +Boid.prototype.render = function() { + // Draw a triangle rotated in the direction of velocity + let theta = this.velocity.heading() + radians(90); + fill(127); + stroke(200); + push(); + translate(this.position.x, this.position.y); + rotate(theta); + beginShape(); + vertex(0, -this.r * 2); + vertex(-this.r, this.r * 2); + vertex(this.r, this.r * 2); + endShape(CLOSE); + pop(); +} + +// Wraparound +Boid.prototype.borders = function() { + if (this.position.x < -this.r) this.position.x = width + this.r; + if (this.position.y < -this.r) this.position.y = height + this.r; + if (this.position.x > width + this.r) this.position.x = -this.r; + if (this.position.y > height + this.r) this.position.y = -this.r; +} + +// Separation +// Method checks for nearby boids and steers away +Boid.prototype.separate = function(boids) { + let desiredseparation = 25.0; + let steer = createVector(0, 0); + let count = 0; + // For every boid in the system, check if it's too close + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position,boids[i].position); + // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) + if ((d > 0) && (d < desiredseparation)) { + // Calculate vector pointing away from neighbor + let diff = p5.Vector.sub(this.position, boids[i].position); + diff.normalize(); + diff.div(d); // Weight by distance + steer.add(diff); + count++; // Keep track of how many + } + } + // Average -- divide by how many + if (count > 0) { + steer.div(count); + } + + // As long as the vector is greater than 0 + if (steer.mag() > 0) { + // Implement Reynolds: Steering = Desired - Velocity + steer.normalize(); + steer.mult(this.maxspeed); + steer.sub(this.velocity); + steer.limit(this.maxforce); + } + return steer; +} + +// Alignment +// For every nearby boid in the system, calculate the average velocity +Boid.prototype.align = function(boids) { + let neighbordist = 50; + let sum = createVector(0,0); + let count = 0; + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position,boids[i].position); + if ((d > 0) && (d < neighbordist)) { + sum.add(boids[i].velocity); + count++; + } + } + if (count > 0) { + sum.div(count); + sum.normalize(); + sum.mult(this.maxspeed); + let steer = p5.Vector.sub(sum, this.velocity); + steer.limit(this.maxforce); + return steer; + } else { + return createVector(0, 0); + } +} + +// Cohesion +// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location +Boid.prototype.cohesion = function(boids) { + let neighbordist = 50; + let sum = createVector(0, 0); // Start with empty vector to accumulate all locations + let count = 0; + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position,boids[i].position); + if ((d > 0) && (d < neighbordist)) { + sum.add(boids[i].position); // Add location + count++; + } + } + if (count > 0) { + sum.div(count); + return this.seek(sum); // Steer towards the location + } else { + return createVector(0, 0); + } +} + + diff --git a/src/data/examples/ko/09_Simulate/03_WolframCA.js b/src/data/examples/ko/09_Simulate/03_WolframCA.js new file mode 100644 index 0000000000..06b9bc5765 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/03_WolframCA.js @@ -0,0 +1,73 @@ +/* + * @name Wolfram CA + * @description Simple demonstration of a Wolfram 1-dimensional cellular automata + * (natureofcode.com) + */ + +let w = 10; +// An array of 0s and 1s +let cells; + + // We arbitrarily start with just the middle cell having a state of "1" +let generation = 0; + +// An array to store the ruleset, for example {0,1,1,0,1,1,0,1} +let ruleset = [0, 1, 0, 1, 1, 0, 1, 0]; + +function setup() { + createCanvas(640, 400); + cells = Array(floor(width / w)); + for (let i = 0; i < cells.length; i++) { + cells[i] = 0; + } + cells[cells.length/2] = 1; + +} + +function draw() { + for (let i = 0; i < cells.length; i++) { + if (cells[i] === 1) { + fill(200); + } else { + fill(51); + noStroke(); + rect(i * w, generation * w, w, w); + } + } + if (generation < height/w) { + generate(); + } +} + +// The process of creating the new generation +function generate() { + // First we create an empty array for the new values + let nextgen = Array(cells.length); + // For every spot, determine new state by examing current state, and neighbor states + // Ignore edges that only have one neighor + for (let i = 1; i < cells.length-1; i++) { + let left = cells[i-1]; // Left neighbor state + let me = cells[i]; // Current state + let right = cells[i+1]; // Right neighbor state + nextgen[i] = rules(left, me, right); // Compute next generation state based on ruleset + } + // The current generation is the new generation + cells = nextgen; + generation++; +} + + +// Implementing the Wolfram rules +// Could be improved and made more concise, but here we can explicitly see what is going on for each case +function rules(a, b, c) { + if (a == 1 && b == 1 && c == 1) return ruleset[0]; + if (a == 1 && b == 1 && c == 0) return ruleset[1]; + if (a == 1 && b == 0 && c == 1) return ruleset[2]; + if (a == 1 && b == 0 && c == 0) return ruleset[3]; + if (a == 0 && b == 1 && c == 1) return ruleset[4]; + if (a == 0 && b == 1 && c == 0) return ruleset[5]; + if (a == 0 && b == 0 && c == 1) return ruleset[6]; + if (a == 0 && b == 0 && c == 0) return ruleset[7]; + return 0; +} + diff --git a/src/data/examples/ko/09_Simulate/04_GameOfLife.js b/src/data/examples/ko/09_Simulate/04_GameOfLife.js new file mode 100644 index 0000000000..81d5be870f --- /dev/null +++ b/src/data/examples/ko/09_Simulate/04_GameOfLife.js @@ -0,0 +1,94 @@ +/* + * @name Game of Life + * @description A basic implementation of John Conway's Game of Life CA + * (natureofcode.com) + */ + +let w; +let columns; +let rows; +let board; +let next; + +function setup() { + createCanvas(720, 400); + w = 20; + // Calculate columns and rows + columns = floor(width / w); + rows = floor(height / w); + // Wacky way to make a 2D array is JS + board = new Array(columns); + for (let i = 0; i < columns; i++) { + board[i] = new Array(rows); + } + // Going to use multiple 2D arrays and swap them + next = new Array(columns); + for (i = 0; i < columns; i++) { + next[i] = new Array(rows); + } + init(); +} + +function draw() { + background(255); + generate(); + for ( let i = 0; i < columns;i++) { + for ( let j = 0; j < rows;j++) { + if ((board[i][j] == 1)) fill(0); + else fill(255); + stroke(0); + rect(i * w, j * w, w-1, w-1); + } + } + +} + +// reset board when mouse is pressed +function mousePressed() { + init(); +} + +// Fill board randomly +function init() { + for (let i = 0; i < columns; i++) { + for (let j = 0; j < rows; j++) { + // Lining the edges with 0s + if (i == 0 || j == 0 || i == columns-1 || j == rows-1) board[i][j] = 0; + // Filling the rest randomly + else board[i][j] = floor(random(2)); + next[i][j] = 0; + } + } +} + +// The process of creating the new generation +function generate() { + + // Loop through every spot in our 2D array and check spots neighbors + for (let x = 1; x < columns - 1; x++) { + for (let y = 1; y < rows - 1; y++) { + // Add up all the states in a 3x3 surrounding grid + let neighbors = 0; + for (let i = -1; i <= 1; i++) { + for (let j = -1; j <= 1; j++) { + neighbors += board[x+i][y+j]; + } + } + + // A little trick to subtract the current cell's state since + // we added it in the above loop + neighbors -= board[x][y]; + // Rules of Life + if ((board[x][y] == 1) && (neighbors < 2)) next[x][y] = 0; // Loneliness + else if ((board[x][y] == 1) && (neighbors > 3)) next[x][y] = 0; // Overpopulation + else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1; // Reproduction + else next[x][y] = board[x][y]; // Stasis + } + } + + // Swap! + let temp = board; + board = next; + next = temp; +} + diff --git a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js new file mode 100644 index 0000000000..afd65424c1 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js @@ -0,0 +1,138 @@ +/* + * @name Multiple Particle Systems + * @description Click the mouse to generate a burst of particles at mouse location.
Each burst is one instance of a particle system with Particles and CrazyParticles (a subclass of Particle).
Note use of Inheritance and Polymorphism here.
+ * Original by Daniel Shiffman. + */ +let systems; + +function setup() { + createCanvas(710, 400); + systems = []; +} + +function draw() { + background(51); + background(0); + for (i = 0; i < systems.length; i++) { + systems[i].run(); + systems[i].addParticle(); + } + if (systems.length == 0) { + fill(255); + textAlign(CENTER); + textSize(32); + text("click mouse to add particle systems", width / 2, height / 2); + } +} + +function mousePressed() { + this.p = new ParticleSystem(createVector(mouseX, mouseY)); + systems.push(p); +} + +// A simple Particle class +let Particle = function(position) { + this.acceleration = createVector(0, 0.05); + this.velocity = createVector(random(-1, 1), random(-1, 0)); + this.position = position.copy(); + this.lifespan = 255.0; +}; + +Particle.prototype.run = function() { + this.update(); + this.display(); +}; + +// Method to update position +Particle.prototype.update = function(){ + this.velocity.add(this.acceleration); + this.position.add(this.velocity); + this.lifespan -= 2; +}; + +// Method to display +Particle.prototype.display = function () { + stroke(200, this.lifespan); + strokeWeight(2); + fill(127, this.lifespan); + ellipse(this.position.x, this.position.y, 12, 12); +}; + +// Is the particle still useful? +Particle.prototype.isDead = function () { + if (this.lifespan < 0) { + return true; + } else { + return false; + } +}; + +let ParticleSystem = function (position) { + this.origin = position.copy(); + this.particles = []; +}; + +ParticleSystem.prototype.addParticle = function () { + // Add either a Particle or CrazyParticle to the system + if (int(random(0, 2)) == 0) { + p = new Particle(this.origin); + } + else { + p = new CrazyParticle(this.origin); + } + this.particles.push(p); +}; + +ParticleSystem.prototype.run = function () { + for (let i = this.particles.length - 1; i >= 0; i--) { + let p = this.particles[i]; + p.run(); + if (p.isDead()) { + this.particles.splice(i, 1); + } + } +}; + +// A subclass of Particle + +function CrazyParticle(origin) { + // Call the parent constructor, making sure (using Function#call) + // that "this" is set correctly during the call + Particle.call(this, origin); + + // Initialize our added properties + this.theta = 0.0; +}; + +// Create a Crazy.prototype object that inherits from Particle.prototype. +// Note: A common error here is to use "new Particle()" to create the +// Crazy.prototype. That's incorrect for several reasons, not least +// that we don't have anything to give Particle for the "origin" +// argument. The correct place to call Particle is above, where we call +// it from Crazy. +CrazyParticle.prototype = Object.create(Particle.prototype); // See note below + +// Set the "constructor" property to refer to CrazyParticle +CrazyParticle.prototype.constructor = CrazyParticle; + +// Notice we don't have the method run() here; it is inherited from Particle + +// This update() method overrides the parent class update() method +CrazyParticle.prototype.update=function() { + Particle.prototype.update.call(this); + // Increment rotation based on horizontal velocity + this.theta += (this.velocity.x * this.velocity.mag()) / 10.0; +} + +// This display() method overrides the parent class display() method +CrazyParticle.prototype.display=function() { + // Render the ellipse just like in a regular particle + Particle.prototype.display.call(this); + // Then add a rotating line + push(); + translate(this.position.x, this.position.y); + rotate(this.theta); + stroke(255, this.lifespan); + line(0, 0, 25, 0); + pop(); +} diff --git a/src/data/examples/ko/09_Simulate/06_Spirograph.js b/src/data/examples/ko/09_Simulate/06_Spirograph.js new file mode 100644 index 0000000000..d1f711ab30 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/06_Spirograph.js @@ -0,0 +1,73 @@ + +/* + * @name Spirograph + * @description This sketch uses simple transformations to create a + * Spirograph-like effect with interlocking circles (called sines). + * Press the spacebar to switch between tracing and showing the underlying geometry.
+ * Example created by R. Luke DuBois.
+ * http://en.wikipedia.org/wiki/Spirograph + */ +let NUMSINES = 20; // how many of these things can we do at once? +let sines = new Array(NUMSINES); // an array to hold all the current angles +let rad; // an initial radius value for the central sine +let i; // a counter variable + +// play with these to get a sense of what's going on: +let fund = 0.005; // the speed of the central sine +let ratio = 1; // what multiplier for speed is each additional sine? +let alpha = 50; // how opaque is the tracing system + +let trace = false; // are we tracing? + +function setup() { + createCanvas(710, 400); + + rad = height / 4; // compute radius for central circle + background(204); // clear the screen + + for (let i = 0; i + * Example created by R. Luke DuBois.
+ * https://en.wikipedia.org/wiki/L-system + */ +// TURTLE STUFF: +let x, y; // the current position of the turtle +let currentangle = 0; // which way the turtle is pointing +let step = 20; // how much the turtle moves with each 'F' +let angle = 90; // how much the turtle turns with a '-' or '+' + +// LINDENMAYER STUFF (L-SYSTEMS) +let thestring = 'A'; // "axiom" or start of the string +let numloops = 5; // how many iterations to pre-compute +let therules = []; // array for rules +therules[0] = ['A', '-BF+AFA+FB-']; // first rule +therules[1] = ['B', '+AF-BFB-FA+']; // second rule + +let whereinstring = 0; // where in the L-system are we? + +function setup() { + createCanvas(710, 400); + background(255); + stroke(0, 0, 0, 255); + + // start the x and y position at lower-left corner + x = 0; + y = height-1; + + // COMPUTE THE L-SYSTEM + for (let i = 0; i < numloops; i++) { + thestring = lindenmayer(thestring); + } +} + +function draw() { + + // draw the current character in the string: + drawIt(thestring[whereinstring]); + + // increment the point for where we're reading the string. + // wrap around at the end. + whereinstring++; + if (whereinstring > thestring.length-1) whereinstring = 0; + +} + +// interpret an L-system +function lindenmayer(s) { + let outputstring = ''; // start a blank output string + + // iterate through 'therules' looking for symbol matches: + for (let i = 0; i < s.length; i++) { + let ismatch = 0; // by default, no match + for (let j = 0; j < therules.length; j++) { + if (s[i] == therules[j][0]) { + outputstring += therules[j][1]; // write substitution + ismatch = 1; // we have a match, so don't copy over symbol + break; // get outta this for() loop + } + } + // if nothing matches, just copy the symbol over. + if (ismatch == 0) outputstring+= s[i]; + } + + return outputstring; // send out the modified string +} + +// this is a custom function that draws turtle commands +function drawIt(k) { + + if (k=='F') { // draw forward + // polar to cartesian based on step and currentangle: + let x1 = x + step*cos(radians(currentangle)); + let y1 = y + step*sin(radians(currentangle)); + line(x, y, x1, y1); // connect the old and the new + + // update the turtle's position: + x = x1; + y = y1; + } else if (k == '+') { + currentangle += angle; // turn left + } else if (k == '-') { + currentangle -= angle; // turn right + } + + // give me some random color values: + let r = random(128, 255); + let g = random(0, 192); + let b = random(0, 50); + let a = random(50, 100); + + // pick a gaussian (D&D) distribution for the radius: + let radius = 0; + radius += random(0, 15); + radius += random(0, 15); + radius += random(0, 15); + radius = radius / 3; + + // draw the stuff: + fill(r, g, b, a); + ellipse(x, y, radius, radius); +} \ No newline at end of file diff --git a/src/data/examples/ko/09_Simulate/08_Spring.js b/src/data/examples/ko/09_Simulate/08_Spring.js new file mode 100644 index 0000000000..b307142cca --- /dev/null +++ b/src/data/examples/ko/09_Simulate/08_Spring.js @@ -0,0 +1,92 @@ +/* + * @name Spring + * @frame 710, 400 + * @description Click, drag, and release the horizontal bar to start the spring. + */ +// Spring drawing constants for top bar +let springHeight = 32, + left, + right, + maxHeight = 200, + minHeight = 100, + over = false, + move = false; + +// Spring simulation constants +let M = 0.8, // Mass + K = 0.2, // Spring constant + D = 0.92, // Damping + R = 150; // Rest position + +// Spring simulation variables +let ps = R, // Position + vs = 0.0, // Velocity + as = 0, // Acceleration + f = 0; // Force + +function setup() { + createCanvas(710, 400); + rectMode(CORNERS); + noStroke(); + left = width / 2 - 100; + right = width / 2 + 100; +} + +function draw() { + background(102); + updateSpring(); + drawSpring(); +} + +function drawSpring() { + // Draw base + fill(0.2); + let baseWidth = 0.5 * ps + -8; + rect(width / 2 - baseWidth, ps + springHeight, width / 2 + baseWidth, height); + + // Set color and draw top bar + if (over || move) { + fill(255); + } else { + fill(204); + } + + rect(left, ps, right, ps + springHeight); +} + +function updateSpring() { + // Update the spring position + if ( !move ) { + f = -K * ( ps - R ); // f=-ky + as = f / M; // Set the acceleration, f=ma == a=f/m + vs = D * (vs + as); // Set the velocity + ps = ps + vs; // Updated position + } + + if (abs(vs) < 0.1) { + vs = 0.0; + } + + // Test if mouse if over the top bar + if (mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + springHeight) { + over = true; + } else { + over = false; + } + + // Set and constrain the position of top bar + if (move) { + ps = mouseY - springHeight / 2; + ps = constrain(ps, minHeight, maxHeight); + } +} + +function mousePressed() { + if (over) { + move = true; + } +} + +function mouseReleased() { + move = false; +} diff --git a/src/data/examples/ko/09_Simulate/09_Springs.js b/src/data/examples/ko/09_Simulate/09_Springs.js new file mode 100644 index 0000000000..43d6f7e6d6 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/09_Springs.js @@ -0,0 +1,147 @@ +/* + * @name Springs + * @frame 710,400 + * @description Move the mouse over one of the circles and click to re-position. + * When you release the mouse, it will snap back into position. + * Each circle has a slightly different behavior. + * (ported from https://processing.org/examples/springs.html) + */ +let num = 3; +let springs = []; + +function setup() { + createCanvas(710, 400); + noStroke(); + + springs[0] = new Spring(240, 260, 40, 0.98, 8.0, 0.1, springs, 0); + springs[1] = new Spring(320, 210, 120, 0.95, 9.0, 0.1, springs, 1); + springs[2] = new Spring(180, 170, 200, 0.90, 9.9, 0.1, springs, 2); +} + +function draw() { + background(51); + + for (let i = 0; i < num; i++) { + springs[i].update(); + springs[i].display(); + } +} + +function mousePressed() { + for (let i = 0; i < num; i++) { + springs[i].pressed(); + } +} + +function mouseReleased() { + for (let i = 0; i < num; i++) { + springs[i].released(); + } +} + +// Spring class +function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) { + // Screen values + // this.xpos = _x; + // this.ypos = _y; + + this.x_pos = _x; + this.y_pos= _y; + + this.size = 20; + this.size = _s; + + this.over = false; + this.move = false; + + // Spring simulation constants + this.mass = _m; // Mass + this.k = 0.2; // Spring constant + this.k = _k_in; + this.damp = _d; // Damping + this.rest_posx = _x; // Rest position X + this.rest_posy = _y; // Rest position Y + + // Spring simulation variables + //float pos = 20.0; // Position + this.velx = 0.0; // X Velocity + this.vely = 0.0; // Y Velocity + this.accel = 0; // Acceleration + this.force = 0; // Force + + this.friends = _others; + this.id = _id; + + this.update = function() { + + if (this.move) { + this.rest_posy = mouseY; + this.rest_posx = mouseX; + } + + this.force = -this.k * (this.y_pos - this.rest_posy); // f=-ky + this.accel = this.force / this.mass; // Set the acceleration, f=ma == a=f/m + this.vely = this.damp * (this.vely + this.accel); // Set the velocity + this.y_pos = this.y_pos + this.vely; // Updated position + + + this.force = -this.k * (this.x_pos - this.rest_posx); // f=-ky + this.accel = this.force / this.mass; // Set the acceleration, f=ma == a=f/m + this.velx = this.damp * (this.velx + this.accel); // Set the velocity + this.x_pos = this.x_pos + this.velx; // Updated position + + + if ((this.overEvent() || this.move) && !(this.otherOver()) ) { + this.over = true; + } else { + this.over = false; + } + } + + // Test to see if mouse is over this spring + this.overEvent = function() { + let disX = this.x_pos - mouseX; + let disY = this.y_pos - mouseY; + let dis = createVector(disX, disY); + if (dis.mag() < this.size / 2 ) { + return true; + } else { + return false; + } + } + + // Make sure no other springs are active + this.otherOver = function() { + for (let i = 0; i < num; i++) { + if (i != this.id) { + if (this.friends[i].over == true) { + return true; + } + } + } + return false; + } + + this.display = function() { + if (this.over) { + fill(153); + } else { + fill(255); + } + ellipse(this.x_pos, this.y_pos, this.size, this.size); + } + + this.pressed = function() { + if (this.over) { + this.move = true; + } else { + this.move = false; + } + } + + this.released = function() { + this.move = false; + this.rest_posx = this.y_pos; + this.rest_posy = this.y_pos; + } +}; \ No newline at end of file diff --git a/src/data/examples/ko/09_Simulate/10_SoftBody.js b/src/data/examples/ko/09_Simulate/10_SoftBody.js new file mode 100644 index 0000000000..b227393300 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/10_SoftBody.js @@ -0,0 +1,110 @@ +/* + * @name Soft Body + * @description Original example by Ira Greenberg. + *

Softbody dynamics simulation using curveVertex() and curveTightness(). + */ +// center point +let centerX = 0.0, centerY = 0.0; + +let radius = 45, rotAngle = -90; +let accelX = 0.0, accelY = 0.0; +let deltaX = 0.0, deltaY = 0.0; +let springing = 0.0009, damping = 0.98; + +//corner nodes +let nodes = 5; + +//zero fill arrays +let nodeStartX = []; +let nodeStartY = []; +let nodeX = []; +let nodeY = []; +let angle = []; +let frequency = []; + +// soft-body dynamics +let organicConstant = 1.0; + +function setup() { + createCanvas(710, 400); + + //center shape in window + centerX = width / 2; + centerY = height / 2; + + //initialize arrays to 0 + for (let i = 0; i < nodes; i++){ + nodeStartX[i] = 0; + nodeStartY[i] = 0; + nodeY[i] = 0; + nodeY[i] = 0; + angle[i] = 0; + } + + // iniitalize frequencies for corner nodes + for (let i = 0; i < nodes; i++){ + frequency[i] = random(5, 12); + } + + noStroke(); + frameRate(30); +} + +function draw() { + //fade background + fill(0, 100); + rect(0, 0, width, height); + drawShape(); + moveShape(); +} + +function drawShape() { + // calculate node starting locations + for (let i = 0; i < nodes; i++){ + nodeStartX[i] = centerX + cos(radians(rotAngle)) * radius; + nodeStartY[i] = centerY + sin(radians(rotAngle)) * radius; + rotAngle += 360.0 / nodes; + } + + // draw polygon + curveTightness(organicConstant); + fill(255); + beginShape(); + for (let i = 0; i < nodes; i++){ + curveVertex(nodeX[i], nodeY[i]); + } + for (let i = 0; i < nodes-1; i++){ + curveVertex(nodeX[i], nodeY[i]); + } + endShape(CLOSE); +} + +function moveShape() { + //move center point + deltaX = mouseX - centerX; + deltaY = mouseY - centerY; + + // create springing effect + deltaX *= springing; + deltaY *= springing; + accelX += deltaX; + accelY += deltaY; + + // move predator's center + centerX += accelX; + centerY += accelY; + + // slow down springing + accelX *= damping; + accelY *= damping; + + // change curve tightness + organicConstant = 1 - ((abs(accelX) + abs(accelY)) * 0.1); + + //move nodes + for (let i = 0; i < nodes; i++){ + nodeX[i] = nodeStartX[i] + sin(radians(angle[i])) * (accelX * 2); + nodeY[i] = nodeStartY[i] + sin(radians(angle[i])) * (accelY * 2); + angle[i] += frequency[i]; + } +} diff --git a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js new file mode 100644 index 0000000000..ddb21859d3 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js @@ -0,0 +1,180 @@ +/* + * @name SmokeParticles + * @description a port of Dan Shiffman's SmokeParticleSystem example originally + * for Processing. Creates smokey particles :p + */ + +// texture for the particle +let particle_texture = null; + +// variable holding our particle system +let ps = null; + +function preload() { + particle_texture = loadImage("assets/particle_texture.png"); +} + +function setup() { + + //set the canvas size + createCanvas(640, 360); + + //initialize our particle system + ps = new ParticleSystem(0, createVector(width / 2, height - 60), particle_texture); +} + +function draw() { + background(0); + + let dx = map(mouseX, 0, width, -0.2, 0.2); + let wind = createVector(dx, 0); + + ps.applyForce(wind); + ps.run(); + for (let i = 0; i < 2; i++) { + ps.addParticle(); + } + + // Draw an arrow representing the wind force + drawVector(wind, createVector(width / 2, 50, 0), 500); +} + +/** + * This function draws an arrow showing the direction our "wind" is blowing. + */ +function drawVector(v, loc, scale){ + push(); + let arrowsize = 4; + translate(loc.x, loc.y); + stroke(255); + rotate(v.heading()); + + let len = v.mag() * scale; + line(0, 0, len,0); + line(len, 0, len-arrowsize, +arrowsize / 2); + line(len, 0, len-arrowsize, -arrowsize / 2); + pop(); +} +//========= PARTICLE SYSTEM =========== + +/** + * A basic particle system class + * @param num the number of particles + * @param v the origin of the particle system + * @param img_ a texture for each particle in the system + * @constructor + */ +let ParticleSystem = function(num, v, img_) { + + this.particles = []; + this.origin = v.copy(); // we make sure to copy the vector value in case we accidentally mutate the original by accident + this.img = img_ + for(let i = 0; i < num; ++i){ + this.particles.push(new Particle(this.origin, this.img)); + } +}; + +/** + * This function runs the entire particle system. + */ +ParticleSystem.prototype.run = function() { + + // cache length of the array we're going to loop into a variable + // You may see .length in a for loop, from time to time but + // we cache it here because otherwise the length is re-calculated for each iteration of a loop + let len = this.particles.length; + + //loop through and run particles + for (let i = len - 1; i >= 0; i--) { + let particle = this.particles[i]; + particle.run(); + + // if the particle is dead, we remove it. + // javascript arrays don't have a "remove" function but "splice" works just as well. + // we feed it an index to start at, then how many numbers from that point to remove. + if (particle.isDead()) { + this.particles.splice(i, 1); + } + } +} + +/** + * Method to add a force vector to all particles currently in the system + * @param dir a p5.Vector describing the direction of the force. + */ +ParticleSystem.prototype.applyForce = function(dir) { + let len = this.particles.length; + for(let i = 0; i < len; ++i){ + this.particles[i].applyForce(dir); + } +} + +/** + * Adds a new particle to the system at the origin of the system and with + * the originally set texture. + */ +ParticleSystem.prototype.addParticle = function() { + this.particles.push(new Particle(this.origin, this.img)); +} + +//========= PARTICLE =========== +/** + * A simple Particle class, renders the particle as an image + */ +let Particle = function (pos, img_) { + this.loc = pos.copy(); + + let vx = randomGaussian() * 0.3; + let vy = randomGaussian() * 0.3 - 1.0; + + this.vel = createVector(vx, vy); + this.acc = createVector(); + this.lifespan = 100.0; + this.texture = img_; +} + +/** + * Simulataneously updates and displays a particle. + */ +Particle.prototype.run = function() { + this.update(); + this.render(); +} + +/** + * A function to display a particle + */ +Particle.prototype.render = function() { + imageMode(CENTER); + tint(255, this.lifespan); + image(this.texture, this.loc.x, this.loc.y); +} + +/** + * A method to apply a force vector to a particle. + */ +Particle.prototype.applyForce = function(f) { + this.acc.add(f); +} + +/** + * This method checks to see if the particle has reached the end of it's lifespan, + * if it has, return true, otherwise return false. + */ +Particle.prototype.isDead = function () { + if (this.lifespan <= 0.0) { + return true; + } else { + return false; + } +} + +/** + * This method updates the position of the particle. + */ +Particle.prototype.update = function() { + this.vel.add(this.acc); + this.loc.add(this.vel); + this.lifespan -= 2.5; + this.acc.mult(0); +} diff --git a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js new file mode 100755 index 0000000000..449e5ad27e --- /dev/null +++ b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js @@ -0,0 +1,46 @@ +/* + * @name Brownian Motion + * @description Recording random movement as a continuous line. + * Port of original example from the Processing examples page. + */ + +let num = 2000; +let range = 6; + +let ax = []; +let ay = []; + + +function setup() { + createCanvas(710, 400); + for ( let i = 0; i < num; i++ ) { + ax[i] = width / 2; + ay[i] = height / 2; + } + frameRate(30); +} + +function draw() { + background(51); + + // Shift all elements 1 place to the left + for ( let i = 1; i < num; i++ ) { + ax[i - 1] = ax[i]; + ay[i - 1] = ay[i]; + } + + // Put a new value at the end of the array + ax[num - 1] += random(-range, range); + ay[num - 1] += random(-range, range); + + // Constrain all points to the screen + ax[num - 1] = constrain(ax[num - 1], 0, width); + ay[num - 1] = constrain(ay[num - 1], 0, height); + + // Draw a line connecting the points + for ( let j = 1; j < num; j++ ) { + let val = j / num * 204.0 + 51; + stroke(val); + line(ax[j - 1], ay[j - 1], ax[j], ay[j]); + } +} \ No newline at end of file diff --git a/src/data/examples/ko/09_Simulate/13_Chain.js b/src/data/examples/ko/09_Simulate/13_Chain.js new file mode 100644 index 0000000000..ba52c54587 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/13_Chain.js @@ -0,0 +1,55 @@ +/* + * @name Chain + * @description One mass is attached to the mouse position and the other is attached the position of the other mass. The gravity in the environment pulls down on both. + * Ported from the Processing Examples page. + */ +let s1, s2; +let gravity = 9.0; +let mass = 2.0; + +function setup() { + createCanvas(720, 400); + fill(255, 126); + // Inputs: x, y, mass, gravity + s1 = new Spring2D(0.0, width / 2, mass, gravity); + s2 = new Spring2D(0.0, width / 2, mass, gravity); +} + +function draw() { + background(0); + s1.update(mouseX, mouseY); + s1.display(mouseX, mouseY); + s2.update(s1.x, s1.y); + s2.display(s1.x, s1.y); +} + +function Spring2D(xpos, ypos, m, g) { + this.x = xpos;// The x- and y-coordinates + this.y = ypos; + this.vx = 0; // The x- and y-axis velocities + this.vy = 0; + this.mass = m; + this.gravity = g; + this.radius = 30; + this.stiffness = 0.2; + this.damping = 0.7; + + this.update = function(targetX, targetY) { + let forceX = (targetX - this.x) * this.stiffness; + let ax = forceX / this.mass; + this.vx = this.damping * (this.vx + ax); + this.x += this.vx; + let forceY = (targetY - this.y) * this.stiffness; + forceY += this.gravity; + let ay = forceY / this.mass; + this.vy = this.damping * (this.vy + ay); + this.y += this.vy; + } + + this.display = function(nx, ny) { + noStroke(); + ellipse(this.x, this.y, this.radius * 2, this.radius * 2); + stroke(255); + line(this.x, this.y, nx, ny); + } +} \ No newline at end of file diff --git a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js new file mode 100755 index 0000000000..0956a80792 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js @@ -0,0 +1,63 @@ +/* + * @name Snowflakes + * @description Particle system simulating the motion of falling snowflakes. + * Uses an array of objects to hold the snowflake particles. + * Contributed by Aatish Bhatia. + */ + +let snowflakes = []; // array to hold snowflake objects + +function setup() { + createCanvas(400, 600); + fill(240); + noStroke(); +} + +function draw() { + background('brown'); + let t = frameCount / 60; // update time + + // create a random number of snowflakes each frame + for (let i = 0; i < random(5); i++) { + snowflakes.push(new snowflake()); // append snowflake object + } + + // loop through snowflakes with a for..of loop + for (let flake of snowflakes) { + flake.update(t); // update snowflake position + flake.display(); // draw snowflake + } +} + +// snowflake class +function snowflake() { + // initialize coordinates + this.posX = 0; + this.posY = random(-50, 0); + this.initialangle = random(0, 2 * PI); + this.size = random(2, 5); + + // radius of snowflake spiral + // chosen so the snowflakes are uniformly spread out in area + this.radius = sqrt(random(pow(width / 2, 2))); + + this.update = function(time) { + // x position follows a circle + let w = 0.6; // angular speed + let angle = w * time + this.initialangle; + this.posX = width / 2 + this.radius * sin(angle); + + // different size snowflakes fall at slightly different y speeds + this.posY += pow(this.size, 0.5); + + // delete snowflake if past end of screen + if (this.posY > height) { + let index = snowflakes.indexOf(this); + snowflakes.splice(index, 1); + } + }; + + this.display = function() { + ellipse(this.posX, this.posY, this.size); + }; +} diff --git a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js new file mode 100644 index 0000000000..fd93ffa845 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js @@ -0,0 +1,125 @@ +/* + * @name Penrose Tiles + * @frame 710,400 + * @description This is a port by David Blitz of the "Penrose Tile" example from processing.org/examples + */ + +let ds; + +function setup() { + createCanvas(710, 400); + ds = new PenroseLSystem(); + //please, play around with the following line + ds.simulate(5); +} + +function draw() { + background(0); + ds.render(); +} + +function PenroseLSystem() { + this.steps = 0; + + //these are axiom and rules for the penrose rhombus l-system + //a reference would be cool, but I couldn't find a good one + this.axiom = "[X]++[X]++[X]++[X]++[X]"; + this.ruleW = "YF++ZF----XF[-YF----WF]++"; + this.ruleX = "+YF--ZF[---WF--XF]+"; + this.ruleY = "-WF++XF[+++YF++ZF]-"; + this.ruleZ = "--YF++++WF[+ZF++++XF]--XF"; + + //please play around with the following two lines + this.startLength = 460.0; + this.theta = TWO_PI / 10.0; //36 degrees, try TWO_PI / 6.0, ... + this.reset(); +} + +PenroseLSystem.prototype.simulate = function (gen) { + while (this.getAge() < gen) { + this.iterate(this.production); + } +} + +PenroseLSystem.prototype.reset = function () { + this.production = this.axiom; + this.drawLength = this.startLength; + this.generations = 0; + } + +PenroseLSystem.prototype.getAge = function () { + return this.generations; + } + +//apply substitution rules to create new iteration of production string +PenroseLSystem.prototype.iterate = function() { + let newProduction = ""; + + for(let i=0; i < this.production.length; ++i) { + let step = this.production.charAt(i); + //if current character is 'W', replace current character + //by corresponding rule + if (step == 'W') { + newProduction = newProduction + this.ruleW; + } + else if (step == 'X') { + newProduction = newProduction + this.ruleX; + } + else if (step == 'Y') { + newProduction = newProduction + this.ruleY; + } + else if (step == 'Z') { + newProduction = newProduction + this.ruleZ; + } + else { + //drop all 'F' characters, don't touch other + //characters (i.e. '+', '-', '[', ']' + if (step != 'F') { + newProduction = newProduction + step; + } + } + } + + this.drawLength = this.drawLength * 0.5; + this.generations++; + this.production = newProduction; +} + +//convert production string to a turtle graphic +PenroseLSystem.prototype.render = function () { + translate(width / 2, height / 2); + + this.steps += 20; + if(this.steps > this.production.length) { + this.steps = this.production.length; + } + + for(let i=0; iRecursive Tree Example for Processing. + */ +let theta; + +function setup() { + createCanvas(710, 400); +} + +function draw() { + background(0); + frameRate(30); + stroke(255); + // Let's pick an angle 0 to 90 degrees based on the mouse position + let a = (mouseX / width) * 90; + // Convert it to radians + theta = radians(a); + // Start the tree from the bottom of the screen + translate(width/2,height); + // Draw a line 120 pixels + line(0,0,0,-120); + // Move to the end of that line + translate(0,-120); + // Start the recursive branching! + branch(120); + +} + +function branch(h) { + // Each branch will be 2/3rds the size of the previous one + h *= 0.66; + + // All recursive functions must have an exit condition!!!! + // Here, ours is when the length of the branch is 2 pixels or less + if (h > 2) { + push(); // Save the current state of transformation (i.e. where are we now) + rotate(theta); // Rotate by theta + line(0, 0, 0, -h); // Draw the branch + translate(0, -h); // Move to the end of the branch + branch(h); // Ok, now call myself to draw two new branches!! + pop(); // Whenever we get back here, we "pop" in order to restore the previous matrix state + + // Repeat the same thing, only branch off to the "left" this time! + push(); + rotate(-theta); + line(0, 0, 0, -h); + translate(0, -h); + branch(h); + pop(); + } +} diff --git a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js new file mode 100644 index 0000000000..76b0bdc4b2 --- /dev/null +++ b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js @@ -0,0 +1,86 @@ +/* + * @name The Mandelbrot Set + * @description Simple rendering of the Mandelbrot set. + * Based on Daniel Shiffman's Mandelbrot Example for Processing. + */ + +function setup() { + createCanvas(710, 400); + pixelDensity(1); + noLoop(); +} + +function draw() { + background(0); + + // Establish a range of values on the complex plane + // A different range will allow us to "zoom" in or out on the fractal + + // It all starts with the width, try higher or lower values + const w = 4; + const h = (w * height) / width; + + // Start at negative half the width and height + const xmin = -w/2; + const ymin = -h/2; + + // Make sure we can write to the pixels[] array. + // Only need to do this once since we don't do any other drawing. + loadPixels(); + + // Maximum number of iterations for each point on the complex plane + const maxiterations = 100; + + // x goes from xmin to xmax + const xmax = xmin + w; + // y goes from ymin to ymax + const ymax = ymin + h; + + // Calculate amount we increment x,y for each pixel + const dx = (xmax - xmin) / (width); + const dy = (ymax - ymin) / (height); + + // Start y + let y = ymin; + for (let j = 0; j < height; j++) { + // Start x + let x = xmin; + for (let i = 0; i < width; i++) { + + // Now we test, as we iterate z = z^2 + cm does z tend towards infinity? + let a = x; + let b = y; + let n = 0; + while (n < maxiterations) { + const aa = a * a; + const bb = b * b; + const twoab = 2.0 * a * b; + a = aa - bb + x; + b = twoab + y; + // Infinty in our finite world is simple, let's just consider it 16 + if (dist(aa, bb, 0, 0) > 16) { + break; // Bail + } + n++; + } + + // We color each pixel based on how long it takes to get to infinity + // If we never got there, let's pick the color black + const pix = (i+j*width)*4; + const norm = map(n, 0, maxiterations, 0, 1); + let bright = map(sqrt(norm), 0, 1, 0, 255); + if (n == maxiterations) { + bright = 0; + } else { + // Gosh, we could make fancy colors here if we wanted + pixels[pix + 0] = bright; + pixels[pix + 1] = bright; + pixels[pix + 2] = bright; + pixels[pix + 3] = 255; + } + x += dx; + } + y += dy; + } + updatePixels(); +} diff --git a/src/data/examples/ko/10_Interaction/10_Tickle.js b/src/data/examples/ko/10_Interaction/10_Tickle.js new file mode 100644 index 0000000000..006ce49caa --- /dev/null +++ b/src/data/examples/ko/10_Interaction/10_Tickle.js @@ -0,0 +1,48 @@ +/* + * @name Tickle + * @description The word "tickle" jitters when the cursor hovers over. + * Sometimes, it can be tickled off the screen. + */ +let message = 'tickle', + font, + bounds, // holds x, y, w, h of the text's bounding box + fontsize = 60, + x, + y; // x and y coordinates of the text + +function preload() { + font = loadFont('assets/SourceSansPro-Regular.otf'); +} + +function setup() { + createCanvas(710, 400); + + // set up the font + textFont(font); + textSize(fontsize); + + // get the width and height of the text so we can center it initially + bounds = font.textBounds(message, 0, 0, fontsize); + x = width / 2 - bounds.w / 2; + y = height / 2 - bounds.h / 2; +} + +function draw() { + background(204, 120); + + // write the text in black and get its bounding box + fill(0); + text(message, x, y); + bounds = font.textBounds(message, x, y, fontsize); + + // check if the mouse is inside the bounding box and tickle if so + if ( + mouseX >= bounds.x && + mouseX <= bounds.x + bounds.w && + mouseY >= bounds.y && + mouseY <= bounds.y + bounds.h + ) { + x += random(-5, 5); + y += random(-5, 5); + } +} diff --git a/src/data/examples/ko/10_Interaction/20_Follow1.js b/src/data/examples/ko/10_Interaction/20_Follow1.js new file mode 100644 index 0000000000..df0902cc09 --- /dev/null +++ b/src/data/examples/ko/10_Interaction/20_Follow1.js @@ -0,0 +1,37 @@ +/* + * @name Follow 1 + * @frame 710,400 + * @description A line segment is pushed and pulled by the cursor. + * Based on code from Keith Peters. + */ +let x = 100, + y = 100, + angle1 = 0.0, + segLength = 50; + +function setup() { + createCanvas(710, 400); + strokeWeight(20.0); + stroke(255, 100); +} + +function draw() { + background(0); + + dx = mouseX - x; + dy = mouseY - y; + angle1 = atan2(dy, dx); + x = mouseX - cos(angle1) * segLength; + y = mouseY - sin(angle1) * segLength; + + segment(x, y, angle1); + ellipse(x, y, 20, 20); +} + +function segment(x, y, a) { + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/10_Interaction/21_Follow2.js b/src/data/examples/ko/10_Interaction/21_Follow2.js new file mode 100644 index 0000000000..ebb87cb2ca --- /dev/null +++ b/src/data/examples/ko/10_Interaction/21_Follow2.js @@ -0,0 +1,39 @@ +/* + * @name Follow 2 + * @frame 710,400 + * @description A two-segmented arm follows the cursor position. The relative + * angle between the segments is calculated with atan2() and the position + * calculated with sin() and cos(). Based on code from Keith Peters. + */ +let x = [0, 0], + y = [0, 0], + segLength = 50; + +function setup() { + createCanvas(710, 400); + strokeWeight(20.0); + stroke(255, 100); +} + +function draw() { + background(0); + dragSegment(0, mouseX, mouseY); + dragSegment(1, x[0], y[0]); +} + +function dragSegment(i, xin, yin) { + const dx = xin - x[i]; + const dy = yin - y[i]; + const angle = atan2(dy, dx); + x[i] = xin - cos(angle) * segLength; + y[i] = yin - sin(angle) * segLength; + segment(x[i], y[i], angle); +} + +function segment(x, y, a) { + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/10_Interaction/22_Follow3.js b/src/data/examples/ko/10_Interaction/22_Follow3.js new file mode 100644 index 0000000000..79878f8f2c --- /dev/null +++ b/src/data/examples/ko/10_Interaction/22_Follow3.js @@ -0,0 +1,47 @@ +/* + * @name Follow 3 + * @frame 710,400 + * @description A segmented line follows the mouse. The relative angle from + * each segment to the next is calculated with atan2() and the position of + * the next is calculated with sin() and cos(). Based on code from Keith Peters. + */ +let x = [], + y = [], + segNum = 20, + segLength = 18; + +for (let i = 0; i < segNum; i++) { + x[i] = 0; + y[i] = 0; +} + +function setup() { + createCanvas(710, 400); + strokeWeight(9); + stroke(255, 100); +} + +function draw() { + background(0); + dragSegment(0, mouseX, mouseY); + for (let i = 0; i < x.length - 1; i++) { + dragSegment(i + 1, x[i], y[i]); + } +} + +function dragSegment(i, xin, yin) { + const dx = xin - x[i]; + const dy = yin - y[i]; + const angle = atan2(dy, dx); + x[i] = xin - cos(angle) * segLength; + y[i] = yin - sin(angle) * segLength; + segment(x[i], y[i], angle); +} + +function segment(x, y, a) { + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/10_Interaction/23_snake.js b/src/data/examples/ko/10_Interaction/23_snake.js new file mode 100644 index 0000000000..ac56aa3fd3 --- /dev/null +++ b/src/data/examples/ko/10_Interaction/23_snake.js @@ -0,0 +1,172 @@ +/* + * @name Snake game + * @description The famous snake game! Once you click run, click anywhere + * inside the black area, and control the snake using i j k and l. Don't let + * the snake hit itself or the wall!
+ * Example created by Prashant Gupta + */ + +// the snake is divided into small segments, which are drawn and edited on each 'draw' call +let numSegments = 10; +let direction = 'right'; + +const xStart = 0; //starting x coordinate for snake +const yStart = 250; //starting y coordinate for snake +const diff = 10; + +let xCor = []; +let yCor = []; + +let xFruit = 0; +let yFruit = 0; +let scoreElem; + +function setup() { + scoreElem = createDiv('Score = 0'); + scoreElem.position(20, 20); + scoreElem.id = 'score'; + scoreElem.style('color', 'white'); + + createCanvas(500, 500); + frameRate(15); + stroke(255); + strokeWeight(10); + updateFruitCoordinates(); + + for (let i = 0; i < numSegments; i++) { + xCor.push(xStart + i * diff); + yCor.push(yStart); + } +} + +function draw() { + background(0); + for (let i = 0; i < numSegments - 1; i++) { + line(xCor[i], yCor[i], xCor[i + 1], yCor[i + 1]); + } + updateSnakeCoordinates(); + checkGameStatus(); + checkForFruit(); +} + +/* + The segments are updated based on the direction of the snake. + All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0 + gets the value of segment 1, segment 1 gets the value of segment 2, and so on, + and this results in the movement of the snake. + + The last segment is added based on the direction in which the snake is going, + if it's going left or right, the last segment's x coordinate is increased by a + predefined value 'diff' than its second to last segment. And if it's going up + or down, the segment's y coordinate is affected. +*/ +function updateSnakeCoordinates() { + for (let i = 0; i < numSegments - 1; i++) { + xCor[i] = xCor[i + 1]; + yCor[i] = yCor[i + 1]; + } + switch (direction) { + case 'right': + xCor[numSegments - 1] = xCor[numSegments - 2] + diff; + yCor[numSegments - 1] = yCor[numSegments - 2]; + break; + case 'up': + xCor[numSegments - 1] = xCor[numSegments - 2]; + yCor[numSegments - 1] = yCor[numSegments - 2] - diff; + break; + case 'left': + xCor[numSegments - 1] = xCor[numSegments - 2] - diff; + yCor[numSegments - 1] = yCor[numSegments - 2]; + break; + case 'down': + xCor[numSegments - 1] = xCor[numSegments - 2]; + yCor[numSegments - 1] = yCor[numSegments - 2] + diff; + break; + } +} + +/* + I always check the snake's head position xCor[xCor.length - 1] and + yCor[yCor.length - 1] to see if it touches the game's boundaries + or if the snake hits itself. +*/ +function checkGameStatus() { + if ( + xCor[xCor.length - 1] > width || + xCor[xCor.length - 1] < 0 || + yCor[yCor.length - 1] > height || + yCor[yCor.length - 1] < 0 || + checkSnakeCollision() + ) { + noLoop(); + const scoreVal = parseInt(scoreElem.html().substring(8)); + scoreElem.html('Game ended! Your score was : ' + scoreVal); + } +} + +/* + If the snake hits itself, that means the snake head's (x,y) coordinate + has to be the same as one of its own segment's (x,y) coordinate. +*/ +function checkSnakeCollision() { + const snakeHeadX = xCor[xCor.length - 1]; + const snakeHeadY = yCor[yCor.length - 1]; + for (let i = 0; i < xCor.length - 1; i++) { + if (xCor[i] === snakeHeadX && yCor[i] === snakeHeadY) { + return true; + } + } +} + +/* + Whenever the snake consumes a fruit, I increment the number of segments, + and just insert the tail segment again at the start of the array (basically + I add the last segment again at the tail, thereby extending the tail) +*/ +function checkForFruit() { + point(xFruit, yFruit); + if (xCor[xCor.length - 1] === xFruit && yCor[yCor.length - 1] === yFruit) { + const prevScore = parseInt(scoreElem.html().substring(8)); + scoreElem.html('Score = ' + (prevScore + 1)); + xCor.unshift(xCor[0]); + yCor.unshift(yCor[0]); + numSegments++; + updateFruitCoordinates(); + } +} + +function updateFruitCoordinates() { + /* + The complex math logic is because I wanted the point to lie + in between 100 and width-100, and be rounded off to the nearest + number divisible by 10, since I move the snake in multiples of 10. + */ + + xFruit = floor(random(10, (width - 100) / 10)) * 10; + yFruit = floor(random(10, (height - 100) / 10)) * 10; +} + +function keyPressed() { + switch (keyCode) { + case 74: + if (direction !== 'right') { + direction = 'left'; + } + break; + case 76: + if (direction !== 'left') { + direction = 'right'; + } + break; + case 73: + if (direction !== 'down') { + direction = 'up'; + } + break; + case 75: + if (direction !== 'up') { + direction = 'down'; + } + break; + } +} diff --git a/src/data/examples/ko/10_Interaction/24_Wavemaker.js b/src/data/examples/ko/10_Interaction/24_Wavemaker.js new file mode 100644 index 0000000000..26d29ee0b2 --- /dev/null +++ b/src/data/examples/ko/10_Interaction/24_Wavemaker.js @@ -0,0 +1,37 @@ +/* + * @name Wavemaker + * @description This illustrates how waves (like water waves) emerge + * from particles oscillating in place. Move your mouse to direct the wave. + * Contributed by Aatish Bhatia, inspired by Orbiters by Dave Whyte. + */ + +let t = 0; // time variable + +function setup() { + createCanvas(600, 600); + noStroke(); + fill(40, 200, 40); +} + +function draw() { + background(10, 10); // translucent background (creates trails) + + // make a x and y grid of ellipses + for (let x = 0; x <= width; x = x + 30) { + for (let y = 0; y <= height; y = y + 30) { + // starting point of each circle depends on mouse position + const xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true); + const yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true); + // and also varies based on the particle's location + const angle = xAngle * (x / width) + yAngle * (y / height); + + // each particle moves in a circle + const myX = x + 20 * cos(2 * PI * t + angle); + const myY = y + 20 * sin(2 * PI * t + angle); + + ellipse(myX, myY, 10); // draw particle + } + } + + t = t + 0.01; // update time +} diff --git a/src/data/examples/ko/10_Interaction/25_reach1.js b/src/data/examples/ko/10_Interaction/25_reach1.js new file mode 100644 index 0000000000..7982061aac --- /dev/null +++ b/src/data/examples/ko/10_Interaction/25_reach1.js @@ -0,0 +1,57 @@ +/* + * @name Reach 1 + * @frame 710,400 + * @description The arm follows the position of the mouse by calculating the + * angles with atan2(). Based on code from Keith Peters. + */ +let segLength = 80, + x, + y, + x2, + y2; + +function setup() { + createCanvas(710, 400); + strokeWeight(20); + stroke(255, 100); + + x = width / 2; + y = height / 2; + x2 = x; + y2 = y; +} + +function draw() { + background(0); + dragSegment(0, mouseX, mouseY); + for (let i = 0; i < x.length - 1; i++) { + dragSegment(i + 1, x[i], y[i]); + } +} + +function dragSegment(i, xin, yin) { + background(0); + + dx = mouseX - x; + dy = mouseY - y; + angle1 = atan2(dy, dx); + + tx = mouseX - cos(angle1) * segLength; + ty = mouseY - sin(angle1) * segLength; + dx = tx - x2; + dy = ty - y2; + angle2 = atan2(dy, dx); + x = x2 + cos(angle2) * segLength; + y = y2 + sin(angle2) * segLength; + + segment(x, y, angle1); + segment(x2, y2, angle2); +} + +function segment(x, y, a) { + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/10_Interaction/26_reach2.js b/src/data/examples/ko/10_Interaction/26_reach2.js new file mode 100644 index 0000000000..4d6ea72174 --- /dev/null +++ b/src/data/examples/ko/10_Interaction/26_reach2.js @@ -0,0 +1,65 @@ +/* + * @name Reach 2 + * @frame 710,400 + * @description The arm follows the position of the mouse by calculating the + * angles with atan2(). Based on code from Keith Peters. + */ +let numSegments = 10, + x = [], + y = [], + angle = [], + segLength = 26, + targetX, + targetY; + +for (let i = 0; i < numSegments; i++) { + x[i] = 0; + y[i] = 0; + angle[i] = 0; +} + +function setup() { + createCanvas(710, 400); + strokeWeight(20); + stroke(255, 100); + + x[x.length - 1] = width / 2; // Set base x-coordinate + y[x.length - 1] = height; // Set base y-coordinate +} + +function draw() { + background(0); + + reachSegment(0, mouseX, mouseY); + for (let i = 1; i < numSegments; i++) { + reachSegment(i, targetX, targetY); + } + for (let j = x.length - 1; j >= 1; j--) { + positionSegment(j, j - 1); + } + for (let k = 0; k < x.length; k++) { + segment(x[k], y[k], angle[k], (k + 1) * 2); + } +} + +function positionSegment(a, b) { + x[b] = x[a] + cos(angle[a]) * segLength; + y[b] = y[a] + sin(angle[a]) * segLength; +} + +function reachSegment(i, xin, yin) { + const dx = xin - x[i]; + const dy = yin - y[i]; + angle[i] = atan2(dy, dx); + targetX = xin - cos(angle[i]) * segLength; + targetY = yin - sin(angle[i]) * segLength; +} + +function segment(x, y, a, sw) { + strokeWeight(sw); + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/10_Interaction/27_reach3.js b/src/data/examples/ko/10_Interaction/27_reach3.js new file mode 100644 index 0000000000..32739138b3 --- /dev/null +++ b/src/data/examples/ko/10_Interaction/27_reach3.js @@ -0,0 +1,81 @@ +/* + * @name Reach 3 + * @frame 710,400 + * @description The arm follows the position of the ball by calculating the + * angles with atan2(). Based on code from Keith Peters. + */ +let numSegments = 8, + x = [], + y = [], + angle = [], + segLength = 26, + targetX, + targetY, + ballX = 50, + ballY = 50, + ballXDirection = 1, + ballYDirection = -1; + +for (let i = 0; i < numSegments; i++) { + x[i] = 0; + y[i] = 0; + angle[i] = 0; +} + +function setup() { + createCanvas(710, 400); + strokeWeight(20); + stroke(255, 100); + noFill(); + + x[x.length - 1] = width / 2; // Set base x-coordinate + y[x.length - 1] = height; // Set base y-coordinate +} + +function draw() { + background(0); + + strokeWeight(20); + ballX = ballX + 1.0 * ballXDirection; + ballY = ballY + 0.8 * ballYDirection; + if (ballX > width - 25 || ballX < 25) { + ballXDirection *= -1; + } + if (ballY > height - 25 || ballY < 25) { + ballYDirection *= -1; + } + ellipse(ballX, ballY, 30, 30); + + reachSegment(0, ballX, ballY); + for (let i = 1; i < numSegments; i++) { + reachSegment(i, targetX, targetY); + } + for (let j = x.length - 1; j >= 1; j--) { + positionSegment(j, j - 1); + } + for (let k = 0; k < x.length; k++) { + segment(x[k], y[k], angle[k], (k + 1) * 2); + } +} + +function positionSegment(a, b) { + x[b] = x[a] + cos(angle[a]) * segLength; + y[b] = y[a] + sin(angle[a]) * segLength; +} + +function reachSegment(i, xin, yin) { + const dx = xin - x[i]; + const dy = yin - y[i]; + angle[i] = atan2(dy, dx); + targetX = xin - cos(angle[i]) * segLength; + targetY = yin - sin(angle[i]) * segLength; +} + +function segment(x, y, a, sw) { + strokeWeight(sw); + push(); + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); + pop(); +} diff --git a/src/data/examples/ko/11_Objects/01_Objects.js b/src/data/examples/ko/11_Objects/01_Objects.js new file mode 100644 index 0000000000..79f10d3295 --- /dev/null +++ b/src/data/examples/ko/11_Objects/01_Objects.js @@ -0,0 +1,39 @@ +/* + * @name Objects + * @description Create a Jitter class, instantiate an object, + * and move it around the screen. Adapted from Getting Started with + * Processing by Casey Reas and Ben Fry. + */ + +let bug; // Declare object + +function setup() { + createCanvas(710, 400); + // Create object + bug = new Jitter(); +} + +function draw() { + background(50, 89, 100); + bug.move(); + bug.display(); +} + +// Jitter class +class Jitter { + constructor() { + this.x = random(width); + this.y = random(height); + this.diameter = random(10, 30); + this.speed = 1; + } + + move() { + this.x += random(-this.speed, this.speed); + this.y += random(-this.speed, this.speed); + } + + display() { + ellipse(this.x, this.y, this.diameter, this.diameter); + } +} diff --git a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js new file mode 100644 index 0000000000..b57e9209e2 --- /dev/null +++ b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js @@ -0,0 +1,50 @@ +/* + * @name Multiple Objects + * @description Create a Jitter class, instantiate multiple objects, + * and move it around the screen. + */ + +let bug1; // Declare objects +let bug2; +let bug3; +let bug4; + +function setup() { + createCanvas(710, 400); + // Create object + bug1 = new Jitter(); + bug2 = new Jitter(); + bug3 = new Jitter(); + bug4 = new Jitter(); +} + +function draw() { + background(50, 89, 100); + bug1.move(); + bug1.display(); + bug2.move(); + bug2.display(); + bug3.move(); + bug3.display(); + bug4.move(); + bug4.display(); +} + +// Jitter class +class Jitter { + constructor() { + this.x = random(width); + this.y = random(height); + this.diameter = random(10, 30); + this.speed = 1; + } + + move() { + this.x += random(-this.speed, this.speed); + this.y += random(-this.speed, this.speed); + } + + display() { + ellipse(this.x, this.y, this.diameter, this.diameter); + } +} diff --git a/src/data/examples/ko/11_Objects/03_Objects_Array.js b/src/data/examples/ko/11_Objects/03_Objects_Array.js new file mode 100644 index 0000000000..ccc5406037 --- /dev/null +++ b/src/data/examples/ko/11_Objects/03_Objects_Array.js @@ -0,0 +1,42 @@ +/* + * @name Array of Objects + * @description Create a Jitter class, instantiate an array of objects + * and move them around the screen. + */ + +let bugs = []; // array of Jitter objects + +function setup() { + createCanvas(710, 400); + // Create objects + for (let i = 0; i < 50; i++) { + bugs.push(new Jitter()); + } +} + +function draw() { + background(50, 89, 100); + for (let i = 0; i < bugs.length; i++) { + bugs[i].move(); + bugs[i].display(); + } +} + +// Jitter class +class Jitter { + constructor() { + this.x = random(width); + this.y = random(height); + this.diameter = random(10, 30); + this.speed = 1; + } + + move() { + this.x += random(-this.speed, this.speed); + this.y += random(-this.speed, this.speed); + } + + display() { + ellipse(this.x, this.y, this.diameter, this.diameter); + } +} diff --git a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js new file mode 100644 index 0000000000..2796774489 --- /dev/null +++ b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js @@ -0,0 +1,65 @@ +/* + * @name Objects 2 + * @description Ported from example by hbarragan. Move the cursor across the + * image to change the speed and positions of the geometry. The class MRect + * defines a group of lines. + */ + +let r1, r2, r3, r4; + +function setup() { + createCanvas(710, 400); + fill(255, 204); + noStroke(); + r1 = new MRect(1, 134.0, 0.532, 0.1 * height, 10.0, 60.0); + r2 = new MRect(2, 44.0, 0.166, 0.3 * height, 5.0, 50.0); + r3 = new MRect(2, 58.0, 0.332, 0.4 * height, 10.0, 35.0); + r4 = new MRect(1, 120.0, 0.0498, 0.9 * height, 15.0, 60.0); +} + +function draw() { + background(0); + + r1.display(); + r2.display(); + r3.display(); + r4.display(); + + r1.move(mouseX - width / 2, mouseY + height * 0.1, 30); + r2.move((mouseX + width * 0.05) % width, mouseY + height * 0.025, 20); + r3.move(mouseX / 4, mouseY - height * 0.025, 40); + r4.move(mouseX - width / 2, height - mouseY, 50); +} + +class MRect { + constructor(iw, ixp, ih, iyp, id, it) { + this.w = iw; // single bar width + this.xpos = ixp; // rect xposition + this.h = ih; // rect height + this.ypos = iyp; // rect yposition + this.d = id; // single bar distance + this.t = it; // number of bars + } + + move(posX, posY, damping) { + let dif = this.ypos - posY; + if (abs(dif) > 1) { + this.ypos -= dif / damping; + } + dif = this.xpos - posX; + if (abs(dif) > 1) { + this.xpos -= dif / damping; + } + } + + display() { + for (let i = 0; i < this.t; i++) { + rect( + this.xpos + i * (this.d + this.w), + this.ypos, + this.w, + height * this.h + ); + } + } +} diff --git a/src/data/examples/ko/11_Objects/04_Inheritance.js b/src/data/examples/ko/11_Objects/04_Inheritance.js new file mode 100644 index 0000000000..32b6a630e3 --- /dev/null +++ b/src/data/examples/ko/11_Objects/04_Inheritance.js @@ -0,0 +1,71 @@ +/* @name Inheritance + * @description A class can be defined using another class as a + * foundation. In object-oriented programming terminology, one class can + * inherit fields and methods from another. An object that inherits from + * another is called a subclass, and the object it inherits from is called + * a superclass. A subclass extends the superclass. + */ +let spots, arm; + +function setup() { + createCanvas(640, 360); + arm = new SpinArm(width/2, height/2, 0.01); + spots = new SpinSpots(width/2, height/2, -0.02, 90.0); +} + +function draw() { + background(204); + arm.update(); + arm.display(); + spots.update(); + spots.display(); +} + +class SpinArm { + constructor(x, y, s) { + this.x = x; + this.y = y; + this.speed = s; + this.angle = 0.0; + } + + update() { + this.angle += this.speed; + } + + display() { + strokeWeight(1); + stroke(0); + push(); + translate(this.x, this.y); + this.angle += this.speed; + rotate(this.angle); + line(0, 0, 165, 0); + pop(); + } +} + +class SpinSpots { + constructor(x, y, s, d) { + this.x = x; + this.y = y; + this.speed = s; + this.dim = d; + this.angle = 0.0; + } + + update() { + this.angle += this.speed; + } + + display() { + noStroke(); + push(); + translate(this.x, this.y); + this.angle += this.speed; + rotate(this.angle); + ellipse(-this.dim/2, 0, this.dim, this.dim); + ellipse(this.dim/2, 0, this.dim, this.dim); + pop(); + } +} diff --git a/src/data/examples/ko/12_Lights/02_Directional.js b/src/data/examples/ko/12_Lights/02_Directional.js new file mode 100755 index 0000000000..1c806373fc --- /dev/null +++ b/src/data/examples/ko/12_Lights/02_Directional.js @@ -0,0 +1,27 @@ +/* + * @name Directional + * @frame 710,400 + * @description Move the mouse to change the direction of the light. + * Directional light comes from one direction and is stronger when hitting a + * surface squarely and weaker if it hits at a a gentle angle. After hitting a + * surface, a directional light scatters in all directions. + */ +const radius = 200; + +function setup() { + createCanvas(710, 400, WEBGL); + noStroke(); + fill(200); +} + +function draw() { + noStroke(); + background(0); + const dirY = (mouseY / height - 0.5) * 4; + const dirX = (mouseX / width - 0.5) * 4; + directionalLight(204, 204, 204, dirX, dirY, 1); + translate(-1.5 * radius, 0, 0); + sphere(radius); + translate(3 * radius, 0, 0); + sphere(radius); +} diff --git a/src/data/examples/ko/12_Lights/05_Mixture.js b/src/data/examples/ko/12_Lights/05_Mixture.js new file mode 100644 index 0000000000..6dc5513aa0 --- /dev/null +++ b/src/data/examples/ko/12_Lights/05_Mixture.js @@ -0,0 +1,26 @@ +/* + * @name Mixture + * @frame 710,400 (optional) + * @description Display a box with three different kinds of lights. + */ +function setup() { + createCanvas(710, 400, WEBGL); + noStroke(); +} + +function draw() { + background(0); + + // Orange point light on the right + pointLight(150, 100, 0, 500, 0, 200); + + // Blue directional light from the left + directionalLight(0, 102, 255, -1, 0, 0); + + // Yellow spotlight from the front + pointLight(255, 255, 109, 0, 0, 300); + + rotateY(map(mouseX, 0, width, 0, PI)); + rotateX(map(mouseY, 0, height, 0, PI)); + box(200); +} diff --git a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js new file mode 100644 index 0000000000..1d5ed269c5 --- /dev/null +++ b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js @@ -0,0 +1,110 @@ +/* + * @name Non Orthogonal Reflection + * @frame 710,400 (optional) + * @description This is a port by David Blitz of the "Reflection 1" example from processing.org/examples + */ + +//Position of left hand side of floor +let base1; + +//Position of right hand side of floor +let base2; +//Length of floor +//let baseLength; + +// Variables related to moving ball +let position; +let velocity; +let r = 6; +let speed = 3.5; + +function setup() { + createCanvas(710, 400); + + fill(128); + base1 = createVector(0, height - 150); + base2 = createVector(width, height); + //createGround(); + + //start ellipse at middle top of screen + position = createVector(width / 2, 0); + + //calculate initial random velocity + velocity = p5.Vector.random2D(); + velocity.mult(speed); +} + +function draw() { + //draw background + fill(0, 12); + noStroke(); + rect(0, 0, width, height); + + //draw base + fill(200); + quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height); + + //calculate base top normal + let baseDelta = p5.Vector.sub(base2, base1); + baseDelta.normalize(); + let normal = createVector(-baseDelta.y, baseDelta.x); + let intercept = p5.Vector.dot(base1, normal); + + //draw ellipse + noStroke(); + fill(255); + ellipse(position.x, position.y, r * 2, r * 2); + + //move ellipse + position.add(velocity); + + //normalized incidence vector + incidence = p5.Vector.mult(velocity, -1); + incidence.normalize(); + + // detect and handle collision with base + if (p5.Vector.dot(normal, position) > intercept) { + //calculate dot product of incident vector and base top + let dot = incidence.dot(normal); + + //calculate reflection vector + //assign reflection vector to direction vector + velocity.set( + 2 * normal.x * dot - incidence.x, + 2 * normal.y * dot - incidence.y, + 0 + ); + velocity.mult(speed); + + // draw base top normal at collision point + stroke(255, 128, 0); + line( + position.x, + position.y, + position.x - normal.x * 100, + position.y - normal.y * 100 + ); + } + //} + + // detect boundary collision + // right + if (position.x > width - r) { + position.x = width - r; + velocity.x *= -1; + } + // left + if (position.x < r) { + position.x = r; + velocity.x *= -1; + } + // top + if (position.y < r) { + position.y = r; + velocity.y *= -1; + + //randomize base top + base1.y = random(height - 100, height); + base2.y = random(height - 100, height); + } +} diff --git a/src/data/examples/ko/13_Motion/02_Linear_Motion.js b/src/data/examples/ko/13_Motion/02_Linear_Motion.js new file mode 100644 index 0000000000..421f99c104 --- /dev/null +++ b/src/data/examples/ko/13_Motion/02_Linear_Motion.js @@ -0,0 +1,24 @@ +/* + * @name Linear + * @frame 720,400 + * @description Changing a variable to create a moving line. + * When the line moves off the edge of the window, + * the variable is set to 0, which places the line back at the bottom of the screen. + */ + +let a; + +function setup() { + createCanvas(720, 400); + stroke(255); + a = height / 2; +} + +function draw() { + background(51); + line(0, a, width, a); + a = a - 0.5; + if (a < 0) { + a = height; + } +} diff --git a/src/data/examples/ko/13_Motion/03_Bounce.js b/src/data/examples/ko/13_Motion/03_Bounce.js new file mode 100644 index 0000000000..a3354e015f --- /dev/null +++ b/src/data/examples/ko/13_Motion/03_Bounce.js @@ -0,0 +1,44 @@ +/* + * @name Bounce + * @frame 720,400 + * @description When the shape hits the edge of the window, it reverses its direction. + */ + +let rad = 60; // Width of the shape +let xpos, ypos; // Starting position of shape + +let xspeed = 2.8; // Speed of the shape +let yspeed = 2.2; // Speed of the shape + +let xdirection = 1; // Left or Right +let ydirection = 1; // Top to Bottom + +function setup() { + createCanvas(720, 400); + noStroke(); + frameRate(30); + ellipseMode(RADIUS); + // Set the starting position of the shape + xpos = width / 2; + ypos = height / 2; +} + +function draw() { + background(102); + + // Update the position of the shape + xpos = xpos + xspeed * xdirection; + ypos = ypos + yspeed * ydirection; + + // Test to see if the shape exceeds the boundaries of the screen + // If it does, reverse its direction by multiplying by -1 + if (xpos > width - rad || xpos < rad) { + xdirection *= -1; + } + if (ypos > height - rad || ypos < rad) { + ydirection *= -1; + } + + // Draw the shape + ellipse(xpos, ypos, rad, rad); +} diff --git a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js new file mode 100644 index 0000000000..9c38b8c6f3 --- /dev/null +++ b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js @@ -0,0 +1,95 @@ +/* + * @name Bouncy Bubbles + * @frame 720,400 + * @description based on code from Keith Peters. Multiple-object collision.. + */ + +let numBalls = 13; +let spring = 0.05; +let gravity = 0.03; +let friction = -0.9; +let balls = []; + +function setup() { + createCanvas(720, 400); + for (let i = 0; i < numBalls; i++) { + balls[i] = new Ball( + random(width), + random(height), + random(30, 70), + i, + balls + ); + } + noStroke(); + fill(255, 204); +} + +function draw() { + background(0); + balls.forEach(ball => { + ball.collide(); + ball.move(); + ball.display(); + }); +} + +class Ball { + constructor(xin, yin, din, idin, oin) { + this.x = xin; + this.y = yin; + let vx = 0; + let vy = 0; + this.diameter = din; + this.id = idin; + this.others = oin; + } + + collide() { + for (let i = this.id + 1; i < numBalls; i++) { + // console.log(others[i]); + let dx = this.others[i].x - this.x; + let dy = this.others[i].y - this.y; + let distance = sqrt(dx * dx + dy * dy); + let minDist = this.others[i].diameter / 2 + this.diameter / 2; + // console.log(distance); + //console.log(minDist); + if (distance < minDist) { + //console.log("2"); + let angle = atan2(dy, dx); + let targetX = this.x + cos(angle) * minDist; + let targetY = this.y + sin(angle) * minDist; + let ax = (targetX - this.others[i].x) * spring; + let ay = (targetY - this.others[i].y) * spring; + vx -= ax; + vy -= ay; + this.others[i].vx += ax; + this.others[i].vy += ay; + } + } + } + + move() { + vy += gravity; + this.x += vx; + this.y += vy; + if (this.x + this.diameter / 2 > width) { + this.x = width - this.diameter / 2; + vx *= friction; + } else if (this.x - this.diameter / 2 < 0) { + this.x = this.diameter / 2; + vx *= friction; + } + if (this.y + this.diameter / 2 > height) { + this.y = height - this.diameter / 2; + vy *= friction; + } else if (this.y - this.diameter / 2 < 0) { + this.y = this.diameter / 2; + vy *= friction; + } + } + + display() { + ellipse(this.x, this.y, this.diameter, this.diameter); + } +} diff --git a/src/data/examples/ko/13_Motion/05_Morph.js b/src/data/examples/ko/13_Motion/05_Morph.js new file mode 100644 index 0000000000..c6479c27d6 --- /dev/null +++ b/src/data/examples/ko/13_Motion/05_Morph.js @@ -0,0 +1,93 @@ +/* + * @name Morph + * @frame 720,400 + * @description Changing one shape into another by interpolating vertices from one to another. + */ + +// Two ArrayLists to store the vertices for two shapes +// This example assumes that each shape will have the same +// number of vertices, i.e. the size of each ArrayList will be the same +let circle = []; +let square = []; + +// An ArrayList for a third set of vertices, the ones we will be drawing +// in the window +let morph = []; + +// This boolean variable will control if we are morphing to a circle or square +let state = false; + +function setup() { + createCanvas(720, 400); + + // Create a circle using vectors pointing from center + for (let angle = 0; angle < 360; angle += 9) { + // Note we are not starting from 0 in order to match the + // path of a circle. + let v = p5.Vector.fromAngle(radians(angle - 135)); + v.mult(100); + circle.push(v); + // Let's fill out morph ArrayList with blank PVectors while we are at it + morph.push(createVector()); + } + + // A square is a bunch of vertices along straight lines + // Top of square + for (let x = -50; x < 50; x += 10) { + square.push(createVector(x, -50)); + } + // Right side + for (let y = -50; y < 50; y += 10) { + square.push(createVector(50, y)); + } + // Bottom + for (let x = 50; x > -50; x -= 10) { + square.push(createVector(x, 50)); + } + // Left side + for (let y = 50; y > -50; y -= 10) { + square.push(createVector(-50, y)); + } +} + +function draw() { + background(51); + + // We will keep how far the vertices are from their target + let totalDistance = 0; + + // Look at each vertex + for (let i = 0; i < circle.length; i++) { + let v1; + // Are we lerping to the circle or square? + if (state) { + v1 = circle[i]; + } else { + v1 = square[i]; + } + // Get the vertex we will draw + let v2 = morph[i]; + // Lerp to the target + v2.lerp(v1, 0.1); + // Check how far we are from target + totalDistance += p5.Vector.dist(v1, v2); + } + + // If all the vertices are close, switch shape + if (totalDistance < 0.1) { + state = !state; + } + + // Draw relative to center + translate(width / 2, height / 2); + strokeWeight(4); + // Draw a polygon that makes up all the vertices + beginShape(); + noFill(); + stroke(255); + + morph.forEach(v => { + vertex(v.x, v.y); + }); + endShape(CLOSE); +} diff --git a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js new file mode 100644 index 0000000000..4c347c7e00 --- /dev/null +++ b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js @@ -0,0 +1,47 @@ +/* + * @name Moving On Curves + * @frame 720,400 + * @description In this example, the circles moves along the curve y = x^4. + * Click the mouse to have it move to a new position. + */ + +let beginX = 20.0; // Initial x-coordinate +let beginY = 10.0; // Initial y-coordinate +let endX = 570.0; // Final x-coordinate +let endY = 320.0; // Final y-coordinate +let distX; // X-axis distance to move +let distY; // Y-axis distance to move +let exponent = 4; // Determines the curve +let x = 0.0; // Current x-coordinate +let y = 0.0; // Current y-coordinate +let step = 0.01; // Size of each step along the path +let pct = 0.0; // Percentage traveled (0.0 to 1.0) + +function setup() { + createCanvas(720, 400); + noStroke(); + distX = endX - beginX; + distY = endY - beginY; +} + +function draw() { + fill(0, 2); + rect(0, 0, width, height); + pct += step; + if (pct < 1.0) { + x = beginX + pct * distX; + y = beginY + pow(pct, exponent) * distY; + } + fill(255); + ellipse(x, y, 20, 20); +} + +function mousePressed() { + pct = 0.0; + beginX = x; + beginY = y; + endX = mouseX; + endY = mouseY; + distX = endX - beginX; + distY = endY - beginY; +} diff --git a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js new file mode 100644 index 0000000000..0c4bc70751 --- /dev/null +++ b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js @@ -0,0 +1,35 @@ +/* + * @name Instantiation + * @description Create a p5 instance, which keeps all variables + * out of the global scope of your page. + */ +let sketch = function(p) { + let x = 100; + let y = 100; + + p.setup = function() { + p.createCanvas(700, 410); + }; + + p.draw = function() { + p.background(0); + p.fill(255); + p.rect(x, y, 50, 50); + }; +}; + +let myp5 = new p5(sketch); + +// Compare to "global mode" +// let x = 100; +// let y = 100; + +// function setup() { +// createCanvas(200,200); +// } + +// function draw() { +// background(0); +// fill(255); +// ellipse(x,y,50,50); +// } diff --git a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js new file mode 100644 index 0000000000..9675fdeaaf --- /dev/null +++ b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js @@ -0,0 +1,94 @@ +/* + * @norender + * @name Instance Container + * @description Optionally, you can specify a default container for the canvas + * and any other elements to append to with a second argument. You can give the + * ID of an element in your html, or an html node itself. + * + * Here are three different options for selecting a container + * DOM element. All DOM elements (canvas, buttons, divs, etc) created by p5 + * will be attached to the DOM element specified as the second argument to the + * p5() call. + */ + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/data/examples/ko/16_Dom/03_Input_Button.js b/src/data/examples/ko/16_Dom/03_Input_Button.js new file mode 100644 index 0000000000..5ec69a29ed --- /dev/null +++ b/src/data/examples/ko/16_Dom/03_Input_Button.js @@ -0,0 +1,41 @@ +/* + * @name Input and Button + * @description You will need to include the + * p5.dom library + * for this example to work in your own project.

+ * Input text and click the button to see it affect the the canvas. + */ +let input, button, greeting; + +function setup() { + // create canvas + createCanvas(710, 400); + + input = createInput(); + input.position(20, 65); + + button = createButton('submit'); + button.position(input.x + input.width, 65); + button.mousePressed(greet); + + greeting = createElement('h2', 'what is your name?'); + greeting.position(20, 5); + + textAlign(CENTER); + textSize(50); +} + +function greet() { + const name = input.value(); + greeting.html('hello ' + name + '!'); + input.value(''); + + for (let i = 0; i < 200; i++) { + push(); + fill(random(255), 255, 255); + translate(random(width), random(height)); + rotate(random(2 * PI)); + text(name, 0, 0); + pop(); + } +} diff --git a/src/data/examples/ko/16_Dom/04_Slider.js b/src/data/examples/ko/16_Dom/04_Slider.js new file mode 100644 index 0000000000..0582953c37 --- /dev/null +++ b/src/data/examples/ko/16_Dom/04_Slider.js @@ -0,0 +1,33 @@ +/* + * @name Slider + * @description You will need to include the + * p5.dom library + * for this example to work in your own project.

+ * Move the sliders to control the R, G, B values of the background. + */ +let rSlider, gSlider, bSlider; + +function setup() { + // create canvas + createCanvas(710, 400); + textSize(15); + noStroke(); + + // create sliders + rSlider = createSlider(0, 255, 100); + rSlider.position(20, 20); + gSlider = createSlider(0, 255, 0); + gSlider.position(20, 50); + bSlider = createSlider(0, 255, 255); + bSlider.position(20, 80); +} + +function draw() { + const r = rSlider.value(); + const g = gSlider.value(); + const b = bSlider.value(); + background(r, g, b); + text('red', rSlider.x * 2 + rSlider.width, 35); + text('green', gSlider.x * 2 + gSlider.width, 65); + text('blue', bSlider.x * 2 + bSlider.width, 95); +} diff --git a/src/data/examples/ko/16_Dom/07_Modify_DOM.js b/src/data/examples/ko/16_Dom/07_Modify_DOM.js new file mode 100644 index 0000000000..c784755f29 --- /dev/null +++ b/src/data/examples/ko/16_Dom/07_Modify_DOM.js @@ -0,0 +1,56 @@ +/* + * @name Modifying the DOM + * @frame 710,300 + * @description

Create DOM elements and modify their properties every time + * draw() is called. You will need to include the + * p5.dom library + * for this example to work in your own project.

+ */ +let dancingWords = []; + +class DanceSpan { + constructor(element, x, y) { + element.position(x, y); + this.element = element; + this.x = x; + this.y = y; + } + + brownian() { + this.x += random(-6, 6); + this.y += random(-6, 6); + this.element.position(this.x, this.y); + } +} + +function setup() { + // This paragraph is created aside of the main block of code. + // It's to differentiate the creation of an element from its + // selection. Selected elements don't need to be created by + // p5js, they can be just plain HTML. + createP( + 'I learn in this Letter, that Don Peter of Aragon, ' + + ' comes this night to Messina' + ).addClass('text').hide(); + + // This line grabs the paragraph just created, but it would + // also grab any other elements with class 'text' in the HTML + // page. + const texts = selectAll('.text'); + + for (let i = 0; i < texts.length; i++) { + const paragraph = texts[i].html(); + const words = paragraph.split(' '); + for (let j = 0; j < words.length; j++) { + const spannedWord = createSpan(words[j]); + const dw = new DanceSpan(spannedWord, random(600), random(200)); + dancingWords.push(dw); + } + } +} + +function draw() { + for (let i = 0; i < dancingWords.length; i++) { + dancingWords[i].brownian(); + } +} diff --git a/src/data/examples/ko/16_Dom/08_Video.js b/src/data/examples/ko/16_Dom/08_Video.js new file mode 100644 index 0000000000..45454f006b --- /dev/null +++ b/src/data/examples/ko/16_Dom/08_Video.js @@ -0,0 +1,31 @@ +/* + * @name Video + * @frame 710,250 + * @description

Load a video with multiple formats and toggle between playing + * and paused with a button press. + *

To run this example locally, you will need at least + * one video file, and the + * p5.dom library.

+ */ +let playing = false; +let fingers; +let button; + +function setup() { + // specify multiple formats for different browsers + fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']); + button = createButton('play'); + button.mousePressed(toggleVid); // attach button listener +} + +// plays or pauses the video depending on current state +function toggleVid() { + if (playing) { + fingers.pause(); + button.html('play'); + } else { + fingers.loop(); + button.html('pause'); + } + playing = !playing; +} diff --git a/src/data/examples/ko/16_Dom/09_Video_Canvas.js b/src/data/examples/ko/16_Dom/09_Video_Canvas.js new file mode 100644 index 0000000000..81de6efd7c --- /dev/null +++ b/src/data/examples/ko/16_Dom/09_Video_Canvas.js @@ -0,0 +1,28 @@ +/* + * @name Video Canvas + * @description

Load a video with multiple formats and draw it to the canvas.

+ *

To run this example locally, you will need the + * p5.dom library + * at least one video file, and a running local server.

+ */ +let fingers; + +function setup() { + createCanvas(710, 400); + // specify multiple formats for different browsers + fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']); + fingers.hide(); // by default video shows up in separate dom + // element. hide it and draw it to the canvas + // instead +} + +function draw() { + background(150); + image(fingers, 10, 10); // draw the video frame to canvas + filter('GRAY'); + image(fingers, 150, 150); // draw a second copy to canvas +} + +function mousePressed() { + fingers.loop(); // set the video to loop and start playing +} diff --git a/src/data/examples/ko/16_Dom/10_Video_Pixels.js b/src/data/examples/ko/16_Dom/10_Video_Pixels.js new file mode 100644 index 0000000000..ba7dcf0638 --- /dev/null +++ b/src/data/examples/ko/16_Dom/10_Video_Pixels.js @@ -0,0 +1,33 @@ +/* + * @name Video Pixels + * @frame 320,240 + * @description

Load a video, manipulate its pixels and draw to canvas. + *

To run this example locally, you will need the + * p5.dom library + * at least one video file, and a running local server.

+ */ +let fingers; + +function setup() { + createCanvas(320, 240); + // specify multiple formats for different browsers + fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']); + fingers.loop(); + fingers.hide(); + noStroke(); + fill(0); +} + +function draw() { + background(255); + fingers.loadPixels(); + const stepSize = round(constrain(mouseX / 8, 6, 32)); + for (let y = 0; y < height; y += stepSize) { + for (let x = 0; x < width; x += stepSize) { + const i = y * width + x; + const darkness = (255 - fingers.pixels[i * 4]) / 255; + const radius = stepSize * darkness; + ellipse(x, y, radius, radius); + } + } +} diff --git a/src/data/examples/ko/16_Dom/11_Capture.js b/src/data/examples/ko/16_Dom/11_Capture.js new file mode 100644 index 0000000000..31e706d487 --- /dev/null +++ b/src/data/examples/ko/16_Dom/11_Capture.js @@ -0,0 +1,25 @@ +/* + * @name Video Capture + * @frame 710,240 + * @description

To run this example locally, you will need the + * p5.dom library + * at least one video file, and a running local server.



+ * Capture video from the webcam and display + * on the canvas as well with invert filter. Note that by + * default the capture feed shows up, too. You can hide the + * feed by uncommenting the capture.hide() line. + */ +let capture; + +function setup() { + createCanvas(390, 240); + capture = createCapture(VIDEO); + capture.size(320, 240); + //capture.hide(); +} + +function draw() { + background(255); + image(capture, 0, 0, 320, 240); + filter('INVERT'); +} diff --git a/src/data/examples/ko/16_Dom/12_Drop.js b/src/data/examples/ko/16_Dom/12_Drop.js new file mode 100644 index 0000000000..3d42627e50 --- /dev/null +++ b/src/data/examples/ko/16_Dom/12_Drop.js @@ -0,0 +1,36 @@ +/* + * @name Drop + * @description You will need to include the + * p5.dom library + * for this example to work in your own project.

+ * Drag an image file onto the canvas to see it displayed. + */ + +function setup() { + // create canvas + const c = createCanvas(710, 400); + background(100); + // Add an event for when a file is dropped onto the canvas + c.drop(gotFile); +} + +function draw() { + fill(255); + noStroke(); + textSize(24); + textAlign(CENTER); + text('Drag an image file onto the canvas.', width / 2, height / 2); + noLoop(); +} + +function gotFile(file) { + // If it's an image file + if (file.type === 'image') { + // Create an image DOM element but don't show it + const img = createImg(file.data).hide(); + // Draw the image onto the canvas + image(img, 0, 0, width, height); + } else { + console.log('Not an image file!'); + } +} diff --git a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js new file mode 100644 index 0000000000..c06901439a --- /dev/null +++ b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js @@ -0,0 +1,15 @@ +/* + * @name Continous Lines + * @description Click and drag the mouse to draw a line. + */ +function setup() { + createCanvas(710, 400); + background(102); +} + +function draw() { + stroke(255); + if (mouseIsPressed === true) { + line(mouseX, mouseY, pmouseX, pmouseY); + } +} diff --git a/src/data/examples/ko/17_Drawing/01_Pattern.js b/src/data/examples/ko/17_Drawing/01_Pattern.js new file mode 100644 index 0000000000..ab3ee36eb5 --- /dev/null +++ b/src/data/examples/ko/17_Drawing/01_Pattern.js @@ -0,0 +1,27 @@ +/* + * @name Patterns + * @description Move the cursor over the image to draw with a software tool + * which responds to the speed of the mouse. + */ +function setup() { + createCanvas(710, 400); + background(102); +} + +function draw() { + // Call the variableEllipse() method and send it the + // parameters for the current mouse position + // and the previous mouse position + variableEllipse(mouseX, mouseY, pmouseX, pmouseY); +} + +// The simple method variableEllipse() was created specifically +// for this program. It calculates the speed of the mouse +// and draws a small ellipse if the mouse is moving slowly +// and draws a large ellipse if the mouse is moving quickly + +function variableEllipse(x, y, px, py) { + let speed = abs(x - px) + abs(y - py); + stroke(speed); + ellipse(x, y, speed, speed); +} diff --git a/src/data/examples/ko/17_Drawing/02_Pulses.js b/src/data/examples/ko/17_Drawing/02_Pulses.js new file mode 100644 index 0000000000..c256672539 --- /dev/null +++ b/src/data/examples/ko/17_Drawing/02_Pulses.js @@ -0,0 +1,31 @@ +/* + * @name Pulses + * @description Software drawing instruments can follow a rhythm or abide by + * rules independent of drawn gestures. This is a form of collaborative drawing + * in which the draftsperson controls some aspects of the image and the software + * controls others. + */ +let angle = 0; + +function setup() { + createCanvas(710, 400); + background(102); + noStroke(); + fill(0, 102); +} + +function draw() { + // Draw only when mouse is pressed + if (mouseIsPressed === true) { + angle += 5; + let val = cos(radians(angle)) * 12.0; + for (let a = 0; a < 360; a += 75) { + let xoff = cos(radians(a)) * val; + let yoff = sin(radians(a)) * val; + fill(0); + ellipse(mouseX + xoff, mouseY + yoff, val, val); + } + fill(255); + ellipse(mouseX, mouseY, 2, 2); + } +} diff --git a/src/data/examples/ko/18_Transform/00_Translate.js b/src/data/examples/ko/18_Transform/00_Translate.js new file mode 100644 index 0000000000..1599f1cf4f --- /dev/null +++ b/src/data/examples/ko/18_Transform/00_Translate.js @@ -0,0 +1,40 @@ +/* + * @name Translate + * @description The translate() function allows objects to be + * moved to any location within the window. The first parameter + * sets the x-axis offset and the second parameter sets the + * y-axis offset. This example shows how transforms accumulate. + */ + +let x = 0; +let y = 0; +let dim = 80.0; + +function setup() { + createCanvas(720, 400); + noStroke(); +} + +function draw() { + background(102); + // Animate by increasing our x value + x = x + 0.8; + // If the shape goes off the canvas, reset the position + if (x > width + dim) { + x = -dim; + } + + // Even though our rect command draws the shape with its + // center at the origin, translate moves it to the new + // x and y position + translate(x, height / 2 - dim / 2); + fill(255); + rect(-dim / 2, -dim / 2, dim, dim); + + // Transforms accumulate. Notice how this rect moves + // twice as fast as the other, but it has the same + // parameter for the x-axis value + translate(x, dim); + fill(0); + rect(-dim / 2, -dim / 2, dim, dim); +} diff --git a/src/data/examples/ko/18_Transform/01_Scale.js b/src/data/examples/ko/18_Transform/01_Scale.js new file mode 100644 index 0000000000..d176f25680 --- /dev/null +++ b/src/data/examples/ko/18_Transform/01_Scale.js @@ -0,0 +1,46 @@ +/* + * @name Scale + * @description Paramenters for the scale() function are values + * specified as decimal percentages. For example, the method + * call scale(2.0) will increase the dimension of the shape by + * 200 percent. Objects always scale from the origin. This example + * shows how transforms accumulate and also how scale and translate + * interact depending on their order. + */ + +let a = 0.0; +let s = 0.0; + +function setup() { + createCanvas(720, 400); + noStroke(); + //Draw all rectangles from their center as opposed to + // the default upper left corner + rectMode(CENTER); +} + +function draw() { + background(102); + + //Slowly increase 'a' and then animate 's' with + //a smooth cyclical motion by finding the cosine of 'a' + a = a + 0.04; + s = cos(a) * 2; + + //Translate our rectangle from the origin to the middle of + //the canvas, then scale it with 's' + translate(width / 2, height / 2); + scale(s); + fill(51); + rect(0, 0, 50, 50); + + //Translate and scale are accumulating, so this translate + //moves the second rectangle further right than the first + //and the scale is getting doubled. Note that cosine is + //making 's' both negative and positive, thus it cycles + //from left to right. + translate(75, 0); + fill(255); + scale(s); + rect(0, 0, 50, 50); +} diff --git a/src/data/examples/ko/18_Transform/02_Rotate.js b/src/data/examples/ko/18_Transform/02_Rotate.js new file mode 100644 index 0000000000..6b91dc2186 --- /dev/null +++ b/src/data/examples/ko/18_Transform/02_Rotate.js @@ -0,0 +1,43 @@ +/* + * @name Rotate + * @description Rotating a square around the Z axis. + * To get the results you expect, send the rotate function angle + * parameters that are values between 0 and PI*2 (TWO_PI which is + * roughly 6.28). If you prefer to think about angles as degrees + * (0-360), you can use the radians() method to convert your values. + * For example: scale(radians(90)) is identical to the statement + * scale(PI/2). In this example, every even numbered second a jitter + * is added to the rotation. During odd seconds rotation moves CW and + * CCW at the speed determined by the last jitter value. + */ + +let angle = 0.0; +let jitter = 0.0; + +function setup() { + createCanvas(720, 400); + noStroke(); + fill(255); + //Draw the rectangle from the center and it will also be the + //rotate around that center + rectMode(CENTER); +} + +function draw() { + background(51); + + // during even-numbered seconds (0, 2, 4, 6...) add jitter to + // the rotation + if (second() % 2 === 0) { + jitter = random(-0.1, 0.1); + } + //increase the angle value using the most recent jitter value + angle = angle + jitter; + //use cosine to get a smooth CW and CCW motion when not jittering + let c = cos(angle); + //move the shape to the center of the canvas + translate(width / 2, height / 2); + //apply the final rotation + rotate(c); + rect(0, 0, 180, 180); +} diff --git a/src/data/examples/ko/18_Transform/03_Arm.js b/src/data/examples/ko/18_Transform/03_Arm.js new file mode 100644 index 0000000000..733fe30909 --- /dev/null +++ b/src/data/examples/ko/18_Transform/03_Arm.js @@ -0,0 +1,49 @@ +/* + * @name Arm + * @description This example uses transform matrices to create + * an arm. The angle of each segment is controlled with the + * mouseX and mouseY position. The transformations applied to + * the first segment are also applied to the second segment + * because they are inside the same push() and + * pop() matrix group. + */ + +let x, y; +let angle1 = 0.0; +let angle2 = 0.0; +let segLength = 100; + +function setup() { + createCanvas(720, 400); + strokeWeight(30); + + //Stroke with a semi-transparent white + stroke(255, 160); + + //Position the "shoulder" of the arm in the center of the canvas + x = width * 0.5; + y = height * 0.5; +} + +function draw() { + background(0); + + //Change the angle of the segments according to the mouse positions + angle1 = (mouseX / float(width) - 0.5) * -TWO_PI; + angle2 = (mouseY / float(height) - 0.5) * PI; + + //use push and pop to "contain" the transforms. Note that + // even though we draw the segments using a custom function, + // the transforms still accumulate + push(); + segment(x, y, angle1); + segment(segLength, 0, angle2); + pop(); +} + +//a custom function for drawing segments +function segment(x, y, a) { + translate(x, y); + rotate(a); + line(0, 0, segLength, 0); +} diff --git a/src/data/examples/ko/19_Typography/00_Letters.js b/src/data/examples/ko/19_Typography/00_Letters.js new file mode 100644 index 0000000000..2e16306ae3 --- /dev/null +++ b/src/data/examples/ko/19_Typography/00_Letters.js @@ -0,0 +1,64 @@ +/* + * @name Letters + * @description Letters can be drawn to the screen by loading a font, setting + * its characteristics and then drawing the letters. This example uses a for + * loop and unicode reference numbers to automatically fill the canvas with + * characters in a grid. Vowels are selected and given a specific fill color. + */ +let font, + fontsize = 32; + +function preload() { + // Ensure the .ttf or .otf font stored in the assets directory + // is loaded before setup() and draw() are called + font = loadFont('assets/SourceSansPro-Regular.otf'); +} + +function setup() { + createCanvas(710, 400); + + // Set text characteristics + textFont(font); + textSize(fontsize); + textAlign(CENTER, CENTER); +} + +function draw() { + background(160); + + // Set the gap between letters and the left and top margin + let gap = 52; + let margin = 10; + translate(margin * 4, margin * 4); + + // Set the counter to start at the character you want + // in this case 35, which is the # symbol + let counter = 35; + + // Loop as long as there is space on the canvas + for (let y = 0; y < height - gap; y += gap) { + for (let x = 0; x < width - gap; x += gap) { + // Use the counter to retrieve individual letters by their Unicode number + let letter = char(counter); + + // Add different color to the vowels and other characters + if ( + letter === 'A' || + letter === 'E' || + letter === 'I' || + letter === 'O' || + letter === 'U' + ) { + fill('#ed225d'); + } else { + fill(255); + } + + // Draw the letter to the screen + text(letter, x, y); + + // Increment the counter + counter++; + } + } +} diff --git a/src/data/examples/ko/19_Typography/01_Words.js b/src/data/examples/ko/19_Typography/01_Words.js new file mode 100644 index 0000000000..d76271f2b8 --- /dev/null +++ b/src/data/examples/ko/19_Typography/01_Words.js @@ -0,0 +1,59 @@ +/* + * @name Words + * @description The text() function is used for writing words to the screen. + * The words can be aligned left, center, or right with the textAlign() + * function, and like with shapes, words can be colored with fill(). + */ +let font, + fontsize = 40; + +function preload() { + // Ensure the .ttf or .otf font stored in the assets directory + // is loaded before setup() and draw() are called + font = loadFont('assets/SourceSansPro-Regular.otf'); +} + +function setup() { + createCanvas(710, 400); + + // Set text characteristics + textFont(font); + textSize(fontsize); + textAlign(CENTER, CENTER); +} + +function draw() { + background(160); + + // Align the text to the right + // and run drawWords() in the left third of the canvas + textAlign(RIGHT); + drawWords(width * 0.25); + + // Align the text in the center + // and run drawWords() in the middle of the canvas + textAlign(CENTER); + drawWords(width * 0.5); + + // Align the text to the left + // and run drawWords() in the right third of the canvas + textAlign(LEFT); + drawWords(width * 0.75); +} + +function drawWords(x) { + // The text() function needs three parameters: + // the text to draw, the horizontal position, + // and the vertical position + fill(0); + text('ichi', x, 80); + + fill(65); + text('ni', x, 150); + + fill(190); + text('san', x, 220); + + fill(255); + text('shi', x, 290); +} diff --git a/src/data/examples/ko/20_3D/00_geometries.js b/src/data/examples/ko/20_3D/00_geometries.js new file mode 100644 index 0000000000..a58cce64e8 --- /dev/null +++ b/src/data/examples/ko/20_3D/00_geometries.js @@ -0,0 +1,60 @@ +/* + * @name Geometries + * @description There are six 3D primitives in p5 now. + */ +function setup() { + createCanvas(710, 400, WEBGL); +} + +function draw() { + background(250); + + translate(-240, -100, 0); + normalMaterial(); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + plane(70); + pop(); + + translate(240, 0, 0); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + box(70, 70, 70); + pop(); + + translate(240, 0, 0); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + cylinder(70, 70); + pop(); + + translate(-240 * 2, 200, 0); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + cone(70, 70); + pop(); + + translate(240, 0, 0); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + torus(70, 20); + pop(); + + translate(240, 0, 0); + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + sphere(70); + pop(); +} diff --git a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js new file mode 100644 index 0000000000..d9adf11963 --- /dev/null +++ b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js @@ -0,0 +1,28 @@ +/* + * @name Sine Cosine in 3D + * @description Sine, cosine and push / pop could be applied in 3D as well. + */ +function setup() { + createCanvas(710, 400, WEBGL); +} + +function draw() { + background(250); + rotateY(frameCount * 0.01); + + for (let j = 0; j < 5; j++) { + push(); + for (let i = 0; i < 80; i++) { + translate( + sin(frameCount * 0.001 + j) * 100, + sin(frameCount * 0.001 + j) * 100, + i * 0.1 + ); + rotateZ(frameCount * 0.002); + push(); + sphere(8, 6, 4); + pop(); + } + pop(); + } +} diff --git a/src/data/examples/ko/20_3D/02_multiple_lights.js b/src/data/examples/ko/20_3D/02_multiple_lights.js new file mode 100644 index 0000000000..7bed590f63 --- /dev/null +++ b/src/data/examples/ko/20_3D/02_multiple_lights.js @@ -0,0 +1,30 @@ +/* + * @name Multiple Lights + * @description All types of lights could be used in one sketch. + */ +function setup() { + createCanvas(710, 400, WEBGL); +} + +function draw() { + background(0); + + let locX = mouseX - height / 2; + let locY = mouseY - width / 2; + + ambientLight(50); + directionalLight(255, 0, 0, 0.25, 0.25, 0); + pointLight(0, 0, 255, locX, locY, 250); + + push(); + translate(-width / 4, 0, 0); + rotateZ(frameCount * 0.02); + rotateX(frameCount * 0.02); + specularMaterial(250); + box(100, 100, 100); + pop(); + + translate(width / 4, 0, 0); + ambientMaterial(250); + sphere(120, 64); +} diff --git a/src/data/examples/ko/20_3D/03_materials.js b/src/data/examples/ko/20_3D/03_materials.js new file mode 100644 index 0000000000..4dd7e97e37 --- /dev/null +++ b/src/data/examples/ko/20_3D/03_materials.js @@ -0,0 +1,65 @@ +/* + * @name Materials + * @description There are five types of materials supported. + * They respond to light differently. + * Move your mouse to change the light position. + */ +let img; +function setup() { + createCanvas(710, 400, WEBGL); + img = loadImage('assets/cat.jpg'); +} + +function draw() { + background(0); + + let locX = mouseX - height / 2; + let locY = mouseY - width / 2; + + ambientLight(60, 60, 60); + pointLight(255, 255, 255, locX, locY, 100); + + push(); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + texture(img); + box(80); + pop(); + + push(); + translate(-width / 4, -height / 4, 0); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + fill(250, 0, 0); + torus(80, 20, 64, 64); + pop(); + + push(); + translate(width / 4, -height / 4, 0); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + normalMaterial(); + torus(80, 20, 64, 64); + pop(); + + push(); + translate(-width / 4, height / 4, 0); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + ambientMaterial(250); + torus(80, 20, 64, 64); + pop(); + + push(); + translate(width / 4, height / 4, 0); + rotateZ(frameCount * 0.01); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + specularMaterial(250); + torus(80, 20, 64, 64); + pop(); +} diff --git a/src/data/examples/ko/20_3D/04_textures.js b/src/data/examples/ko/20_3D/04_textures.js new file mode 100644 index 0000000000..0a4df84872 --- /dev/null +++ b/src/data/examples/ko/20_3D/04_textures.js @@ -0,0 +1,40 @@ +/* + * @name Textures + * @description Images and videos are supported for texture. + */ +// video source: https://vimeo.com/90312869 +let img; +let vid; +let theta = 0; + +function setup() { + createCanvas(710, 400, WEBGL); + + img = loadImage('assets/cat.jpg'); + vid = createVideo(['assets/360video_256crop_v2.mp4']); + vid.elt.muted = true; + vid.loop(); + vid.hide(); +} + +function draw() { + background(250); + translate(-220, 0, 0); + push(); + rotateZ(theta * mouseX * 0.001); + rotateX(theta * mouseX * 0.001); + rotateY(theta * mouseX * 0.001); + //pass image as texture + texture(vid); + sphere(150); + pop(); + translate(440, 0, 0); + push(); + rotateZ(theta * 0.1); + rotateX(theta * 0.1); + rotateY(theta * 0.1); + texture(img); + box(100, 100, 100); + pop(); + theta += 0.05; +} diff --git a/src/data/examples/ko/20_3D/07_orbit_control.js b/src/data/examples/ko/20_3D/07_orbit_control.js new file mode 100644 index 0000000000..7d30f82cbd --- /dev/null +++ b/src/data/examples/ko/20_3D/07_orbit_control.js @@ -0,0 +1,36 @@ +/* + * @name Orbit Control + * @description Orbit control allows you to drag and move around the world. + */ +function setup() { + createCanvas(710, 400, WEBGL); +} + +function draw() { + background(250); + let radius = width * 1.5; + + //drag to move the world. + orbitControl(); + + normalMaterial(); + translate(0, 0, -600); + for (let i = 0; i <= 12; i++) { + for (let j = 0; j <= 12; j++) { + push(); + let a = (j / 12) * PI; + let b = (i / 12) * PI; + translate( + sin(2 * a) * radius * sin(b), + (cos(b) * radius) / 2, + cos(2 * a) * radius * sin(b) + ); + if (j % 2 === 0) { + cone(30, 30); + } else { + box(30, 30, 30); + } + pop(); + } + } +} diff --git a/src/data/examples/ko/21_Input/00_Clock.js b/src/data/examples/ko/21_Input/00_Clock.js new file mode 100644 index 0000000000..5603db0f3e --- /dev/null +++ b/src/data/examples/ko/21_Input/00_Clock.js @@ -0,0 +1,62 @@ +/* + * @name Clock + * @description The current time can be read with the second(), + * minute(), and hour() functions. In this example, sin() and + * cos() values are used to set the position of the hands. + */ +let cx, cy; +let secondsRadius; +let minutesRadius; +let hoursRadius; +let clockDiameter; + +function setup() { + createCanvas(720, 400); + stroke(255); + + let radius = min(width, height) / 2; + secondsRadius = radius * 0.71; + minutesRadius = radius * 0.6; + hoursRadius = radius * 0.5; + clockDiameter = radius * 1.7; + + cx = width / 2; + cy = height / 2; +} + +function draw() { + background(230); + + // Draw the clock background + noStroke(); + fill(244, 122, 158); + ellipse(cx, cy, clockDiameter + 25, clockDiameter + 25); + fill(237, 34, 93); + ellipse(cx, cy, clockDiameter, clockDiameter); + + // Angles for sin() and cos() start at 3 o'clock; + // subtract HALF_PI to make them start at the top + let s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI; + let m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI; + let h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI; + + // Draw the hands of the clock + stroke(255); + strokeWeight(1); + line(cx, cy, cx + cos(s) * secondsRadius, cy + sin(s) * secondsRadius); + strokeWeight(2); + line(cx, cy, cx + cos(m) * minutesRadius, cy + sin(m) * minutesRadius); + strokeWeight(4); + line(cx, cy, cx + cos(h) * hoursRadius, cy + sin(h) * hoursRadius); + + // Draw the minute ticks + strokeWeight(2); + beginShape(POINTS); + for (let a = 0; a < 360; a += 6) { + let angle = radians(a); + let x = cx + cos(angle) * secondsRadius; + let y = cy + sin(angle) * secondsRadius; + vertex(x, y); + } + endShape(); +} diff --git a/src/data/examples/ko/21_Input/01_Constrain.js b/src/data/examples/ko/21_Input/01_Constrain.js new file mode 100644 index 0000000000..36a08abd31 --- /dev/null +++ b/src/data/examples/ko/21_Input/01_Constrain.js @@ -0,0 +1,36 @@ +/* + * @name Constrain + * @description Move the mouse across the screen to move + * the circle. The program constrains the circle to its box. + */ +let mx = 1; +let my = 1; +let easing = 0.05; +let radius = 24; +let edge = 100; +let inner = edge + radius; + +function setup() { + createCanvas(720, 400); + noStroke(); + ellipseMode(RADIUS); + rectMode(CORNERS); +} + +function draw() { + background(230); + + if (abs(mouseX - mx) > 0.1) { + mx = mx + (mouseX - mx) * easing; + } + if (abs(mouseY - my) > 0.1) { + my = my + (mouseY - my) * easing; + } + + mx = constrain(mx, inner, width - inner); + my = constrain(my, inner, height - inner); + fill(237, 34, 93); + rect(edge, edge, width - edge, height - edge); + fill(255); + ellipse(mx, my, radius, radius); +} diff --git a/src/data/examples/ko/21_Input/02_Easing.js b/src/data/examples/ko/21_Input/02_Easing.js new file mode 100644 index 0000000000..6fe01dc1b0 --- /dev/null +++ b/src/data/examples/ko/21_Input/02_Easing.js @@ -0,0 +1,30 @@ +/* + * @name Easing + * @description Move the mouse across the screen and the symbol + * will follow. Between drawing each frame of the animation, the + * program calculates the difference between the position of the + * symbol and the cursor. If the distance is larger than 1 pixel, + * the symbol moves part of the distance (0.05) from its current + * position toward the cursor. + */ +let x = 1; +let y = 1; +let easing = 0.05; + +function setup() { + createCanvas(720, 400); + noStroke(); +} + +function draw() { + background(237, 34, 93); + let targetX = mouseX; + let dx = targetX - x; + x += dx * easing; + + let targetY = mouseY; + let dy = targetY - y; + y += dy * easing; + + ellipse(x, y, 66, 66); +} diff --git a/src/data/examples/ko/21_Input/03_Keyboard.js b/src/data/examples/ko/21_Input/03_Keyboard.js new file mode 100644 index 0000000000..c7b50f99a3 --- /dev/null +++ b/src/data/examples/ko/21_Input/03_Keyboard.js @@ -0,0 +1,38 @@ +/* + * @name Keyboard + * @description Click on the image to give it focus and + * press the letter keys to create forms in time and space. + * Each key has a unique identifying number. These numbers + * can be used to position shapes in space. + */ +let rectWidth; + +function setup() { + createCanvas(720, 400); + noStroke(); + background(230); + rectWidth = width / 4; +} + +function draw() { + // keep draw() here to continue looping while waiting for keys +} + +function keyPressed() { + let keyIndex = -1; + if (key >= 'a' && key <= 'z') { + keyIndex = key.charCodeAt(0) - 'a'.charCodeAt(0); + } + if (keyIndex === -1) { + // If it's not a letter key, clear the screen + background(230); + } else { + // It's a letter key, fill a rectangle + randFill_r = Math.floor(Math.random() * 255 + 1); + randFill_g = Math.floor(Math.random() * 255 + 1); + randFill_b = Math.floor(Math.random() * 255 + 1); + fill(randFill_r, randFill_g, randFill_b); + let x = map(keyIndex, 0, 25, 0, width - rectWidth); + rect(x, 0, rectWidth, height); + } +} diff --git a/src/data/examples/ko/21_Input/04_Mouse1D.js b/src/data/examples/ko/21_Input/04_Mouse1D.js new file mode 100644 index 0000000000..eb613fbab9 --- /dev/null +++ b/src/data/examples/ko/21_Input/04_Mouse1D.js @@ -0,0 +1,24 @@ +/* + * @name Mouse 1D + * @description Move the mouse left and right to + * shift the balance. The "mouseX" variable is used + * to control both the size and color of the rectangles. + */ +function setup() { + createCanvas(720, 400); + noStroke(); + rectMode(CENTER); +} + +function draw() { + background(230); + + let r1 = map(mouseX, 0, width, 0, height); + let r2 = height - r1; + + fill(237, 34, 93, r1); + rect(width / 2 + r1 / 2, height / 2, r1, r1); + + fill(237, 34, 93, r2); + rect(width / 2 - r2 / 2, height / 2, r2, r2); +} diff --git a/src/data/examples/ko/21_Input/05_Mouse2D.js b/src/data/examples/ko/21_Input/05_Mouse2D.js new file mode 100644 index 0000000000..efc623adae --- /dev/null +++ b/src/data/examples/ko/21_Input/05_Mouse2D.js @@ -0,0 +1,20 @@ +/* + * @name Mouse 2D + * @description Moving the mouse changes the position and + * size of each box. + */ +function setup() { + createCanvas(720, 400); + noStroke(); + rectMode(CENTER); +} + +function draw() { + background(230); + fill(244, 122, 158); + rect(mouseX, height / 2, mouseY / 2 + 10, mouseY / 2 + 10); + fill(237, 34, 93); + let inverseX = width - mouseX; + let inverseY = height - mouseY; + rect(inverseX, height / 2, inverseY / 2 + 10, inverseY / 2 + 10); +} diff --git a/src/data/examples/ko/21_Input/06_MouseIsPressed.js b/src/data/examples/ko/21_Input/06_MouseIsPressed.js new file mode 100644 index 0000000000..27279e99b0 --- /dev/null +++ b/src/data/examples/ko/21_Input/06_MouseIsPressed.js @@ -0,0 +1,20 @@ +/* + * @name Mouse Press + * @description Move the mouse to position the shape. + * Press the mouse button to invert the color. + */ +function setup() { + createCanvas(720, 400); + background(230); + strokeWeight(2); +} + +function draw() { + if (mouseIsPressed) { + stroke(255); + } else { + stroke(237, 34, 93); + } + line(mouseX - 66, mouseY, mouseX + 66, mouseY); + line(mouseX, mouseY - 66, mouseX, mouseY + 66); +} diff --git a/src/data/examples/ko/21_Input/07_Mouse_Functions.js b/src/data/examples/ko/21_Input/07_Mouse_Functions.js new file mode 100644 index 0000000000..ad1acdc7b2 --- /dev/null +++ b/src/data/examples/ko/21_Input/07_Mouse_Functions.js @@ -0,0 +1,66 @@ +/* + * @name Mouse Functions + * @description Click on the box and drag it across the screen. + */ +let bx; +let by; +let boxSize = 75; +let overBox = false; +let locked = false; +let xOffset = 0.0; +let yOffset = 0.0; + +function setup() { + createCanvas(720, 400); + bx = width / 2.0; + by = height / 2.0; + rectMode(RADIUS); + strokeWeight(2); +} + +function draw() { + background(237, 34, 93); + + // Test if the cursor is over the box + if ( + mouseX > bx - boxSize && + mouseX < bx + boxSize && + mouseY > by - boxSize && + mouseY < by + boxSize + ) { + overBox = true; + if (!locked) { + stroke(255); + fill(244, 122, 158); + } + } else { + stroke(156, 39, 176); + fill(244, 122, 158); + overBox = false; + } + + // Draw the box + rect(bx, by, boxSize, boxSize); +} + +function mousePressed() { + if (overBox) { + locked = true; + fill(255, 255, 255); + } else { + locked = false; + } + xOffset = mouseX - bx; + yOffset = mouseY - by; +} + +function mouseDragged() { + if (locked) { + bx = mouseX - xOffset; + by = mouseY - yOffset; + } +} + +function mouseReleased() { + locked = false; +} diff --git a/src/data/examples/ko/21_Input/08_Mouse_Signals.js b/src/data/examples/ko/21_Input/08_Mouse_Signals.js new file mode 100644 index 0000000000..8847fe8f1c --- /dev/null +++ b/src/data/examples/ko/21_Input/08_Mouse_Signals.js @@ -0,0 +1,52 @@ +/* + * @name Mouse Signals + * @description Move and click the mouse to generate signals. + * The top row is the signal from "mouseX", the middle row is + * the signal from "mouseY", and the bottom row is the signal + * from "mouseIsPressed". + */ +let xvals = []; +let yvals = []; +let bvals = []; + +function setup() { + createCanvas(720, 400); + strokeWeight(2); +} + +function draw() { + background(237, 34, 93); + + for (let i = 1; i < width; i++) { + xvals[i - 1] = xvals[i]; + yvals[i - 1] = yvals[i]; + bvals[i - 1] = bvals[i]; + } + // Add the new values to the end of the array + xvals[width - 1] = mouseX; + yvals[width - 1] = mouseY; + + if (mouseIsPressed) { + bvals[width - 1] = 0; + } else { + bvals[width - 1] = 255; + } + + fill(255); + noStroke(); + rect(0, height / 3, width, height / 3 + 1); + + for (let i = 1; i < width; i++) { + stroke(255); + point(i, xvals[i] / 3); + stroke(0); + point(i, height / 3 + yvals[i] / 3); + stroke(255); + line( + i, + (2 * height) / 3 + bvals[i] / 3, + i, + (2 * height) / 3 + bvals[i - 1] / 3 + ); + } +} diff --git a/src/data/examples/ko/21_Input/09_Storing_Input.js b/src/data/examples/ko/21_Input/09_Storing_Input.js new file mode 100644 index 0000000000..563ff80759 --- /dev/null +++ b/src/data/examples/ko/21_Input/09_Storing_Input.js @@ -0,0 +1,38 @@ +/* + * @name Storing Input + * @description Move the mouse across the screen to + * change the position of the circles. The positions + * of the mouse are recorded into an array and played + * back every frame. Between each frame, the newest + * value are added to the end of each array and the + * oldest value is deleted. + */ +let num = 60; +let mx = []; +let my = []; + +function setup() { + createCanvas(720, 400); + noStroke(); + fill(255, 153); + for (let i = 0; i < num; i++) { + mx.push(i); + my.push(i); + } +} + +function draw() { + background(237, 34, 93); + + // Cycle through the array, using a different entry on each frame. + // Using modulo (%) like this is faster than moving all the values over. + let which = frameCount % num; + mx[which] = mouseX; + my[which] = mouseY; + + for (let i = 0; i < num; i++) { + // which+1 is the smallest (the oldest in the array) + let index = (which + 1 + i) % num; + ellipse(mx[index], my[index], i, i); + } +} diff --git a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js new file mode 100644 index 0000000000..7d3e8f4b66 --- /dev/null +++ b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js @@ -0,0 +1,104 @@ +/* + * @name Load Saved JSON + * @description Create a Bubble class, instantiate multiple bubbles using data from + * a JSON file, and display results on the screen. + * Because the web browsers differ in where they save files, we do not make use of + * saveJSON, unlike the Processing example.

+ * Based on Daniel Shiffman's LoadSaveJSON Example for Processing. + */ + +// Bubble class +class Bubble { + constructor(x, y, diameter, name) { + this.x = x; + this.y = y; + this.diameter = diameter; + this.radius = diameter / 2; + this.name = name; + + this.over = false; + } + + // Check if mouse is over the bubble + rollover(px, py) { + let d = dist(px, py, this.x, this.y); + this.over = d < this.radius; + } + + // Display the Bubble + display() { + stroke(0); + strokeWeight(0.8); + noFill(); + ellipse(this.x, this.y, this.diameter, this.diameter); + if (this.over) { + fill(0); + textAlign(CENTER); + text(this.name, this.x, this.y + this.radius + 20); + } + } +} + +let data = {}; // Global object to hold results from the loadJSON call +let bubbles = []; // Global array to hold all bubble objects + +// Put any asynchronous data loading in preload to complete before "setup" is run +function preload() { + data = loadJSON('assets/bubbles.json'); +} + +// Convert saved Bubble data into Bubble Objects +function loadData() { + let bubbleData = data['bubbles']; + for (let i = 0; i < bubbleData.length; i++) { + // Get each object in the array + let bubble = bubbleData[i]; + // Get a position object + let position = bubble['position']; + // Get x,y from position + let x = position['x']; + let y = position['y']; + + // Get diameter and label + let diameter = bubble['diameter']; + let label = bubble['label']; + + // Put object in array + bubbles.push(new Bubble(x, y, diameter, label)); + } +} + +// Create a new Bubble each time the mouse is clicked. +function mousePressed() { + // Add diameter and label to bubble + let diameter = random(40, 80); + let label = 'New Label'; + + // Append the new JSON bubble object to the array + bubbles.push(new Bubble(mouseX, mouseY, diameter, label)); + + // Prune Bubble Count if there are too many + if (bubbles.length > 10) { + bubbles.shift(); // remove first item from array + } +} + +function setup() { + createCanvas(640, 360); + loadData(); +} + +function draw() { + background(255); + + // Display all bubbles + for (let i = 0; i < bubbles.length; i++) { + bubbles[i].display(); + bubbles[i].rollover(mouseX, mouseY); + } + + // Label directions at bottom + textAlign(LEFT); + fill(0); + text('Click to add bubbles.', 10, height - 10); +} diff --git a/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js new file mode 100644 index 0000000000..feffaffdc7 --- /dev/null +++ b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js @@ -0,0 +1,25 @@ +/* + * @name Load and Play Sound + * @description Load sound during preload(). Play a sound when canvas is clicked. + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server. + */ +let song; + +function setup() { + song = loadSound('assets/lucky_dragons_-_power_melody.mp3'); + createCanvas(720, 200); + background(255, 0, 0); +} + +function mousePressed() { + if (song.isPlaying()) { + // .isPlaying() returns a boolean + song.stop(); + background(255, 0, 0); + } else { + song.play(); + background(0, 255, 0); + } +} diff --git a/src/data/examples/ko/33_Sound/01_Preload_Sound.js b/src/data/examples/ko/33_Sound/01_Preload_Sound.js new file mode 100644 index 0000000000..08c419179e --- /dev/null +++ b/src/data/examples/ko/33_Sound/01_Preload_Sound.js @@ -0,0 +1,34 @@ +/* + * @name Preload SoundFile + * @description Call loadSound() during preload() to ensure that the + * sound is completely loaded before setup() is called. It's best to always + * call loadSound() in preload(), otherwise sounds won't necessarily be loaded + * by the time you want to play them in your sketch. + * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server. + */ + +let song; + +function preload() { + song = loadSound('assets/lucky_dragons_-_power_melody.mp3'); +} + +function setup() { + createCanvas(710, 200); + song.loop(); // song is ready to play during setup() because it was loaded during preload + background(0, 255, 0); +} + +function mousePressed() { + if (song.isPlaying()) { + // .isPlaying() returns a boolean + song.pause(); // .play() will resume from .pause() position + background(255, 0, 0); + } else { + song.play(); + background(0, 255, 0); + } +} diff --git a/src/data/examples/ko/33_Sound/02_soundFormats.js b/src/data/examples/ko/33_Sound/02_soundFormats.js new file mode 100644 index 0000000000..ae7571fb01 --- /dev/null +++ b/src/data/examples/ko/33_Sound/02_soundFormats.js @@ -0,0 +1,54 @@ +/** + * @name soundFormats + * @description

Technically, due to patent issues, there is no single + * sound format that is supported by all web browsers. While + * mp3 is supported across the + * latest versions of major browsers on OS X and Windows, for example, + * it may not be available on some less mainstream operating systems and + * browsers.

+ * + *

To ensure full compatibility, you can include the same sound file + * in multiple formats, e.g. 'sound.mp3' and 'sound.ogg'. (Ogg is an + * open source alternative to mp3.) You can convert audio files + * into web friendly formats for free online at media.io

. + * + *

The soundFormats() method tells loadSound which formats + * we have included with our sketch. Then, loadSound will + * attempt to load the first format that is supported by the + * client's web browser.

+ * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let song; + +function preload() { + // we have included both an .ogg file and an .mp3 file + soundFormats('ogg', 'mp3'); + + // if mp3 is not supported by this browser, + // loadSound will load the ogg file + // we have included with our sketch + song = loadSound('assets/lucky_dragons_-_power_melody.mp3'); +} + +function setup() { + createCanvas(710, 200); + + // song loaded during preload(), ready to play in setup() + song.play(); + background(0, 255, 0); +} + +function mousePressed() { + if (song.isPlaying()) { + // .isPlaying() returns a boolean + song.pause(); + background(255, 0, 0); + } else { + song.play(); // playback will resume from the pause position + background(0, 255, 0); + } +} diff --git a/src/data/examples/ko/33_Sound/03_Play_Mode.js b/src/data/examples/ko/33_Sound/03_Play_Mode.js new file mode 100644 index 0000000000..3b89691dee --- /dev/null +++ b/src/data/examples/ko/33_Sound/03_Play_Mode.js @@ -0,0 +1,42 @@ +/* + * @name Play Mode + * @description + *

In 'sustain' mode, the sound will overlap with itself. + * In 'restart' mode it will stop and then start again. + * Click mouse to play a sound file. + * Trigger lots of sounds at once! Press any key to change playmode.

+ *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let playMode = 'sustain'; +let sample; + +function setup() { + createCanvas(710, 50); + soundFormats('mp3', 'ogg'); + sample = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); +} + +function draw() { + background(255, 255, 0); + let str = 'Click here to play! Press key to toggle play mode.'; + str += ' Current Play Mode: ' + playMode + '.'; + text(str, 10, height / 2); +} + +function mouseClicked() { + sample.play(); +} +function keyPressed(k) { + togglePlayMode(); +} + +function togglePlayMode() { + if (playMode === 'sustain') { + playMode = 'restart'; + } else { + playMode = 'sustain'; + } + sample.playMode(playMode); +} diff --git a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js new file mode 100644 index 0000000000..b1d881db36 --- /dev/null +++ b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js @@ -0,0 +1,34 @@ +/* + * @name Pan Sound + * @description

Click mouse to play the sound. + * Ball position follows mouse and correlates to panning of sound.

+ *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ * + */ +let ball = {}; +let soundFile; + +function preload() { + soundFormats('mp3', 'ogg'); + soundFile = loadSound('assets/beatbox.ogg'); +} + +function setup() { + createCanvas(710, 100); +} + +function draw() { + background(0); + ball.x = constrain(mouseX, 0, width); + ellipse(ball.x, height / 2, 100, 100); +} + +function mousePressed() { + // map the ball's x location to a panning degree + // between -1.0 (left) and 1.0 (right) + let panning = map(ball.x, 0, width, -1.0, 1.0); + soundFile.pan(panning); + soundFile.play(); +} diff --git a/src/data/examples/ko/33_Sound/05_Sound_Effect.js b/src/data/examples/ko/33_Sound/05_Sound_Effect.js new file mode 100644 index 0000000000..ee825d2e15 --- /dev/null +++ b/src/data/examples/ko/33_Sound/05_Sound_Effect.js @@ -0,0 +1,68 @@ +/* + * @name Sound Effect + * @description

Play a sound effect when the mouse is clicked inside the circle.

+ *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +// Adapted from Learning Processing by Daniel Shiffman +// http://www.learningprocessing.com +// Doorbell sample by Corsica_S via freesound.org, +// Creative Commons BY 3.0 + +// A Class to describe a "doorbell" (really a button) +class Doorbell { + constructor(x_, y_, r_) { + // Location and size + this.x = x_; + this.y = y_; + this.r = r_; + } + // Is a point inside the doorbell? (used for mouse rollover, etc.) + contains(mx, my) { + return dist(mx, my, this.x, this.y) < this.r; + } + + // Show the doorbell (hardcoded colors, could be improved) + display(mx, my) { + if (this.contains(mx, my)) { + fill(100); + } else { + fill(175); + } + stroke(0); + strokeWeight(4); + ellipse(this.x, this.y, this.r, this.r); + } +} + +// A sound file object +let dingdong; + +// A doorbell object (that will trigger the sound) +let doorbell; + +function setup() { + createCanvas(200, 200); + + // Load the sound file. + // We have included both an MP3 and an OGG version. + soundFormats('mp3', 'ogg'); + dingdong = loadSound('assets/doorbell.mp3'); + + // Create a new doorbell + doorbell = new Doorbell(width / 2, height / 2, 64); +} + +function draw() { + background(255); + // Show the doorbell + doorbell.display(mouseX, mouseY); +} + +function mousePressed() { + // If the user clicks on the doorbell, play the sound! + if (doorbell.contains(mouseX, mouseY)) { + dingdong.play(); + } +} diff --git a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js new file mode 100644 index 0000000000..60ad548038 --- /dev/null +++ b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js @@ -0,0 +1,49 @@ +/* + * @name Playback Rate + * @description

Load a SoundFile and map its playback rate to + * mouseY, volume to mouseX. Playback rate is the speed with + * which the web audio context processings the sound file information. + * Slower rates not only increase the duration of the sound, but also + * decrease the pitch because it is being played back at a slower frequency.

+ *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +// A sound file object +let song; + +function preload() { + // Load a sound file + song = loadSound('assets/Damscray_DancingTiger.mp3'); +} + +function setup() { + createCanvas(710, 400); + + // Loop the sound forever + // (well, at least until stop() is called) + song.loop(); +} + +function draw() { + background(200); + + // Set the volume to a range between 0 and 1.0 + let volume = map(mouseX, 0, width, 0, 1); + volume = constrain(volume, 0, 1); + song.amp(volume); + + // Set the rate to a range between 0.1 and 4 + // Changing the rate alters the pitch + let speed = map(mouseY, 0.1, height, 0, 2); + speed = constrain(speed, 0.01, 4); + song.rate(speed); + + // Draw some circles to show what is going on + stroke(0); + fill(51, 100); + ellipse(mouseX, 100, 48, 48); + stroke(0); + fill(51, 100); + ellipse(100, mouseY, 48, 48); +} diff --git a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js new file mode 100644 index 0000000000..7bf3446e4f --- /dev/null +++ b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js @@ -0,0 +1,50 @@ +/** + * @name Measuring Amplitude + * @description

Analyze the amplitude of sound with + * p5.Amplitude.

+ * + *

Amplitude is the magnitude of vibration. Sound is vibration, + * so its amplitude is is closely related to volume / loudness.

+ * + *

The getLevel() method takes an array + * of amplitude values collected over a small period of time (1024 samples). + * Then it returns the Root Mean Square (RMS) of these values.

+ * + *

The original amplitude values for digital audio are between -1.0 and 1.0. + * But the RMS will always be positive, because it is squared. + * And, rather than use instantanous amplitude readings that are sampled at a rate + * of 44,100 times per second, the RMS is an average over time (1024 samples, in this case), + * which better represents how we hear amplitude. + *

+ *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let song, analyzer; + +function preload() { + song = loadSound('assets/lucky_dragons_-_power_melody.mp3'); +} + +function setup() { + createCanvas(710, 200); + song.loop(); + + // create a new Amplitude analyzer + analyzer = new p5.Amplitude(); + + // Patch the input to an volume analyzer + analyzer.setInput(song); +} + +function draw() { + background(255); + + // Get the average (root mean square) amplitude + let rms = analyzer.getLevel(); + fill(127); + stroke(0); + + // Draw an ellipse with size based on volume + ellipse(width / 2, height / 2, 10 + rms * 200, 10 + rms * 200); +} diff --git a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js new file mode 100644 index 0000000000..b38e423c75 --- /dev/null +++ b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js @@ -0,0 +1,54 @@ +/** + * @name Noise Drum Envelope + * @description

White Noise is a random audio signal with equal energy + * at every part of the frequency spectrum

+ * + *

An Envelope is a series of fades, defined + * as time / value pairs.

+ * + *

In this example, the p5.Env + * will be used to "play" the p5.Noise like a drum by controlling its output + * amplitude. A p5.Amplitude will get the level of all sound in the sketch, and + * we'll use this value to draw a green rectangle that shows the envelope + * in action.

+ *

To run this example locally, you will need the + * p5.sound library and a + * sound file.

+ */ +let noise, env, analyzer; + +function setup() { + createCanvas(710, 200); + noise = new p5.Noise(); // other types include 'brown' and 'pink' + noise.start(); + + // multiply noise volume by 0 + // (keep it quiet until we're ready to make noise!) + noise.amp(0); + + env = new p5.Env(); + // set attackTime, decayTime, sustainRatio, releaseTime + env.setADSR(0.001, 0.1, 0.2, 0.1); + // set attackLevel, releaseLevel + env.setRange(1, 0); + + // p5.Amplitude will analyze all sound in the sketch + // unless the setInput() method is used to specify an input. + analyzer = new p5.Amplitude(); +} + +function draw() { + background(0); + + // get volume reading from the p5.Amplitude analyzer + let level = analyzer.getLevel(); + + // use level to draw a green rectangle + let levelHeight = map(level, 0, 0.4, 0, height); + fill(100, 250, 100); + rect(0, height, width, -levelHeight); +} + +function mousePressed() { + env.play(noise); +} diff --git a/src/data/examples/ko/33_Sound/09_Note_Envelope.js b/src/data/examples/ko/33_Sound/09_Note_Envelope.js new file mode 100644 index 0000000000..4b9122d244 --- /dev/null +++ b/src/data/examples/ko/33_Sound/09_Note_Envelope.js @@ -0,0 +1,61 @@ +/** + * @name Note Envelope + * @description

An Envelope is a series of fades, defined + * as time / value pairs. In this example, the envelope + * will be used to "play" a note by controlling the output + * amplitude of an oscillator.

+ * The p5.Oscillator sends its output through + * an internal Web Audio GainNode (p5.Oscillator.output). + * By default, that node has a constant value of 0.5. It can + * be reset with the osc.amp() method. Or, in this example, an + * Envelope takes control of that node, turning the amplitude + * up and down like a volume knob.

+ *

To run this example locally, you will need the + * p5.sound library and a + * sound file.

+ */ +let osc, envelope, fft; + +let scaleArray = [60, 62, 64, 65, 67, 69, 71, 72]; +let note = 0; + +function setup() { + createCanvas(710, 200); + osc = new p5.SinOsc(); + + // Instantiate the envelope + envelope = new p5.Env(); + + // set attackTime, decayTime, sustainRatio, releaseTime + envelope.setADSR(0.001, 0.5, 0.1, 0.5); + + // set attackLevel, releaseLevel + envelope.setRange(1, 0); + + osc.start(); + + fft = new p5.FFT(); + noStroke(); +} + +function draw() { + background(20); + + if (frameCount % 60 === 0 || frameCount === 1) { + let midiValue = scaleArray[note]; + let freqValue = midiToFreq(midiValue); + osc.freq(freqValue); + + envelope.play(osc, 0, 0.1); + note = (note + 1) % scaleArray.length; + } + + // plot FFT.analyze() frequency analysis on the canvas + let spectrum = fft.analyze(); + for (let i = 0; i < spectrum.length / 20; i++) { + fill(spectrum[i], spectrum[i] / 10, 0); + let x = map(i, 0, spectrum.length / 20, 0, width); + let h = map(spectrum[i], 0, 255, 0, height); + rect(x, height, spectrum.length / 20, -h); + } +} diff --git a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js new file mode 100644 index 0000000000..4737680b81 --- /dev/null +++ b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js @@ -0,0 +1,40 @@ +/* + * @name Oscillator Frequency + * @description

Control an Oscillator and view the waveform using FFT. + * MouseX is mapped to frequency, mouseY is mapped to amplitude.

+ *

To run this example locally, you will need the + * p5.sound library and a + * sound file.

+ */ +let osc, fft; + +function setup() { + createCanvas(720, 256); + + osc = new p5.TriOsc(); // set frequency and type + osc.amp(0.5); + + fft = new p5.FFT(); + osc.start(); +} + +function draw() { + background(255); + + let waveform = fft.waveform(); // analyze the waveform + beginShape(); + strokeWeight(5); + for (let i = 0; i < waveform.length; i++) { + let x = map(i, 0, waveform.length, 0, width); + let y = map(waveform[i], -1, 1, height, 0); + vertex(x, y); + } + endShape(); + + // change oscillator frequency based on mouseX + let freq = map(mouseX, 0, width, 40, 880); + osc.freq(freq); + + let amp = map(mouseY, 0, height, 1, 0.01); + osc.amp(amp); +} diff --git a/src/data/examples/ko/33_Sound/11_Live_Input.js b/src/data/examples/ko/33_Sound/11_Live_Input.js new file mode 100644 index 0000000000..30136d62a0 --- /dev/null +++ b/src/data/examples/ko/33_Sound/11_Live_Input.js @@ -0,0 +1,36 @@ +/** + * @name Mic Input + * @description

Get audio input from your computer's microphone. + * Make noise to float the ellipse.

+ *

Note: p5.AudioIn contains its own p5.Amplitude object, + * so you can call getLevel on p5.AudioIn without + * creating a p5.Amplitude.

+ *

To run this example locally, you will need the + * p5.sound library + * and a running local server.

+ */ +let mic; + +function setup() { + createCanvas(710, 200); + + // Create an Audio input + mic = new p5.AudioIn(); + + // start the Audio Input. + // By default, it does not .connect() (to the computer speakers) + mic.start(); +} + +function draw() { + background(200); + + // Get the overall volume (between 0 and 1.0) + let vol = mic.getLevel(); + fill(127); + stroke(0); + + // Draw an ellipse with height based on volume + let h = map(vol, 0, 1, height, 0); + ellipse(width / 2, h - 25, 50, 50); +} diff --git a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js new file mode 100644 index 0000000000..9bc8dedfd7 --- /dev/null +++ b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js @@ -0,0 +1,30 @@ +/** + * @name Frequency Spectrum + * @description

Visualize the frequency spectrum of live audio input.

+ *

To run this example locally, you will need the + * p5.sound library + * and a running local server.

+ */ +let mic, fft; + +function setup() { + createCanvas(710, 400); + noFill(); + + mic = new p5.AudioIn(); + mic.start(); + fft = new p5.FFT(); + fft.setInput(mic); +} + +function draw() { + background(200); + + let spectrum = fft.analyze(); + + beginShape(); + for (i = 0; i < spectrum.length; i++) { + vertex(i, map(spectrum[i], 0, 255, height, 0)); + } + endShape(); +} diff --git a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js new file mode 100644 index 0000000000..4c765b059d --- /dev/null +++ b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js @@ -0,0 +1,49 @@ +/** + * @name Mic Threshold + * @description

Trigger an event (draw a rectangle) when the Audio Input + * volume surpasses a threshold.

+ *

To run this example locally, you will need the + * p5.sound library + * and a running local server.

+ */ +// Adapted from Learning Processing, Daniel Shiffman +// learningprocessing.com +let input; +let analyzer; + +function setup() { + createCanvas(710, 200); + background(255); + + // Create an Audio input + input = new p5.AudioIn(); + + input.start(); +} + +function draw() { + // Get the overall volume (between 0 and 1.0) + let volume = input.getLevel(); + + // If the volume > 0.1, a rect is drawn at a random location. + // The louder the volume, the larger the rectangle. + let threshold = 0.1; + if (volume > threshold) { + stroke(0); + fill(0, 100); + rect(random(40, width), random(height), volume * 50, volume * 50); + } + + // Graph the overall potential volume, w/ a line at the threshold + let y = map(volume, 0, 1, height, 0); + let ythreshold = map(threshold, 0, 1, height, 0); + + noStroke(); + fill(175); + rect(0, 0, 20, height); + // Then draw a rectangle on the graph, sized according to volume + fill(0); + rect(0, y, 20, y); + stroke(0); + line(0, ythreshold, 19, ythreshold); +} diff --git a/src/data/examples/ko/33_Sound/14_Filter_LowPass.js b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js new file mode 100644 index 0000000000..d1337ed63e --- /dev/null +++ b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js @@ -0,0 +1,62 @@ +/** + * @name Filter LowPass + * @description Apply a p5.LowPass filter to a p5.SoundFile. + * Visualize the sound with FFT. + * Map mouseX to the the filter's cutoff frequency + * and mouseY to resonance/width of the a BandPass filter + * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let soundFile; +let fft; + +let filter, filterFreq, filterRes; + +function preload() { + soundFormats('mp3', 'ogg'); + soundFile = loadSound('assets/beat'); +} + +function setup() { + createCanvas(710, 256); + fill(255, 40, 255); + + // loop the sound file + soundFile.loop(); + + filter = new p5.LowPass(); + + // Disconnect soundfile from master output. + // Then, connect it to the filter, so that we only hear the filtered sound + soundFile.disconnect(); + soundFile.connect(filter); + + fft = new p5.FFT(); +} + +function draw() { + background(30); + + // Map mouseX to a the cutoff frequency from the lowest + // frequency (10Hz) to the highest (22050Hz) that humans can hear + filterFreq = map(mouseX, 0, width, 10, 22050); + + // Map mouseY to resonance (volume boost) at the cutoff frequency + filterRes = map(mouseY, 0, height, 15, 5); + + // set filter parameters + filter.set(filterFreq, filterRes); + + // Draw every value in the FFT spectrum analysis where + // x = lowest (10Hz) to highest (22050Hz) frequencies, + // h = energy (amplitude / volume) at that frequency + let spectrum = fft.analyze(); + noStroke(); + for (let i = 0; i < spectrum.length; i++) { + let x = map(i, 0, spectrum.length, 0, width); + let h = -height + map(spectrum[i], 0, 255, height, 0); + rect(x, height, width / spectrum.length, h); + } +} diff --git a/src/data/examples/ko/33_Sound/15_Filter_BandPass.js b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js new file mode 100644 index 0000000000..5e128fcec1 --- /dev/null +++ b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js @@ -0,0 +1,51 @@ +/** + * @name Filter BandPass + * @description Apply a p5.BandPass filter to white noise. + * Visualize the sound with FFT. + * Map mouseX to the bandpass frequency + * and mouseY to resonance/width of the a BandPass filter + * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let noise; +let fft; +let filter, filterFreq, filterWidth; + +function setup() { + createCanvas(710, 256); + fill(255, 40, 255); + + filter = new p5.BandPass(); + + noise = new p5.Noise(); + + noise.disconnect(); // Disconnect soundfile from master output... + filter.process(noise); // ...and connect to filter so we'll only hear BandPass. + noise.start(); + + fft = new p5.FFT(); +} + +function draw() { + background(30); + + // Map mouseX to a bandpass freq from the FFT spectrum range: 10Hz - 22050Hz + filterFreq = map(mouseX, 0, width, 10, 22050); + // Map mouseY to resonance/width + filterWidth = map(mouseY, 0, height, 0, 90); + // set filter parameters + filter.set(filterFreq, filterWidth); + + // Draw every value in the FFT spectrum analysis where + // x = lowest (10Hz) to highest (22050Hz) frequencies, + // h = energy / amplitude at that frequency + let spectrum = fft.analyze(); + noStroke(); + for (let i = 0; i < spectrum.length; i++) { + let x = map(i, 0, spectrum.length, 0, width); + let h = -height + map(spectrum[i], 0, 255, height, 0); + rect(x, height, width / spectrum.length, h); + } +} diff --git a/src/data/examples/ko/33_Sound/16_Delay.js b/src/data/examples/ko/33_Sound/16_Delay.js new file mode 100644 index 0000000000..0027b42f73 --- /dev/null +++ b/src/data/examples/ko/33_Sound/16_Delay.js @@ -0,0 +1,56 @@ +/** + * @name Delay + * @description + * Click the mouse to hear the p5.Delay process a SoundFile. + * MouseX controls the p5.Delay Filter Frequency. + * MouseY controls both the p5.Delay Time and Resonance. + * Visualize the resulting sound's volume with an Amplitude object. + * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ + +let soundFile, analyzer, delay; + +function preload() { + soundFormats('ogg', 'mp3'); + soundFile = loadSound('assets/beatbox.mp3'); +} + +function setup() { + createCanvas(710, 400); + + soundFile.disconnect(); // so we'll only hear delay + + delay = new p5.Delay(); + delay.process(soundFile, 0.12, 0.7, 2300); + delay.setType('pingPong'); // a stereo effect + + analyzer = new p5.Amplitude(); +} + +function draw() { + background(0); + + // get volume reading from the p5.Amplitude analyzer + let level = analyzer.getLevel(); + + // use level to draw a green rectangle + let levelHeight = map(level, 0, 0.1, 0, height); + fill(100, 250, 100); + rect(0, height, width, -levelHeight); + + let filterFreq = map(mouseX, 0, width, 60, 15000); + filterFreq = constrain(filterFreq, 60, 15000); + let filterRes = map(mouseY, 0, height, 3, 0.01); + filterRes = constrain(filterRes, 0.01, 3); + delay.filter(filterFreq, filterRes); + let delTime = map(mouseY, 0, width, 0.2, 0.01); + delTime = constrain(delTime, 0.01, 0.2); + delay.delayTime(delTime); +} + +function mousePressed() { + soundFile.play(); +} diff --git a/src/data/examples/ko/33_Sound/17_Reverb.js b/src/data/examples/ko/33_Sound/17_Reverb.js new file mode 100644 index 0000000000..db99aa3ed1 --- /dev/null +++ b/src/data/examples/ko/33_Sound/17_Reverb.js @@ -0,0 +1,36 @@ +/** + * @name Reverb + * @description Reverb gives depth and perceived space to a sound. Here, + * noise is processed with reverb. + * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let sound, reverb; + +function preload() { + soundFormats('mp3', 'ogg'); + soundFile = loadSound('assets/Damscray_DancingTiger'); + + // disconnect the default connection + // so that we only hear the sound via the reverb.process + soundFile.disconnect(); +} + +function setup() { + createCanvas(720, 100); + background(0); + + reverb = new p5.Reverb(); + + // sonnects soundFile to reverb with a + // reverbTime of 6 seconds, decayRate of 0.2% + reverb.process(soundFile, 6, 0.2); + + reverb.amp(4); // turn it up! +} + +function mousePressed() { + soundFile.play(); +} diff --git a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js new file mode 100644 index 0000000000..bfcfecb57e --- /dev/null +++ b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js @@ -0,0 +1,87 @@ +/** + * @name Convolution Reverb + * @description

The p5.Convolver can recreate the sound of actual + * spaces using convolution. Convolution takes an Impulse Response, + * (the sound of a room reverberating), and uses that to + * recreate the sound of that space.

Click to play a sound through + * convolution. Every time you click, the sound is convolved with + * a different Impulse Response. To hear the Impulse Response itself, + * press any key.

+ * + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server. + * These convolution samples are Creative Commons BY + * + * recordinghopkins

+ */ +let sound, env, cVerb, fft; +let currentIR = 0; +let rawImpulse; + +function preload() { + // we have included both MP3 and OGG versions of all the impulses/sounds + soundFormats('ogg', 'mp3'); + + // create a p5.Convolver + cVerb = createConvolver('assets/bx-spring'); + + // add Impulse Responses to cVerb.impulses array, in addition to bx-spring + cVerb.addImpulse('assets/small-plate'); + cVerb.addImpulse('assets/drum'); + cVerb.addImpulse('assets/beatbox'); + cVerb.addImpulse('assets/concrete-tunnel'); + + // load a sound that will be processed by the p5.ConvultionReverb + sound = loadSound('assets/Damscray_DancingTiger'); +} + +function setup() { + createCanvas(710, 400); + rawImpulse = loadSound('assets/' + cVerb.impulses[currentIR].name); + + // disconnect from master output... + sound.disconnect(); + // ... and process with cVerb + // so that we only hear the reverb + cVerb.process(sound); + + fft = new p5.FFT(); +} + +function draw() { + background(30); + fill(0, 255, 40); + + let spectrum = fft.analyze(); + + // Draw every value in the frequencySpectrum array as a rectangle + noStroke(); + for (let i = 0; i < spectrum.length; i++) { + let x = map(i, 0, spectrum.length, 0, width); + let h = -height + map(spectrum[i], 0, 255, height, 0); + rect(x, height, width / spectrum.length, h); + } +} + +function mousePressed() { + // cycle through the array of cVerb.impulses + currentIR++; + if (currentIR >= cVerb.impulses.length) { + currentIR = 0; + } + cVerb.toggleImpulse(currentIR); + + // play the sound through the impulse + sound.play(); + + // display the current Impulse Response name (the filepath) + println('Convolution Impulse Response: ' + cVerb.impulses[currentIR].name); + + rawImpulse.setPath('assets/' + cVerb.impulses[currentIR].name); +} + +// play the impulse (without convolution) +function keyPressed() { + rawImpulse.play(); +} diff --git a/src/data/examples/ko/33_Sound/19_Record_Save.js b/src/data/examples/ko/33_Sound/19_Record_Save.js new file mode 100644 index 0000000000..b44b7379a8 --- /dev/null +++ b/src/data/examples/ko/33_Sound/19_Record_Save.js @@ -0,0 +1,58 @@ +/** + * @name Record Save Audio + * @description Record a sound, play it back and save + * it as a .wav file to the client's computer. + * We need three objects: a p5.AudioIn (mic / sound source), + * p5.SoundRecorder (records the sound), and a + * p5.SoundFile (play back / save). + *

To run this example locally, you will need the + * p5.sound library + * a sound file, and a running local server.

+ */ +let mic, recorder, soundFile; + +let state = 0; // mousePress will increment from Record, to Stop, to Play + +function setup() { + createCanvas(400, 400); + background(200); + fill(0); + text('Enable mic and click the mouse to begin recording', 20, 20); + + // create an audio in + mic = new p5.AudioIn(); + + // users must manually enable their browser microphone for recording to work properly! + mic.start(); + + // create a sound recorder + recorder = new p5.SoundRecorder(); + + // connect the mic to the recorder + recorder.setInput(mic); + + // create an empty sound file that we will use to playback the recording + soundFile = new p5.SoundFile(); +} + +function mousePressed() { + // use the '.enabled' boolean to make sure user enabled the mic (otherwise we'd record silence) + if (state === 0 && mic.enabled) { + // Tell recorder to record to a p5.SoundFile which we will use for playback + recorder.record(soundFile); + + background(255, 0, 0); + text('Recording now! Click to stop.', 20, 20); + state++; + } else if (state === 1) { + recorder.stop(); // stop recorder, and send the result to soundFile + + background(0, 255, 0); + text('Recording stopped. Click to play & save', 20, 20); + state++; + } else if (state === 2) { + soundFile.play(); // play the result! + saveSound(soundFile, 'mySound.wav'); // save file + state++; + } +} diff --git a/src/data/examples/ko/33_Sound/21_FreqModulation.js b/src/data/examples/ko/33_Sound/21_FreqModulation.js new file mode 100644 index 0000000000..ab51e8bc61 --- /dev/null +++ b/src/data/examples/ko/33_Sound/21_FreqModulation.js @@ -0,0 +1,148 @@ +/** + * @name Frequency Modulation + * @description

Frequency Modulation is a powerful form of synthesis. + * In its simplest form, FM involves two oscillators, referred + * to as the carrier and the modulator. As the modulator's waveform oscillates + * between some minimum and maximum amplitude value, that momentary value + * is added to ("modulates") the frequency of the carrier.

+ *

The carrier is typically set to oscillate at an audible frequency + * that we perceive as a pitch—in this case, it is a sine wave oscilaltor at 220Hz, + * equivalent to an "A3" note. The carrier is connected to master output by default + * (this is the case for all p5.Oscillators).

+ *

We will disconnect the modulator from master output, + * and instead connect to the frequency of the carrier: + * carrier.freq(modulator). This adds the output amplitude of the + * modulator to the frequency of the carrier.

+ *

+ * Modulation Depth describes how much the carrier frequency will modulate. + * It is based on the amplitude of the modulator. + * The modulator produces a continuous stream of amplitude values that we will add + * to the carrier frequency. An amplitude of zero means silence, so the modulation will + * have no effect. An amplitude of 1.0 scales the range of output values + * between +1.0 and -1.0. That is the standard range for sound that gets sent to + * your speakers, but in FM we are instead sending the modulator's output to the carrier frequency, + * where we'd barely notice the +1Hz / -1Hz modulation. + * So we will typically increase the amplitude ("depth") of the modulator to numbers much higher than what + * we might send to our speakers.

+ *

Modulation Frequency is the speed of modulation. When the modulation frequency is lower + * than 20Hz, we stop hearing its frequency as pitch, and start to hear it as a beating rhythm. + * For example, try 7.5Hz at a depth of 20 to mimic the "vibrato" effect of an operatic vocalist. + * The term for this is Low Frequency Oscillator, or LFO. Modulators set to higher frequencies can + * also produce interesting effects, especially when the frequency has a harmonic relationship + * to the carrier signal. For example, listen to what happens when the modulator's frequency is + * half or twice that of the carrier. This is the basis for FM Synthesis, developed by John Chowning + * in the 1960s, which came to revolutionize synthesis in the 1980s and is often used to synthesize + * brass and bell-like sounds. + * + *

In this example,

+ * - MouseX controls the modulation depth (the amplitude of the modulator) from -150 to 150. + * When the modulator's amplitude is set to 0 (in the middle), notice how the modulation + * has no effect. The greater (the absolute value of) the number, the greater the effect. + * If the modulator waveform is symetrical like a square [], sine ~ + * or triangle /\, the negative amplitude will be the same as positive amplitude. + * But in this example, the modulator is an asymetrical sawtooth wave, shaped like this /. + * When we multiply it by a negative number, it goes backwards like this \. To best + * observe the difference, try lowering the frequency. + *

+ *

- MouseY controls the frequency of the modulator from 0 to 112 Hz. + * Try comparing modulation frequencies below the audible range (which starts around 20hz), + * and above it, especially in a harmonic relationship to the carrier frequency (which is 220hz, so + * try half that, 1/3, 1/4 etc...). + * + *

You will need to include the + * p5.sound library + * for this example to work in your own project.

+ */ + +let carrier; // this is the oscillator we will hear +let modulator; // this oscillator will modulate the frequency of the carrier + +let analyzer; // we'll use this visualize the waveform + +// the carrier frequency pre-modulation +let carrierBaseFreq = 220; + +// min/max ranges for modulator +let modMaxFreq = 112; +let modMinFreq = 0; +let modMaxDepth = 150; +let modMinDepth = -150; + +function setup() { + let cnv = createCanvas(800, 400); + noFill(); + + carrier = new p5.Oscillator('sine'); + carrier.amp(0); // set amplitude + carrier.freq(carrierBaseFreq); // set frequency + carrier.start(); // start oscillating + + // try changing the type to 'square', 'sine' or 'triangle' + modulator = new p5.Oscillator('sawtooth'); + modulator.start(); + + // add the modulator's output to modulate the carrier's frequency + modulator.disconnect(); + carrier.freq(modulator); + + // create an FFT to analyze the audio + analyzer = new p5.FFT(); + + // fade carrier in/out on mouseover / touch start + toggleAudio(cnv); +} + +function draw() { + background(30); + + // map mouseY to modulator freq between a maximum and minimum frequency + let modFreq = map(mouseY, height, 0, modMinFreq, modMaxFreq); + modulator.freq(modFreq); + + // change the amplitude of the modulator + // negative amp reverses the sawtooth waveform, and sounds percussive + // + let modDepth = map(mouseX, 0, width, modMinDepth, modMaxDepth); + modulator.amp(modDepth); + + // analyze the waveform + waveform = analyzer.waveform(); + + // draw the shape of the waveform + stroke(255); + strokeWeight(10); + beginShape(); + for (let i = 0; i < waveform.length; i++) { + let x = map(i, 0, waveform.length, 0, width); + let y = map(waveform[i], -1, 1, -height / 2, height / 2); + vertex(x, y + height / 2); + } + endShape(); + + strokeWeight(1); + // add a note about what's happening + text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20); + text( + 'Modulator Amplitude (Modulation Depth): ' + modDepth.toFixed(3), + 20, + 40 + ); + text( + 'Carrier Frequency (pre-modulation): ' + carrierBaseFreq + ' Hz', + width / 2, + 20 + ); +} + +// helper function to toggle sound +function toggleAudio(cnv) { + cnv.mouseOver(function() { + carrier.amp(1.0, 0.01); + }); + cnv.touchStarted(function() { + carrier.amp(1.0, 0.01); + }); + cnv.mouseOut(function() { + carrier.amp(0.0, 1.0); + }); +} diff --git a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js new file mode 100644 index 0000000000..bc77cbd091 --- /dev/null +++ b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js @@ -0,0 +1,95 @@ +/** + * @name Amplitude Modulation + * @description

Amplitude Modulation involves two oscillators, referred + * to as the carrier and the modulator, where the modulator controls + * the carrier's amplitude.

+ * + *

The carrier is typically set at an audible frequency (i.e. 440 Hz) + * and connected to master output by default. The carrier.amp is + * set to zero because we will have the modulator control its amplitude.

+ * + *

The modulator is disconnected from master output. Instead, it is connected + * to the amplitude of the Carrier, like this: carrier.amp(modulator).

+ * + *

In this example...

+ *

- MouseX controls the amplitude of the modulator + * from 0 to 1. When the modulator's amplitude is set to 0, the + * amplitude modulation has no effect.

+ * + *

- MouseY controls the frequency of the modulator from 0 to 20hz. + * This range is lower frequencies than humans can hear, and we perceive the + * modulation as a rhythm. This range can simulate effects such as Tremolo. + * Ring Modulation is a type of Amplitude Modulation where the original + * carrier signal is not present, and often involves modulation at a faster + * frequency.

+ * + *

You will need to include the + * p5.sound library + * for this example to work in your own project.

+ */ +let carrier; // this is the oscillator we will hear +let modulator; // this oscillator will modulate the amplitude of the carrier +let fft; // we'll visualize the waveform + +function setup() { + createCanvas(800, 400); + noFill(); + background(30); // alpha + + carrier = new p5.Oscillator(); // connects to master output by default + carrier.freq(340); + carrier.amp(0); + // carrier's amp is 0 by default, giving our modulator total control + + carrier.start(); + + modulator = new p5.Oscillator('triangle'); + modulator.disconnect(); // disconnect the modulator from master output + modulator.freq(5); + modulator.amp(1); + modulator.start(); + + // Modulate the carrier's amplitude with the modulator + // Optionally, we can scale the signal. + carrier.amp(modulator.scale(-1, 1, 1, -1)); + + // create an fft to analyze the audio + fft = new p5.FFT(); +} + +function draw() { + background(30, 30, 30, 100); // alpha + + // map mouseY to moodulator freq between 0 and 20hz + let modFreq = map(mouseY, 0, height, 20, 0); + modulator.freq(modFreq); + + let modAmp = map(mouseX, 0, width, 0, 1); + modulator.amp(modAmp, 0.01); // fade time of 0.1 for smooth fading + + // analyze the waveform + waveform = fft.waveform(); + + // draw the shape of the waveform + drawWaveform(); + + drawText(modFreq, modAmp); +} + +function drawWaveform() { + stroke(240); + strokeWeight(4); + beginShape(); + for (let i = 0; i < waveform.length; i++) { + let x = map(i, 0, waveform.length, 0, width); + let y = map(waveform[i], -1, 1, -height / 2, height / 2); + vertex(x, y + height / 2); + } + endShape(); +} + +function drawText(modFreq, modAmp) { + strokeWeight(1); + text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20); + text('Modulator Amplitude: ' + modAmp.toFixed(3), 20, 40); +} diff --git a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js new file mode 100644 index 0000000000..0942148573 --- /dev/null +++ b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js @@ -0,0 +1,58 @@ +/* + * @name Acceleration Ball Bounce + * @description Move an ellipse around based on accelerationX and accelerationY values, and bounces when touch the edge of the canvas. + */ + +// Position Variables +let x = 0; +let y = 0; + +// Speed - Velocity +let vx = 0; +let vy = 0; + +// Acceleration +let ax = 0; +let ay = 0; + +let vMultiplier = 0.007; +let bMultiplier = 0.6; + +function setup() { + createCanvas(displayWidth, displayHeight); + fill(0); +} + +function draw() { + background(255); + ballMove(); + ellipse(x, y, 30, 30); +} + +function ballMove() { + ax = accelerationX; + ay = accelerationY; + + vx = vx + ay; + vy = vy + ax; + y = y + vy * vMultiplier; + x = x + vx * vMultiplier; + + // Bounce when touch the edge of the canvas + if (x < 0) { + x = 0; + vx = -vx * bMultiplier; + } + if (y < 0) { + y = 0; + vy = -vy * bMultiplier; + } + if (x > width - 20) { + x = width - 20; + vx = -vx * bMultiplier; + } + if (y > height - 20) { + y = height - 20; + vy = -vy * bMultiplier; + } +} diff --git a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js new file mode 100644 index 0000000000..80cddb8562 --- /dev/null +++ b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js @@ -0,0 +1,15 @@ +/* + * @name Simple Draw + * @description Touch to draw on the screen using mouseX, mouseY, pmouseX, and pmouseY values. + */ + +function setup() { + createCanvas(displayWidth, displayHeight); + strokeWeight(10); + stroke(0); +} + +function touchMoved() { + line(mouseX, mouseY, pmouseX, pmouseY); + return false; +} diff --git a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js new file mode 100644 index 0000000000..a7183d1def --- /dev/null +++ b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js @@ -0,0 +1,24 @@ +/* + * @name Acceleration Color + * @description Use deviceMoved() to detect when the device is rotated. The background RGB color values are mapped to accelerationX, accelerationY, and accelerationZ values. + */ + +let r, g, b; + +function setup() { + createCanvas(displayWidth, displayHeight); + r = random(50, 255); + g = random(0, 200); + b = random(50, 255); +} + +function draw() { + background(r, g, b); + console.log('draw'); +} + +function deviceMoved() { + r = map(accelerationX, -90, 90, 100, 175); + g = map(accelerationY, -90, 90, 100, 200); + b = map(accelerationZ, -90, 90, 100, 200); +} diff --git a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js new file mode 100644 index 0000000000..5d2880dbe7 --- /dev/null +++ b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js @@ -0,0 +1,114 @@ +/* + * @name Shake Ball Bounce + * @description Create a Ball class, instantiate multiple objects, move it around the screen, and bounce when touch the edge of the canvas. + * Detect shake event based on total change in accelerationX and accelerationY and speed up or slow down objects based on detection. + */ + +let balls = []; + +let threshold = 30; +let accChangeX = 0; +let accChangeY = 0; +let accChangeT = 0; + +function setup() { + createCanvas(displayWidth, displayHeight); + + for (let i = 0; i < 20; i++) { + balls.push(new Ball()); + } +} + +function draw() { + background(0); + + for (let i = 0; i < balls.length; i++) { + balls[i].move(); + balls[i].display(); + } + + checkForShake(); +} + +function checkForShake() { + // Calculate total change in accelerationX and accelerationY + accChangeX = abs(accelerationX - pAccelerationX); + accChangeY = abs(accelerationY - pAccelerationY); + accChangeT = accChangeX + accChangeY; + // If shake + if (accChangeT >= threshold) { + for (let i = 0; i < balls.length; i++) { + balls[i].shake(); + balls[i].turn(); + } + } + // If not shake + else { + for (let i = 0; i < balls.length; i++) { + balls[i].stopShake(); + balls[i].turn(); + balls[i].move(); + } + } +} + +// Ball class +class Ball { + constructor() { + this.x = random(width); + this.y = random(height); + this.diameter = random(10, 30); + this.xspeed = random(-2, 2); + this.yspeed = random(-2, 2); + this.oxspeed = this.xspeed; + this.oyspeed = this.yspeed; + this.direction = 0.7; + } + + move() { + this.x += this.xspeed * this.direction; + this.y += this.yspeed * this.direction; + } + + // Bounce when touch the edge of the canvas + turn() { + if (this.x < 0) { + this.x = 0; + this.direction = -this.direction; + } else if (this.y < 0) { + this.y = 0; + this.direction = -this.direction; + } else if (this.x > width - 20) { + this.x = width - 20; + this.direction = -this.direction; + } else if (this.y > height - 20) { + this.y = height - 20; + this.direction = -this.direction; + } + } + + // Add to xspeed and yspeed based on + // the change in accelerationX value + shake() { + this.xspeed += random(5, accChangeX / 3); + this.yspeed += random(5, accChangeX / 3); + } + + // Gradually slows down + stopShake() { + if (this.xspeed > this.oxspeed) { + this.xspeed -= 0.6; + } else { + this.xspeed = this.oxspeed; + } + if (this.yspeed > this.oyspeed) { + this.yspeed -= 0.6; + } else { + this.yspeed = this.oyspeed; + } + } + + display() { + ellipse(this.x, this.y, this.diameter, this.diameter); + } +} diff --git a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js new file mode 100644 index 0000000000..ea39b5414f --- /dev/null +++ b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js @@ -0,0 +1,15 @@ +/* + * @name Tilted 3D Box + * @description Use mobile to tilt a box + */ +function setup() { + createCanvas(displayWidth, displayHeight, WEBGL); +} + +function draw() { + background(250); + normalMaterial(); + rotateX(accelerationX * 0.01); + rotateY(accelerationY * 0.01); + box(100, 100, 100); +} diff --git a/src/data/examples/ko/90_Hello_P5/01_shapes.js b/src/data/examples/ko/90_Hello_P5/01_shapes.js new file mode 100644 index 0000000000..5196abef4a --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/01_shapes.js @@ -0,0 +1,28 @@ +/* + * @name Simple Shapes + * @description This examples includes a circle, square, triangle, and a flower. + */ +function setup() { + // Create the canvas + createCanvas(720, 400); + background(200); + + // Set colors + fill(204, 101, 192, 127); + stroke(127, 63, 120); + + // A rectangle + rect(40, 120, 120, 40); + // An ellipse + ellipse(240, 240, 80, 80); + // A triangle + triangle(300, 100, 320, 100, 310, 80); + + // A design for a simple flower + translate(580, 200); + noStroke(); + for (let i = 0; i < 10; i ++) { + ellipse(0, 30, 20, 80); + rotate(PI/5); + } +} diff --git a/src/data/examples/ko/90_Hello_P5/02_interactivity.js b/src/data/examples/ko/90_Hello_P5/02_interactivity.js new file mode 100644 index 0000000000..2822149bcf --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/02_interactivity.js @@ -0,0 +1,40 @@ +/* + * @name Interactivity 1 + * @frame 720,425 + * @description The circle changes color when you click on it. + *

To run this example locally, you will need the + * p5.dom library. + *

+ */ + +// for red, green, and blue color values +let r, g, b; + +function setup() { + createCanvas(720, 400); + // Pick colors randomly + r = random(255); + g = random(255); + b = random(255); +} + +function draw() { + background(127); + // Draw a circle + strokeWeight(2); + stroke(r, g, b); + fill(r, g, b, 127); + ellipse(360, 200, 200, 200); +} + +// When the user clicks the mouse +function mousePressed() { + // Check if mouse is inside the circle + let d = dist(mouseX, mouseY, 360, 200); + if (d < 100) { + // Pick new random color values + r = random(255); + g = random(255); + b = random(255); + } +} diff --git a/src/data/examples/ko/90_Hello_P5/03_interactivity.js b/src/data/examples/ko/90_Hello_P5/03_interactivity.js new file mode 100644 index 0000000000..08af063d3b --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/03_interactivity.js @@ -0,0 +1,29 @@ +/* + * @name Interactivity 2 + * @frame 720,425 + * @description The circle changes color when you move the slider. + * You will need to include the + * p5.dom library + * for this example to work in your own project. + */ + +// A HTML range slider +let slider; + +function setup() { + createCanvas(720, 400); + // hue, saturation, and brightness + colorMode(HSB, 255); + // slider has a range between 0 and 255 with a starting value of 127 + slider = createSlider(0, 255, 127); +} + +function draw() { + background(127); + strokeWeight(2); + + // Set the hue according to the slider + stroke(slider.value(), 255, 255); + fill(slider.value(), 255, 255, 127); + ellipse(360, 200, 200, 200); +} \ No newline at end of file diff --git a/src/data/examples/ko/90_Hello_P5/04_animate.js b/src/data/examples/ko/90_Hello_P5/04_animate.js new file mode 100644 index 0000000000..7c87da3a24 --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/04_animate.js @@ -0,0 +1,33 @@ +/* + * @name Animation + * @description The circle moves. + */ +// Where is the circle +let x, y; + +function setup() { + createCanvas(720, 400); + // Starts in the middle + x = width / 2; + y = height; +} + +function draw() { + background(200); + + // Draw a circle + stroke(50); + fill(100); + ellipse(x, y, 24, 24); + + // Jiggling randomly on the horizontal axis + x = x + random(-1, 1); + // Moving up at a constant speed + y = y - 1; + + // Reset to the bottom + if (y < 0) { + y = height; + } +} + diff --git a/src/data/examples/ko/90_Hello_P5/04_flocking.js b/src/data/examples/ko/90_Hello_P5/04_flocking.js new file mode 100644 index 0000000000..93c5cd6b2f --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/04_flocking.js @@ -0,0 +1,185 @@ +/* + * @name Flocking + * @description Demonstration of Craig Reynolds' "Flocking" behavior.
+ * (Rules: Cohesion, Separation, Alignment.)
+ * From natureofcode.com. + */ +let boids = []; + +function setup() { + createCanvas(720, 400); + + // Add an initial set of boids into the system + for (let i = 0; i < 100; i++) { + boids[i] = new Boid(random(width), random(height)); + } +} + +function draw() { + background(51); + // Run all the boids + for (let i = 0; i < boids.length; i++) { + boids[i].run(boids); + } +} + +// Boid class +// Methods for Separation, Cohesion, Alignment added +class Boid { + constructor(x, y) { + this.acceleration = createVector(0, 0); + this.velocity = p5.Vector.random2D(); + this.position = createVector(x, y); + this.r = 3.0; + this.maxspeed = 3; // Maximum speed + this.maxforce = 0.05; // Maximum steering force + } + + run(boids) { + this.flock(boids); + this.update(); + this.borders(); + this.render(); + } + + // Forces go into acceleration + applyForce(force) { + this.acceleration.add(force); + } + + // We accumulate a new acceleration each time based on three rules + flock(boids) { + let sep = this.separate(boids); // Separation + let ali = this.align(boids); // Alignment + let coh = this.cohesion(boids); // Cohesion + // Arbitrarily weight these forces + sep.mult(2.5); + ali.mult(1.0); + coh.mult(1.0); + // Add the force vectors to acceleration + this.applyForce(sep); + this.applyForce(ali); + this.applyForce(coh); + } + + // Method to update location + update() { + // Update velocity + this.velocity.add(this.acceleration); + // Limit speed + this.velocity.limit(this.maxspeed); + this.position.add(this.velocity); + // Reset acceleration to 0 each cycle + this.acceleration.mult(0); + } + + // A method that calculates and applies a steering force towards a target + // STEER = DESIRED MINUS VELOCITY + seek(target) { + let desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target + // Normalize desired and scale to maximum speed + desired.normalize(); + desired.mult(this.maxspeed); + // Steering = Desired minus Velocity + let steer = p5.Vector.sub(desired, this.velocity); + steer.limit(this.maxforce); // Limit to maximum steering force + return steer; + } + + // Draw boid as a circle + render() { + fill(127, 127); + stroke(200); + ellipse(this.position.x, this.position.y, 16, 16); + } + + // Wraparound + borders() { + if (this.position.x < -this.r) this.position.x = width + this.r; + if (this.position.y < -this.r) this.position.y = height + this.r; + if (this.position.x > width + this.r) this.position.x = -this.r; + if (this.position.y > height + this.r) this.position.y = -this.r; + } + + // Separation + // Method checks for nearby boids and steers away + separate(boids) { + let desiredseparation = 25.0; + let steer = createVector(0, 0); + let count = 0; + // For every boid in the system, check if it's too close + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position, boids[i].position); + // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) + if ((d > 0) && (d < desiredseparation)) { + // Calculate vector pointing away from neighbor + let diff = p5.Vector.sub(this.position, boids[i].position); + diff.normalize(); + diff.div(d); // Weight by distance + steer.add(diff); + count++; // Keep track of how many + } + } + // Average -- divide by how many + if (count > 0) { + steer.div(count); + } + + // As long as the vector is greater than 0 + if (steer.mag() > 0) { + // Implement Reynolds: Steering = Desired - Velocity + steer.normalize(); + steer.mult(this.maxspeed); + steer.sub(this.velocity); + steer.limit(this.maxforce); + } + return steer; + } + + // Alignment + // For every nearby boid in the system, calculate the average velocity + align(boids) { + let neighbordist = 50; + let sum = createVector(0, 0); + let count = 0; + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position, boids[i].position); + if ((d > 0) && (d < neighbordist)) { + sum.add(boids[i].velocity); + count++; + } + } + if (count > 0) { + sum.div(count); + sum.normalize(); + sum.mult(this.maxspeed); + let steer = p5.Vector.sub(sum, this.velocity); + steer.limit(this.maxforce); + return steer; + } else { + return createVector(0, 0); + } + } + + // Cohesion + // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location + cohesion(boids) { + let neighbordist = 50; + let sum = createVector(0, 0); // Start with empty vector to accumulate all locations + let count = 0; + for (let i = 0; i < boids.length; i++) { + let d = p5.Vector.dist(this.position, boids[i].position); + if ((d > 0) && (d < neighbordist)) { + sum.add(boids[i].position); // Add location + count++; + } + } + if (count > 0) { + sum.div(count); + return this.seek(sum); // Steer towards the location + } else { + return createVector(0, 0); + } + } +} + diff --git a/src/data/examples/ko/90_Hello_P5/05_weather.js b/src/data/examples/ko/90_Hello_P5/05_weather.js new file mode 100644 index 0000000000..321ce86acb --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/05_weather.js @@ -0,0 +1,73 @@ +/* + * @name Weather + * @frame 720,280 + * @description This example grabs JSON weather data from apixu.com. + * You will need to include the + * p5.dom library + * for this example to work in your own project. +*/ + +// A wind direction vector +let wind; +// Circle position +let position; + +function setup() { + createCanvas(720, 200); + // Request the data from apixu.com + let url = 'https://api.apixu.com/v1/current.json?key=513d8003c8b348f1a2461629162106&q=NYC'; + loadJSON(url, gotWeather); + // Circle starts in the middle + position = createVector(width/2, height/2); + // wind starts as (0,0) + wind = createVector(); +} + +function draw() { + background(200); + + // This section draws an arrow pointing in the direction of wind + push(); + translate(32, height - 32); + // Rotate by the wind's angle + rotate(wind.heading() + PI/2); + noStroke(); + fill(255); + ellipse(0, 0, 48, 48); + + stroke(45, 123, 182); + strokeWeight(3); + line(0, -16, 0, 16); + + noStroke(); + fill(45, 123, 182); + triangle(0, -18, -6, -10, 6, -10); + pop(); + + // Move in the wind's direction + position.add(wind); + + stroke(0); + fill(51); + ellipse(position.x, position.y, 16, 16); + + if (position.x > width) position.x = 0; + if (position.x < 0) position.x = width; + if (position.y > height) position.y = 0; + if (position.y < 0) position.y = height; +} + +function gotWeather(weather) { + + // Get the angle (convert to radians) + let angle = radians(Number(weather.current.wind_degree)); + // Get the wind speed + let windmag = Number(weather.current.wind_mph); + + // Display as HTML elements + let temperatureDiv = createDiv(floor(weather.current.temp_f) + '°'); + let windDiv = createDiv("WIND " + windmag + " MPH"); + + // Make a vector + wind = p5.Vector.fromAngle(angle); +} diff --git a/src/data/examples/ko/90_Hello_P5/06_drawing.js b/src/data/examples/ko/90_Hello_P5/06_drawing.js new file mode 100644 index 0000000000..2450401328 --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/06_drawing.js @@ -0,0 +1,132 @@ +/* +* @name Drawing +* @description Generative painting program. +*/ + +// All the paths +let paths = []; +// Are we painting? +let painting = false; +// How long until the next circle +let next = 0; +// Where are we now and where were we? +let current; +let previous; + +function setup() { + createCanvas(720, 400); + current = createVector(0,0); + previous = createVector(0,0); +}; + +function draw() { + background(200); + + // If it's time for a new point + if (millis() > next && painting) { + + // Grab mouse position + current.x = mouseX; + current.y = mouseY; + + // New particle's force is based on mouse movement + let force = p5.Vector.sub(current, previous); + force.mult(0.05); + + // Add new particle + paths[paths.length - 1].add(current, force); + + // Schedule next circle + next = millis() + random(100); + + // Store mouse values + previous.x = current.x; + previous.y = current.y; + } + + // Draw all paths + for( let i = 0; i < paths.length; i++) { + paths[i].update(); + paths[i].display(); + } +} + +// Start it up +function mousePressed() { + next = 0; + painting = true; + previous.x = mouseX; + previous.y = mouseY; + paths.push(new Path()); +} + +// Stop +function mouseReleased() { + painting = false; +} + +// A Path is a list of particles +class Path { + constructor() { + this.particles = []; + this.hue = random(100); + } + + add(position, force) { + // Add a new particle with a position, force, and hue + this.particles.push(new Particle(position, force, this.hue)); + } + + // Display plath + update() { + for (let i = 0; i < this.particles.length; i++) { + this.particles[i].update(); + } + } + + // Display plath + display() { + // Loop through backwards + for (let i = this.particles.length - 1; i >= 0; i--) { + // If we shold remove it + if (this.particles[i].lifespan <= 0) { + this.particles.splice(i, 1); + // Otherwise, display it + } else { + this.particles[i].display(this.particles[i+1]); + } + } + + } +} + +// Particles along the path +class Particle { + constructor(position, force, hue) { + this.position = createVector(position.x, position.y); + this.velocity = createVector(force.x, force.y); + this.drag = 0.95; + this.lifespan = 255; + } + + update() { + // Move it + this.position.add(this.velocity); + // Slow it down + this.velocity.mult(this.drag); + // Fade it out + this.lifespan--; + } + + // Draw particle and connect it with a line + // Draw a line to another + display(other) { + stroke(0, this.lifespan); + fill(0, this.lifespan/2); + ellipse(this.position.x,this.position.y, 8, 8); + // If we need to draw a line + if (other) { + line(this.position.x, this.position.y, other.position.x, other.position.y); + } + } +} diff --git a/src/data/examples/ko/90_Hello_P5/07_song.js b/src/data/examples/ko/90_Hello_P5/07_song.js new file mode 100644 index 0000000000..5e4337b7c9 --- /dev/null +++ b/src/data/examples/ko/90_Hello_P5/07_song.js @@ -0,0 +1,119 @@ +/* + * @name Song + * @frame 720, 430 + * @description Play a song. + * You will need to include the + * p5.sound + * library for this example to work in your own project. + */ +// The midi notes of a scale +let notes = [ 60, 62, 64, 65, 67, 69, 71]; + +// For automatically playing the song +let index = 0; +let song = [ + { note: 4, duration: 400, display: "D" }, + { note: 0, duration: 200, display: "G" }, + { note: 1, duration: 200, display: "A" }, + { note: 2, duration: 200, display: "B" }, + { note: 3, duration: 200, display: "C" }, + { note: 4, duration: 400, display: "D" }, + { note: 0, duration: 400, display: "G" }, + { note: 0, duration: 400, display: "G" } +]; +let trigger = 0; +let autoplay = false; +let osc; + +function setup() { + createCanvas(720, 400); + let div = createDiv("Click to play notes or ") + div.id("instructions"); + let button = createButton("play song automatically."); + button.parent("instructions"); + // Trigger automatically playing + button.mousePressed(function() { + if (!autoplay) { + index = 0; + autoplay = true; + } + }); + + // A triangle oscillator + osc = new p5.TriOsc(); + // Start silent + osc.start(); + osc.amp(0); +} + +// A function to play a note +function playNote(note, duration) { + osc.freq(midiToFreq(note)); + // Fade it in + osc.fade(0.5,0.2); + + // If we sest a duration, fade it out + if (duration) { + setTimeout(function() { + osc.fade(0,0.2); + }, duration-50); + } +} + +function draw() { + + // If we are autoplaying and it's time for the next note + if (autoplay && millis() > trigger){ + playNote(notes[song[index].note], song[index].duration); + trigger = millis() + song[index].duration; + // Move to the next note + index ++; + // We're at the end, stop autoplaying. + } else if (index >= song.length) { + autoplay = false; + } + + + // Draw a keyboard + + // The width for each key + let w = width / notes.length; + for (let i = 0; i < notes.length; i++) { + let x = i * w; + // If the mouse is over the key + if (mouseX > x && mouseX < x + w && mouseY < height) { + // If we're clicking + if (mouseIsPressed) { + fill(100,255,200); + // Or just rolling over + } else { + fill(127); + } + } else { + fill(200); + } + + // Or if we're playing the song, let's highlight it too + if (autoplay && i === song[index-1].note) { + fill(100,255,200); + } + + // Draw the key + rect(x, 0, w-1, height-1); + } + +} + +// When we click +function mousePressed(event) { + if(event.button == 0 && event.clientX < width && event.clientY < height) { + // Map mouse to the key index + let key = floor(map(mouseX, 0, width, 0, notes.length)); + playNote(notes[key]); + } +} + +// Fade it out when we release +function mouseReleased() { + osc.fade(0,0.5); +} diff --git a/src/data/ko.yml b/src/data/ko.yml new file mode 100644 index 0000000000..901cd08c33 --- /dev/null +++ b/src/data/ko.yml @@ -0,0 +1,501 @@ +Home: "Home" +Download: "Download" +Start: "Start" +Reference: "Reference" +Libraries: "Libraries" +Learn: "Learn" +Examples: "Examples" +Books: "Books" +Community: "Community" +Contribute: "Contribute" +Forum: "Forum" + +footer1: "p5.js was created by " +footer2: " and is developed by a community of collaborators, with support from the " +footer3: " and " +footer4: "Identity and graphic design by " + +tagline1: "Processing fun times JavaScript quirkiness" +tagline2: "Processing simplicity times JavaScript flexibility" +tagline3: "Processing intuition times JavaScript power" +tagline4: "Processing creativity times JavaScript dynamism" +tagline5: "Processing community times JavaScript community" +tagline6: "the power of Processing times the reach of JavaScript" + +home: + Download: "Download" + Start: "Start" + Reference: "Reference" + Libraries: "Libraries" + Learn: "Learn" + Community: "Community" + p1x1: "안녕하세요! p5.js is a JavaScript library that starts with the original goal of " + p1x2: ", to make coding accessible for artists, designers, educators, and beginners, and reinterprets this for today's web." + p2x1: "Using the original metaphor of a software sketchbook, p5.js has a full set of drawing functionality. However, you're not limited to your drawing canvas, you can think of your whole browser page as your sketch! For this, p5.js has addon" + libraries: " libraries" + p2x2: " that make it" + interact: " easy to interact" + p2x3: " with other HTML5 objects, including text, input, video, webcam, and sound." + p3x1: "p5.js is a new interpretation, not an emulation or port, and it is in active development." + p3x2: "Try it out now in the new p5.js Web Editor!" + sketch_by: "by" + sketch_info: "CC Fest! November 10 @ NYU ITP" + sketch_info_link: "http://ccfest.rocks/" + +copyright: + copyright1: "The p5.js library is free software; you can redistribute it and/or modify it under the terms of the " + copyright2: " as published by the Free Software Foundation, version 2.1." + copyright3: "The Reference for the language is under a " + copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited." + +get started: + get-started-title: "Get Started" + get-started1: "This page walks you through setting up a p5.js project and making your first sketch." + get-started2: "If you'd like to start with the new " + get-started3: "p5.js Web Editor" + get-started4: ", you can jump down to" + get-started5: "Your First Sketch" + download-title: "Download and File Setup" + download1: "The easiest way to start is by using the empty example that comes with the " + download2: "p5.js complete" + download3: " download." + download4: "If you look in index.html, you'll notice that it links to the file p5.js. If you would like to use the minified version (compressed for faster page loading), change the link to p5.min.js." + download5: "Alternatively, you can link to a p5.js file hosted online. All versions of p5.js are stored in a CDN (Content Delivery Network). You can see a history of these versions here: " + download6: ". In this case you can change the link to:" + download7: "A sample HTML page might look like this:" + download8: "You can also start with this template from " + download9: "." + environment-title: "Environment" + environment1: "You can use the " + environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor" + environment2: " code editor " + environment3: "of your choice. Instructions for getting set up with " + environment4: " are included below, other good editor options include " + environment5: " and " + environment6: "If you are a screen reader user and not using the p5 web editor, you may want to use " + environment7: " or " + environment8: "Open Sublime. Go to the File menu and choose Open... and choose the folder that your html and js files are located in. On the left sidebar, you should now see the folder name at the top, with a list of the files contained in the folder directly below." + environment9: "Click on your sketch.js file and it will open on the right where you can edit it. " + environment10: "p5 starter code opened up in sublime editor." + environment11: "Open the index.html file in your browser by double clicking on it in your file manager or type:" + environment12: "file:///the/file/path/to/your/html" + environment13: " in the address bar to view your sketch." + your-first-sketch-title: "Your First Sketch" + your-first-sketch-intro1: "Processing users may want to check out the " + your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition" + your-first-sketch-intro3: "Processing transition tutorial" + your-first-sketch-intro4: "In your editor, type the following:" + your-first-sketch2: "This line of code means \"draw an ellipse, with the center 50 pixels over from the left and 50 pixels down from the top, with a width and height of 80 pixels\"." + your-first-sketch3: "Save your sketch and refresh your page view in your browser. If you've typed everything correctly, you'll see this appear in the display window:" + your-first-sketch4: "Note: If you are using a screen reader, you must either turn on the accessible outputs in the p5 online editor, outside the editor you must add the accessibility library in your html. To learn about " + your-first-sketch5: "using p5 with a screen reader click here" + your-first-sketch6: " and to learn more about " + your-first-sketch7: "the accessibility library here" + your-first-sketch8: "canvas has a circle of width and height 50 at position 80 x and 80 y" + your-first-sketch9: "If you didn't type it correctly, you might not see anything. If this happens, make sure that you've copied the example code exactly: the numbers should be contained within parentheses and have commas between each of them, and the line should end with a semicolon." + your-first-sketch10: "One of the most difficult things about getting started with programming is that you have to be very specific about the syntax. The browser isn't always smart enough to know what you mean, and can be quite fussy about the placement of punctuation. You'll get used to it with a little practice. Depending on the browser you are using, you can also see errors by looking at the JavaScript \"console\". In Chrome, for example, this is under View > Developer > JavaScript Console." + your-first-sketch11: "Next, we'll skip ahead to a sketch that's a little more exciting. Delete the text from the last example, and try this:" + your-first-sketch12: "This program creates a canvas that is 640 pixels wide and 480 pixels high, and then starts drawing white circles at the position of the mouse. When a mouse button is pressed, the circle color changes to black. We'll explain more about the elements of this program in detail later. For now, run the code, move the mouse, and click to experience it." + your-first-sketch13: "canvas has multiple circles drawn on it following the path of the mouse" + what-next-title: "What Next?" + processing-transition1: "Read the " + processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition" + processing-transition3: "Processing transition tutorial" + processing-transition4: " to learn how to convert from Processing to p5.js, and the main differences between them." + reference1: "View the " + reference2: " reference" + reference3: " for full documentation." + learn1: "Check out the " + learn2: "learn" + learn3: " page and " + learn4: "examples" + learn5: " page for more." + learn6: "If you wish to use p5 with a screenreader, check out the " + learn7: "p5 with a screenreader tutorial" + book1: "Parts of this tutorial were adapted from the book, Getting Started with p5.js, by Lauren McCarthy, Casey Reas, and Ben Fry, O'Reilly / Make 2015. Copyright " + book2: 2015 Lauren McCarthy, Casey Reas, and Ben Fry. All rights reserved. + +download: + Download: "Download" + complete-library-title: "Complete Library" + p5.js-complete: "p5.js complete" + includes-1: "Includes:" + includes-2: "p5.js, p5.dom.js, p5.sound.js, and an example project" + includes-3: "Version " + single-files-title: "Single Files" + single-file: "Single file: " + p5.js-uncompressed: "Full uncompressed version" + compressed: "Compressed version" + link: "Link: " + statically-hosted-file: "Statically hosted file" + editor-title: "Editor" + p5.js-editor: "p5.js Web Editor" + editor-includes: "Start coding using the p5.js Web Editor, no setup required!" + etc-title: "ETC" + older-releases: "Older releases / changelog " + report-bugs: "Report bugs " + supported-browsers: "Supported browsers " + support-title: "Support p5.js!" + support-1: "p5.js is free, open-source software. We want to make our community as open and inclusive as possible. You can support this work by " + support-2: "becoming a member" + support-3: " of the Processing Foundation as an individual, a studio, or an educational institution. You can also " + support-4: "make a donation" + support-5: " without purchasing a membership." + support-6: "Individual" + support-7: "$25" + support-8: "Studio" + support-9: "$250" + support-10: "Educational Institution" + support-11: "$5/student or $500" + support-12: "Your membership supports software development (for p5.js, Processing, Processing.py, Processing for Android and ARM devices, education resources like code examples and tutorials, " + support-13: "Fellowships" + support-14: ", and " + support-15: "community events" + support-16: ". We need your help!" + support-17: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)" + support-18: "Processing Fellow Saskia Freeke is organizing Code Liberation x Processing workshops in London (Image credit: Code Liberation Foundation)" + support-19: "Learning to Teach, Teaching to Learn conference with SFPC (Image credit: Kira Simon-Kennedy)" + support-20: "Processing Foundation Fellow Cassie Tarakajian’s workshop at Code Art Miami (Image credit: Christian Arévalo Photography)" + support-21: "Taeyoon Choi and ASL interpretor at Signing Coders p5.js workshop (Image credit: Taeyoon Choi)" + support-22: "Google Summer of Code kickoff (Image credit: Taeyoon Choi)" + support-23: "Processing Foundation Fellow Cassie Tarakajian’s workshop at Code Art Miami (Image credit: Christian Arévalo Photography)" + support-24: "Luisa Pereira and Yeseul Song helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)" + support-25: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)" + support-26: "Processing Fellow Digital Citizens Lab hosts a panel on STEM teaching at the International Center of Photography (Image credit: International Center of Photography)" + support-27: "Participants at p5.js workshop in Santiago, Chile, led by Aarón Montoya-Moraga (Image credit: Aarón Montoya-Moraga.)" + support-28: "Claire Kearney-Volpe helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)" + support-29: "Processing Foundation Fellow DIY Girls run a creative coding program in Los Angeles (Image credit: DIY Girls)" + support-30: "Processing Fellow Digital Citizens Lab" + support-31: "Bicoastal p5.js meetup at UCLA DMA and NYU ITP" + support-32: "The Processing Foundation" + support-33: " was founded in 2012 after more than a decade of work with the original Processing software. The Foundation’s mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources." + +learn: + learn-title: "Learn" + learn1: "These tutorials provide more in-depth or step-by-step overviews of particular topics. Check out the " + learn2: "examples page" + learn3: "to see short demonstrations of various p5.js topics." + introduction-to-p5js-title: "Introduction to p5.js" + hello-p5js-title: "Hello p5.js" + hello-p5js: "This short video will introduce you to the library and what you can do with it." + getting-started-title: "Getting Started" + getting-started: "Welcome to p5.js!
This introduction covers the basics of setting up a p5.js project." + p5js-overview-title: "p5.js overview" + p5js-overview: "An overview of the main features of p5.js." + p5js-processing-title: "p5.js and Processing" + p5js-processing: "The main differences between the two, and how to convert from one to the other." + p5-screen-reader-title: "p5 with a screen reader" + p5-screen-reader: "Setting up p5 so that it can be used easily with a screen reader." + using-local-server-title: "Using a local server" + using-local-server: "How to set up a local server on Mac OSX, Windows, or Linux." + connecting-p5js-title: "Connecting p5.js" + creating-libraries-title: "Creating libraries" + creating-libraries: "Creating p5.js addon libraries." + nodejs-and-socketio-title: "node.js and socket.io" + nodejs-and-socketio: "Using a node.js server with p5.js, communication via socket.io." + programming-topics-title: "Programming topics" + beyond-the-canvas-title: "Beyond the canvas" + beyond-the-canvas: "Creating and manipulating elements on the page beyond the canvas." + 3d-webgl-title: "3D/WebGL" + 3d-webgl: "Developing advanced graphics applications in p5.js using WEBGL mode." + color-title: "Color" + color: "An introduction to digital color." + coordinate-system-and-shapes-title: "Coordinate System and Shapes" + coordinate-system-and-shapes: "Drawing simple shapes and using the coordinate system." + interactivity-title: "Interactivity" + interactivity: "Introduction to interactivity with the mouse and keyboard." + program-flow-title: "Program Flow" + program-flow: "Introduction to controlling program flow in p5.js." + curves-title: "Curves" + curves: "An introduction to the three types of curves in p5.js: arcs, spline curves, and Bézier curves." + becoming-a-better-programmer-title: "Becoming a better programmer" + debugging-title: "Debugging" + debugging: "Field guide to debugging for everyone." + optimizing-title: "Optimizing p5.js code for performance" + optimizing: "A tutorial of tips and tricks for optimizing your code to make it run faster and smoother." + test-driven-development-title: "Unit testing and test driven development" + test-driven-development: "Save yourself from agony on install day. What is unit testing and how to use it? By Andy Timmons." + contributing-to-the-community-title: "Contributing to the community" + development-title: "Development" + development: "Getting started and overview for contributing to development." + looking-inside-title: "Looking inside p5" + looking-inside: "A friendly intro to the file structure and tools for p5.js development, by Luisa Pereira." + writing-tutorial-title: "Writing a tutorial" + writing-tutorial: "A guide to writing a p5.js programming tutorial." + writing-a-tutorial-title: "Guide to contributing p5.js tutorials" + writing-a-tutorial-author: "This tutorial was written by Tega Brain." + writing-a-tutorial-1: "We invite educators, contributors and general enthusiasts to contribute p5js tutorials. The p5js project makes creative coding and open source development more accessible to a diverse community and we are excited to publish tutorials on all aspects of the development process. Our learning materials so far include guides on learning p5, programming technique and how to contribute to an open source project." + writing-a-tutorial-2: "We welcome new written tutorial contributions and this guide outlines the steps of how to propose, prepare and contribute." + writing-a-tutorial-how-start-title: "How to get started:" + writing-a-tutorial-how-start-1: "Check that your proposed topic has not already been covered. There is " + writing-a-tutorial-how-start-2: "a working spreadsheet here" + writing-a-tutorial-how-start-3: "that outlines in progress tutorials. If your topic is listed as in progress, perhaps you can add to work being done and contribute to preparing existing work for publication so please reach out to us." + writing-a-tutorial-how-start-4: "If your topic is not already covered and is not listed as in progress, please write a few sentences on what you propose to cover and email us this description at education@p5js.org." + writing-a-tutorial-how-prepare-title: "How to prepare a p5js tutorial for publication online:" + writing-a-tutorial-how-prepare-1: "When your tutorial is ready for publication, please follow these steps to prepare your content for the p5js website." + writing-a-tutorial-how-prepare-2: "Prepare the content of your tutorial as a tutorial-name.hbs file with " + writing-a-tutorial-how-prepare-3: "this basic structure" + writing-a-tutorial-how-prepare-4: ". As is shown in this file, it must contain a header as shown below:" + writing-a-tutorial-how-prepare-5: "The folder containing your tutorial will be placed in the 'tutorials' folder of the p5js site. The file called index.hbs is the " + writing-a-tutorial-how-prepare-6: "p5.js tutorials landing page," + writing-a-tutorial-how-prepare-7: " and the test-tutorial.hbs file is the test tutorial." + writing-a-tutorial-how-prepare-8: "All content should go in the:" + writing-a-tutorial-how-prepare-9: "tags on the page, with formatting defined by the <h1> and <h2> tags, the <p> paragraph tags as is done shown on the" + writing-a-tutorial-how-prepare-10: "test tutorial page." + writing-a-tutorial-how-prepare-11: "If your tutorial contains images, they are to be placed in the assets folder of the p5 site, in the location src/assets/learn/test-tutorial/images as shown below." + writing-a-tutorial-how-prepare-12: "To correctly format code in the html of the page use the tag:" + writing-a-tutorial-embedding-title: "Embedding p5.js sketches" + writing-a-tutorial-embedding-1: "Using p5js means you can illustrate your tutorial with animated, interactive or editable code examples to demonstrate programming concepts. Your examples should be prepared as p5.js sketches and can be embedded into the tutorial in two ways." + writing-a-tutorial-embedding-2: "If the example is to be editable like in " + writing-a-tutorial-embedding-3: "the reference pages" + writing-a-tutorial-embedding-4: " of the p5js site, the p5 sketch should be embedded into the html page using the p5js widget. Follow " + writing-a-tutorial-embedding-5: "this guide " + writing-a-tutorial-embedding-6: "on how to embed p5js sketches using the widget written by " + writing-a-tutorial-embedding-7: ". You can also see this in action on the" + writing-a-tutorial-embedding-8: " test tutorial page" + writing-a-tutorial-embedding-9: "." + writing-a-tutorial-embedding-10: "If the example is to be animated and/or interactive but not editable. The p5.js sketch should be embedded into the page as an iframe as described below." + writing-a-tutorial-iframe-title: "Embed a p5 sketch using an iframe" + writing-a-tutorial-iframe-1: "An iframe is like creating a window through which you can see another page, sandboxed from the rest of your page. In this case it will be a window to the index.html containing your p5.js sketch. " + writing-a-tutorial-iframe-2: "Put your p5 sketches in the /src/assets/learn folder of the site, in a folder labelled with the name of your sketch as shown in the screenshot. This is where all the images and p5 sketches linked by iframe should be stored." + writing-a-tutorial-iframe-3: "In the subfolders containing your p5 examples there should be a sketch.js file and the embed.html file for the sketch. " + writing-a-tutorial-iframe-4: "Make sure your embed.html file has the correct paths to the p5 libraries of the site. If your file structure is the same as above, the path to the p5.js library should be \"../../../js/p5.min.js\"." + writing-a-tutorial-iframe-5: "You can then embed the p5js index files as iframes in the .hbs file that contains your tutorial content. The embed code for the iframe would then be: " + writing-a-tutorial-iframe-6: "Styling for the iframe (this could directly into the post or in a stylesheet): " + writing-a-tutorial-iframe-7: "Here you can see the naked sketch running: " + writing-a-tutorial-iframe-8: "And here it is embedded in the p5 site using the code below: " + writing-a-tutorial-iframe-9: "One thing to note is that you need to manually set the size of the iframe, so it works best if things are a standard size." + writing-a-tutorial-iframe-10: "Also note that the links to the p5.js library files do not happen from the .eps page with all the tutorial content. Instead they will be located in the html page that is rendering your sketch (in this case, called embed.html)." + writing-a-tutorial-iframe-11: "More information on embedding p5.js sketches can be found " + writing-a-tutorial-embed-iframe-12: "here." + writing-a-tutorial-finishing-title: "Finishing up" + writing-a-tutorial-finishing-1: "Once your have finished writing your tutorial and your content has been given the thumbs up. Fork the p5.js website repository, prepare your content as described above and then issue a pull request to the p5.js website repository so we can publish your contribution!" + writing-a-tutorial-finishing-2: "Thank you!" + color-description1: "This tutorial is from the book Learning Processing by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to P5 by Kelly Chang. If you see any errors or have comments, " + color-description2: " please let us know." + color-title: "Color" + color-p1x1: "In the digital world, when we want to talk about a color, precision is required. Saying \"Hey, can you make that circle bluish-green?\" will not do. Color, rather, is defined as a range of numbers. Let's start with the simplest case: black & white or grayscale. 0 means black, 255 means white. In between, every other number—50, 87, 162, 209, and so on—is a shade of gray ranging from black to white." + color-p2x1: "By adding the " + color-p2x2: " and " + color-p2x3: " functions before something is drawn, we can set the color of any given shape. There is also the function " + color-p2x4: ", which sets a background color for the window. Here's an example." + color-code1: "background(255); // Setting the background to white \n stroke(0); // Setting the outline (stroke) to black \n fill(150); // Setting the interior of a shape (fill) to grey \n rect(50,50,75,100); // Drawing the rectangle" + color-p3x1: "Stroke or fill can be eliminated with the functions: " + color-p3x2: " and " + color-p3x3: ". Our instinct might be to say \"stroke(0)\" for no outline, however, it is important to remember that 0 is not \"nothing\", but rather denotes the color black. Also, remember not to eliminate both—with " + color-p3x4: " and " + color-p3x5: ", nothing will appear!" + color-p4x1: "In addition, if we draw two shapes, p5.js will always use the most recently specified stroke and fill, reading the code from top to bottom." + color-rgb-title: "RGB Color" + color-rgb-p1x1: "Remember finger painting? By mixing three \"primary\" colors, any color could be generated. Swirling all colors together resulted in a muddy brown. The more paint you added, the darker it got. Digital colors are also constructed by mixing three primary colors, but it works differently from paint. First, the primaries are different: red, green, and blue (i.e., \"RGB\" color). And with color on the screen, you are mixing light, not paint, so the mixing rules are different as well." + color-rgb-li1: "Red + Green = Yellow" + color-rgb-li2: "Red + Blue = Purple" + color-rgb-li3: "Green + Blue = Cyan (blue-green)" + color-rgb-li4: "Red + Green + Blue = White" + color-rgb-li5: "No colors = Black" + color-rgb-p2x1: "This assumes that the colors are all as bright as possible, but of course, you have a range of color available, so some red plus some green plus some blue equals gray, and a bit of red plus a bit of blue equals dark purple. While this may take some getting used to, the more you program and experiment with RGB color, the more it will become instinctive, much like swirling colors with your fingers. And of course you can't say \"Mix some red with a bit of blue,\" you have to provide an exact amount. As with grayscale, the individual color elements are expressed as ranges from 0 (none of that color) to 255 (as much as possible), and they are listed in the order R, G, and B. You will get the hang of RGB color mixing through experimentation, but next we will cover some code using some common colors." + color-transparency-title: "Color Transparency" + color-transparency-p1x1: "In addition to the red, green, and blue components of each color, there is an additional optional fourth component, referred to as the color's \"alpha\". Alpha means transparency and is particularly useful when you want to draw elements that appear partially see-through on top of one another. The alpha values for an image are sometimes referred to collectively as the \"alpha channel\" of an image." + color-transparency-p2x1: "It is important to realize that pixels are not literally transparent, this is simply a convenient illusion that is accomplished by blending colors. Behind the scenes, p5.js takes the color numbers and adds a percentage of one to a percentage of another, creating the optical perception of blending. (If you are interested in programming \"rose-colored\" glasses, this is where you would begin.)" + color-transparency-p3x1: "Alpha values also range from 0 to 255, with 0 being completely transparent (i.e., 0% opaque) and 255 completely opaque (i.e., 100% opaque)." + color-custom-ranges-title: "Custom Color Ranges" + color-custom-ranges-p1x1: "RGB color with ranges of 0 to 255 is not the only way you can handle color in p5.js, in fact, it allows us to think about color any way we like. For example, you might prefer to think of color as ranging from 0 to 100 (like a percentage). You can do this by specifying a custom " + color-custom-ranges-p2x1: "The above function says: \"OK, we want to think about color in terms of red, green, and blue. The range of RGB values will be from 0 to 100.\"" + color-custom-ranges-p3x1: "Although it is rarely convenient to do so, you can also have different ranges for each color component:" + color-custom-ranges-p4x1: "Now we are saying \"Red values go from 0 to 100, green from 0 to 500, blue from 0 to 10, and alpha from 0 to 255.\"" + color-custom-ranges-p5x1: "Finally, while you will likely only need RGB color for all of your programming needs, you can also specify colors in the HSB (hue, saturation, and brightness) mode. Without getting into too much detail, HSB color works as follows:" + color-custom-ranges-li1x1: "Hue" + color-custom-ranges-li1x2: "—The color type, ranges from 0 to 255 by default." + color-custom-ranges-li2x1: "Saturation" + color-custom-ranges-li2x2: "—The vibrancy of the color, 0 to 255 by default." + color-custom-ranges-li3x1: "Brightness" + color-custom-ranges-li3x2: "—The, well, brightness of the color, 0 to 255 by default." + color-custom-ranges-p6x1: "With " + color-custom-ranges-p6x2: " you can set your own ranges for these values. Some prefer a range of 0-360 for hue (think of 360 degrees on a color wheel) and 0-100 for saturation and brightness (think of 0-100%)." + coordinate-system-description1: "This tutorial is from the book " + coordinate-system-description2: "Learning Processing" + coordinate-system-description3: " by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to p5.js by Alex Yixuan Xu. If you see any errors or have comments, please " + coordinate-system-description4: "let us know" + coordinate-system-description5: "." + coordinate-system-description-title: "Coordinate System and Shapes" + coordinate-system-description-p1x1: "Before we begin programming with p5, we must first channel our eighth grade selves, pull out a piece of graph paper, and draw a line. The shortest distance between two points is a good old fashioned line, and this is where we begin, with two points on that graph paper." + coordinate-system-description-p2x1: "The above figure shows a line between point A (1,0) and point B (4,5). If you wanted to direct a friend of yours to draw that same line, you would give them a shout and say \"draw a line from the point one-zero to the point four-five, please.\" Well, for the moment, imagine your friend was a computer and you wanted to instruct this digital pal to display that same line on its screen. The same command applies (only this time you can skip the pleasantries and you will be required to employ a precise formatting). Here, the instruction will look like this:" + coordinate-system-description-p3x1: "Even without having studied the syntax of writing code, the above statement should make a fair amount of sense. We are providing a command (which we will refer to as a \"function\") for the machine to follow entitled \"line.\" In addition, we are specifying some arguments for how that line should be drawn, from point A (1,0) to point B (4,5). If you think of that line of code as a sentence, the function is a verb and the arguments are the objects of the sentence. The code sentence also ends with a semicolon instead of a period." + coordinate-system-description-p4x1: "The key here is to realize that the computer screen is nothing more than a fancier piece of graph paper. Each pixel of the screen is a coordinate - two numbers, an \"x\" (horizontal) and a \"y\" (vertical) - that determines the location of a point in space. And it is our job to specify what shapes and colors should appear at these pixel coordinates." + coordinate-system-description-p5x1: "Nevertheless, there is a catch here. The graph paper from eighth grade (\"Cartesian coordinate system\") placed (0,0) in the center with the y-axis pointing up and the x-axis pointing to the right (in the positive direction, negative down and to the left). The coordinate system for pixels in a computer window, however, is reversed along the y-axis. (0,0) can be found at the top left with the positive direction to the right horizontally and down vertically." + coordinate-system-simple-shapes-title: "Simple Shapes" + coordinate-system-simple-shapes-p1x1: "The vast majority of the programming examples you'll see with p5 are visual in nature. These examples, at their core, involve drawing shapes and setting pixels. Let's begin by looking at four primitive shapes." + coordinate-system-simple-shapes-p2x1: "For each shape, we will ask ourselves what information is required to specify the location and size (and later color) of that shape and learn how p5 expects to receive that information. In each of the diagrams below, we'll assume a window with a width of 100 pixels and height of 100 pixels." + coordinate-system-simple-shapes-p3x1: "A " + coordinate-system-simple-shapes-p3x2: " is the easiest of the shapes and a good place to start. To draw a point, we only need an x and y coordinate." + coordinate-system-simple-shapes-p4x1: "A " + coordinate-system-simple-shapes-p4x2: " isn't terribly difficult either and simply requires two points: (x1,y1) and (x2,y2):" + coordinate-system-simple-shapes-p5x1: "Once we arrive at drawing a " + coordinate-system-simple-shapes-p5x2: ", things become a bit more complicated. In p5, a rectangle is specified by the coordinate for the top left corner of the rectangle, as well as its width and height." + coordinate-system-simple-shapes-p6x1: "A second way to draw a rectangle involves specifying the centerpoint, along with width and height. If we prefer this method, we first indicate that we want to use the " + coordinate-system-simple-shapes-p6x2: " mode before the instruction for the rectangle itself. Note that p5 is case-sensitive." + coordinate-system-simple-shapes-p7x1: "Finally, we can also draw a rectangle with two points (the top left corner and the bottom right corner). The mode here is " + coordinate-system-simple-shapes-p7x2: ". Note this example gives the same result on screen as the example above." + coordinate-system-simple-shapes-p8x1: "Once we have become comfortable with the concept of drawing a rectangle, an " + coordinate-system-simple-shapes-p8x2: " is a snap. In fact, it is identical to " + coordinate-system-simple-shapes-p8x3: " with the difference being that an ellipse is drawn where the bounding box of the rectangle would be. The default mode for " + coordinate-system-simple-shapes-p8x4: " is " + coordinate-system-simple-shapes-p8x5: ", rather than " + coordinate-system-simple-shapes-p8x6: "." + coordinate-system-simple-shapes-p9x1: "Now let's look at what some code with shapes in more complete form, with canvas dimensions of 200 by 200. Note the use of the createCanvas() function to specify the width and height of the canvas." + +test-tutorial: + +libraries: + Libraries: "Libraries" + p5.dom: "p5.dom lets you interact with HTML5 objects beyond the canvas, including video, audio, webcam, input, and text." + p5.sound: "p5.sound extends p5 with Web Audio functionality including audio input, playback, analysis and synthesis." + p5.accessibility: "p5.accessibility makes the p5 canvas more accessible to people who are blind and visually impaired." + Contributed: "Contributed" + p5.serial1: "p5.serial enables serial communication between devices that support serial (RS-232) and p5 sketches running in the browser. Created by " + p5.serial2: ", with contributions from " + p5.serial3: " and " + p5.collide2D: "p5.collide2D provides tools for calculating collision detection for 2D geometry with p5.js. Created by " + rita.js: "RiTa.js provides a set of natural language processing objects for generative literature. Created by " + p5.geolocation: "p5.geolocation provides techniques for acquiring, watching, calculating, and geofencing user locations for p5.js. Created by " + p5.speech: "p5.speech provides simple, clear access to the Web Speech and Speech Recognition APIs, allowing for the easy creation of sketches that can talk and listen. Created by " + p5.bots: "With p5.bots you can interact with your Arduino (or other microprocessor) from within the browser. Use sensor data to drive a sketch; use a sketch to drive LEDs, motors, and more! Created by " + grafica.js: "grafica.js lets you add simple but highly configurable 2D plots to your p5.js sketches. Created by " + p5.play: "p5.play provides sprites, animations, input and collision functions for games and gamelike applications. Created by " + p5.gui: "p5.gui generates a graphical user interface for your p5.js sketches. Created by " + p5.gibber: "p5.gibber provides rapid music sequencing and audio synthesis capabilities. Created by " + p5.particle: "The Particle and Fountain objects can be used to create data-driven effects that are defined through user structures or JSON input and user-draw functions. Created by " + p5.scribble: "Draw 2D primitives in a sketchy look. Created by Janneck Wullschleger, based on a port of the original Processing library " + p5.tiledmap1: "p5.tiledmap provides drawing and helper functions to include maps made with" + p5.tiledmap2: "in your sketches. Created by " + p5.dimensions1: "p5.dimensions extends p5.js' vector functions to work in any number of dimensions. Created by " + p5.dimensions2: " and " + p5.scenemanager: "p5.SceneManager helps you create sketches with multiple states / scenes. Each scene is a like a sketch within the main sketch. Created by " + mappa: "Mappa provides a set of tools for working with static maps, tile maps, and geo-data. Useful when building geolocation-based visual representations. Created by " + p5.func: "p5.func is a p5 extension that provides new objects and utilities for function generation in the time, frequency, and spatial domains. Created by " + p5.voronoi: "p5.voronoi provides a set of tools to draw and utilize voronoi diagrams in your p5.js sketches. Created by " + using-a-library-title: "Using a library" + using-a-library1: "A p5.js library can be any JavaScript code that extends or adds to the p5.js core functionality. There are two categories of libraries. Core libraries (" + using-a-library2: " and " + using-a-library3: ") are part of the p5.js distribution, while contributed libraries are developed, owned, and maintained by members of the p5.js community." + using-a-library4: "To include a library in your sketch, link it into your HTML file, after you have linked in p5.js. An example HTML file might look like this:" + create-your-own-title: "Create Your Own" + create-your-own1: "p5.js welcomes libraries contributed by others! Check out the" + create-your-own2: "libraries tutorial" + create-your-own3: "for more specifics about how to create one." + create-your-own4: "If you have created a library and would like to have it included on this page, submit this form!" + +community: + community-title: "Community" + community-statement-title: "p5.js Community Statement" + community-statement1: "p5.js is a community interested in exploring the creation of art and design with technology." + community-statement2: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners." + community-statement3: "We like these hashtags: #noCodeSnobs (because we value community over efficiency), #newKidLove (because we all started somewhere), #unassumeCore (because we don't assume knowledge), and #BlackLivesMatter (because of course)." + in-practice-title: "In practice:" + in-practice1: " We are not code snobs. We do not assume knowledge or imply there are things that somebody should know. " + in-practice2: "We insist on actively engaging with requests for feedback regardless of their complexity." + in-practice3: "We welcome newcomers and prioritize the education of others. We strive to approach all tasks with the enthusiasm of a newcomer. Because we believe that newcomers are just as valuable in this effort as experts." + in-practice4: "We consistently make the effort to actively recognize and validate multiple types of contributions." + in-practice5: "We are always willing to offer help or guidance." + in-times-conflict-title: "In times of conflict:" + in-times-conflict1: "We listen." + in-times-conflict2: "We clearly communicate while acknowledging other's feelings." + in-times-conflict3: "We admit when we're wrong, apologize, and accept responsibility for our actions." + in-times-conflict4: "We are continuously seeking to improve ourselves and our community." + in-times-conflict5: "We keep our community respectful and open." + in-times-conflict6: "We make everyone feel heard." + in-times-conflict7: "We are mindful and kind in our interactions." + in-the-future-title: "In the future:" + in-the-future1: "The future is now." + contribute-title: "Contribute" + contribute1: "Our community is always looking for enthusiasts to help in all different ways." + develop-title: "Develop." + develop1: "GitHub" + develop2: " is the main place where code is collected, issues are documented, and discussions about code are had. Check out the " + develop3: " development tutorial" + develop4: " to get started, or " + develop5: "create your own library." + document-title: "Document." + document1: " Everyone loves documentation. Help is needed " + document2: "porting examples" + document3: ", and" + document4: " adding documentation" + document5: ", and creating tutorials." + teach-title: "Teach." + teach1: " Teach a workshop, a class, a friend, a collaborator! Tag @p5xjs on Twitter and we will do our best to share what you're doing." + create-title: "Create." + create1: " p5.js is looking for designers, artists, coders, programmers to bring your creative and amazing work to show on the front page and inspire other people. Submit your work to " + create2: "hello@p5js.org" + create3: "." + donate-title: "Donate." + donate1: " p5.js is free and open source and made by artists. Help support the development of p5.js through a donation to the " + donate2: "Processing Foundation" + donate3: "." + contributors-conference-title: "Contributors Conference" + contributors-conference1: "In 2015, p5.js held its first-ever " + contributors-conference2: "contributors conference" + contributors-conference3: ". Artists, designers, developers, educators, and more joined forces at " + contributors-conference4: "CMU's Studio for Creative Inquiry" + contributors-conference5: " to make p5.js awesome." + mailing-list-title: "Mailing list" + mailing-list-1: "Enter your email address to receive occasional updates from the Processing Foundation." + people-title: "People" + people1: "blah" + +books: + books-title: "Books" + +examples: + Examples: "Examples" + back-examples: "Back to Examples" + Structure: "Structure" + Form: "Form" + Data: "Data" + Arrays: "Arrays" + Control: "Control" + Image: "Image" + Color: "Color" + Math: "Math" + Simulate: "Simulate" + Interaction: "Interaction" + Objects: "Objects" + Lights: "Lights" + Motion: "Motion" + Instance_Mode: "Instance Mode" + Dom: "DOM" + Drawing: "Drawing" + Transform: "Transform" + Typography: "Typography" + 3D: "3D" + Input: "Input" + Advanced_Data: "Advanced Data" + Sound: "Sound" + Mobile: "Mobile" + Hello_P5: "Hello p5" + +contributors-conference: + contributors-conference-title: "p5.js Contributors Conference" + contributors-conference-date: "May 25-31" + contributors-conference1: "A diverse group of approximately 30 participants gathered spent a week at the " + contributors-conference2: ", advancing the code, documentation, and community outreach tools of the p5.js programming environment. Participants came from as far away as Hong Kong, Seattle, Los Angeles,Boston and New York. Most were working professionals in the fields of creative technology, interaction design, and new-media arts, but the group also included a half-dozen undergraduate and graduate students from Carnegie Mellon’s Schools of Art and Architecture." + contributors-conference-participants-title: "Participants" + contributors-conference-diversity-title: "Diversity" + contributors-conference-diversity1: "Alongside technical development, one of the main focuses of this conference was outreach, community, and diversity. The conference began with a panel" + contributors-conference-diversity2: "Diversity: Seven Voices on Race, Gender, Ability & Class for FLOSS and the Internet" + contributors-conference-diversity3: ". " + contributors-conference-diversity4: "Organized by" + contributors-conference-diversity5: "and" + contributors-conference-diversity6: ", " + contributors-conference-diversity7: "the panel took place Tuesday, 25 May 2015 in Kresge Auditorium at Carnegie Mellon University. Speakers included" + contributors-conference-diversity8: "and" + contributors-conference-diversity9: "." + contributors-conference-support-title: "Support" + contributors-conference-support1: "Our contributor conference took place at the" + contributors-conference-support2: "at Carnegie Mellon University, an academic laboratory for atypical, anti-disciplinary, and inter-institutional research at the intersections of arts, science, technology, and culture." + contributors-conference-support3: "This event was made possible by a grant from the" + contributors-conference-support4: "and generous support from the" + contributors-conference-support5: "and" + contributors-conference-support6: "Thank you!" + +reference: + Reference: "Reference" \ No newline at end of file diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json new file mode 100644 index 0000000000..cdd17d07e3 --- /dev/null +++ b/src/data/reference/ko.json @@ -0,0 +1,1726 @@ +{ + "Home": "Inicio", + "Download": "Descargar", + "Start": "Empezar", + "Reference": "Referencia", + "reference-tagline": "la intuición de Processing x el poder de JavaScript", + "reference-search": "Busca en la API", + "reference-menu-home": "Inicio", + "reference-menu-download": "Descargar", + "reference-menu-get-started": "Empezar", + "reference-menu-reference": "Referencia", + "reference-menu-libraries": "Bibliotecas", + "reference-menu-learn": "Aprender", + "reference-menu-examples": "Ejemplos", + "reference-menu-books": "Libros", + "reference-menu-community": "Comunidad", + "reference-menu-forum": "Foro", + "reference-description1": "¿No encuentras lo que buscas? Quizás debas revisar en", + "reference-description2": "o", + "reference-description3": "Puedes descargar una versión de la referencia", + "reference-description4": "aquí", + "reference-contribute1": "Si ves algún error o tienes alguna sugerencia", + "reference-contribute2": "por favor dinos", + "reference-error1": "¿Encontraste algún error?", + "reference-error2": "está documentado y definido en", + "reference-error3": "Por favor siéntete libre de ", + "reference-error4": "editar el archivo", + "reference-error5": "y de indicar un pull request.", + "reference-example": "Ejemplo", + "reference-description": "Descripción", + "reference-extends": "Extiende", + "reference-parameters": "Parámetros", + "reference-syntax": "Sintaxis", + "reference-returns": "Retorna", + "footer1": "p5.js fue creado por ", + "footer2": " y es desarrollado por una comunidad de colaboradores, con apoyo de ", + "footer3": " y ", + "footer4": "Identidad y diseño gráfico por ", + "Libraries": "Bibliotecas", + "Learn": "Aprender", + "Examples": "Ejemplos", + "Books": "Libros", + "Community": "Comunidad", + "Contribute": "Contribuir", + "Forum": "Foro", + "h1": "Referencia", + "Color": "Color", + "Shape": "Forma", + "Creating & Reading": "Creación y lectura", + "Setting": "Configuración", + "2D Primitives": "Primitivas 2D", + "Attributes": "Atributos", + "Curves": "Curvas", + "Vertex": "Vértices", + "3D Models": "Modelos 3D", + "3D Primitives": "Primitivas 3D", + "Constants": "Constantes", + "Structure": "Estructura", + "Environment": "Ambiente", + "DOM": "DOM", + "Rendering": "Render", + "Transform": "Transformar", + "Data": "Datos", + "Dictionary": "Diccionario", + "Array Functions": "Funciones de arreglo", + "Conversion": "Conversión", + "String Functions": "Funciones de String", + "Events": "Eventos", + "Acceleration": "Aceleración", + "Keyboard": "Teclado", + "Mouse": "Ratón", + "Touch": "Tacto", + "Image": "Imagen", + "Loading & Displaying": "Cargar & Mostrar", + "Pixels": "Pixeles", + "IO": "Entrada y salida", + "Input": "Entrada", + "Output": "Salida", + "Table": "Tabla", + "Time & Date": "Tiempo & Fecha", + "XML": "XML", + "Math": "Matemáticas", + "Calculation": "Cálculo", + "Noise": "Ruido", + "Trigonometry": "Trigonometría", + "Typography": "Tipografía", + "Font": "Fuente", + "Lights, Camera": "Luces, cámara", + "Camera": "Cámara", + "Lights": "Luces", + "Material": "Materiales", + "footer1": "p5.js fue creado por ", + "footer2": " y es desarrollado por una comunidad de colaboradores, con apoyo de ", + "footer3": " y ", + "footer4": "Identidad y diseño gráfico por ", + "p5": { + "alpha": { + "description": "Extrae el valor de alpha de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "el objeto p5" + }, + "blue": { + "description": "Extrae el valor de azul de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "el objeto p5" + }, + "brightness": { + "description": "Extrae el valor de brillo HSB de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "el objeto p5" + }, + "color": { + "description": "Crea colores para ser almacenados en variables del tipo color. Los parámetros son interpretados como valores RGB o HSB, dependiendo del modo actual de color según colorMode)(). El modo por defecto es RGB con valores entre 0 y 255 y, por lo tanto, la función color(255, 204, 0) retorna un color amarillo brillante. Nota que si solo se provee un valor a la función color(), será interpretado como un valor en escala de grises. Añade un segundo valor, y será usado como transparencia alpha. Cuando se especifican tres valores, son interpretados como valores RGB o HSB. Al añadir un cuarto valor se aplica transparencia alpha. Si se provee solo un parámetro de tipo string, será interpretado como un string de color compatible con CSS.Los colores son almacenados como números o arreglos.", + "params": ["Número|String: número especificando el valor entre blanco y negro.", + "Número: valor de alpha relativo al rango de color actual (por defecto es 0-100)", + "Número|String: valor de rojo o tinte relativo al rango de color actual, o un string de color", + "Número: valor de verde o saturación relativo al rango de color actual", + "Número: valor de azul o brillo relativo al rango de color actual"], + "returns": "Arreglo: color resultante" + }, + "green": { + "description": "Extrae el valor de verde de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "the p5 object" + }, + "hue": { + "description": "Extrae el valor de tinte de un color o de un arreglo de pixeles. El tinte (hue) existe en HSB y HSL. Esta función retorna el tinte normalizado HSB que cuando se le provee un objeto de color HSB (o cuando se le provee un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará el tinte normalizado según HSB en otro caso. (Estos valores solo son diferentes si la configuración de valor de tinte máximo de cada sistema es diferente.)", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "the p5 object" + }, + "lerpColor": { + "description": "Mezcla dos colores para encontrar un tercer color según la combinación de ambos. El parámetro amt es la cantidad a interpolar entre los dos valores, donde 0.0 es igual al primer color, 0.1 es muy cercano al primer color, 0.5 está a medio camino entre ambos, etc. Un valor menor que 0 será tratado como 0. Del mismo modo, valores sobre 1 serán tratados como 1. Esto es distinto al comportamiento de lerp(), pero necesario porque de otra manera los números fuera de rango producirían colores no esperados y extraños. La manera en que los colores son interpolados depende del modo de color actual.", + "params": ["Arreglo/Número: interpola desde este color", + "Arreglo/Número: interpola hacia este color", + "Número: número entre 0 y 1"], + "returns": "Arreglo/Número: color interpolado" + }, + "lightness": { + "description": "Extrae el valor de luminosidad HSL de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "the p5 object" + }, + "red": { + "description": "Extrae el valor de rojo de un color o de un arreglo de pixeles.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "the p5 object" + }, + "saturation": { + "description": "Extrae el valor de saturación de un color o de un arreglo de pixeles. La saturación es escalada en HSB y HSL de forma distinta. Esta función retornará la saturación HSB cuando le sea provisto un objeto de color HSB (o cuando le sea provisto un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará saturación HSL.", + "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], + "returns": "the p5 object" + }, + "background": { + "description": "La función background() define el color usado como fondo del lienzo p5.js. El fondo por defecto es gris claro. Esta función es típicamente usada dentro de draw() para despejar o borrar la ventana mostrada al inicio de cada cuadro, pero puede ser usada dentro de setup() para definir el fondo en el primer cuadro de la animación o si el fondo solo necesita ser definido una vez.", + "params": ["Color: cualquier valor creado con la función color()", + "Número: opacidad del fondo relativo al rango de color actual (por defecto es 0-100)", + "colorstring: string de color, formatos posibles: enteros rgb() o rgba(), porcentajes rgb() o rgba(), hex 3 dígitos, hex 6 dígitos", + "Número: especifica un valor entre blanco y negro", + "Número: valor de rojo o hue (dependiendo del modo de color actual)", + "Número: valor de verde o saturación (dependiendo del modo de color actual)", + "Número: valor de azul o brillo (dependiendo del modo de color actual)", + "p5.Image: imagen creada con loadImage() o createImage(), para ser definida como fondo (debe ser del mismo tamaño que la ventana del bosquejo)"], + "returns": "the p5 object" + }, + "clear": { + "description": "Borra los pixeles del buffer. Esta función solo funciona en objetos p5.Canvas creados con la función createCanvas(); no funcionará con la ventana principal. A diferencia del contexto principal de gráficas, los pixeles en las áreas gráficas adicionales creadas con createGraphics() pueden ser entera o parcialmente transparentes. Esta función borra todo para hacer los pixeles 100% transparentes.", + "returns": "the p5 object" + }, + "colorMode": { + "description": "colorMode() cambia la manera en que p5.js interpreta los datos de color. Por defecto, los parámetros de fill(), stroke(), background() y color() son definidos por valores entre 0 y 255 en modo RGB. Esto es equivalente a definir el modo de color según colorMode(RGB, 255). Definir el modo de color en colorMode(HSB) permite usar el sistema HSB. Por defecto, este modo de color es colorMode(HSB, 360, 100, 100, 1). También se puede usar HSL. Nota: los objetos de color existentes recuerdan el modo en que fueron creados, por lo que puedes cambiar el modo como quieras, sin afectar su apariencia.", + "params": ["Constante: RGB o HSB, correspondiente a Rojo/Verde/Azul o tinte/saturación/brillo (o luminosidad)", + "Número: rango de rojo o tinte, dependiendo del modo de color actual, o rango para todos los valores", + "Número: rango de verde o saturación, dependiendo del modo de color actual.", + "Número: rango de azul o brillo/luminosidad, dependiendo del modo de color actual.", + "Número: rango de transparencia alpha"], + "returns": "the p5 object" + }, + "fill": { + "description": "Define el color usado para el relleno de figuras geométricas. Por ejemplo, si ejecutas fill(204, 102, 0), todas las figuras a continuación tendrán relleno naranja. Este color es especificado en términos de color RGB o HSB, dependiendo del modo de color según colorMode() (el dominio de color por defecto es RGB, con cada valor en el rango entre 0 y 255). Si se provee un argumento tipo string, los tipos RGB, RGBA y CSS hexadecimal están soportados. Un objeto Color p5 puede ser provisto para definir el color del relleno.", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo, tinte (dependiendo del modo de color actual), o arreglo de color, o string de color CSS.", + "Número: valor de verde o saturación (dependiendo del modo de color actual)", + "Número: valor de azul o brillo (dependiendo del modo de color actual)", + "Número: opacidad del fondo"], + "returns": "the p5 object" + }, + "noFill": { + "description": "Deshabilita el relleno de figuras geométricas. Si tanto noStroke() como noFill() son ejecutados, nada será dibujado en pantalla.", + "returns": "the p5 object" + }, + "noStroke": { + "description": "Deshabilita el dibujo de los trazos (bordes). Si tanto noStroke() como noFill() son ejecutados, nada será dibujado en pantalla.", + "returns": "the p5 object" + }, + "stroke": { + "description": "Define el color usado para dibujar líneas y bordes de figuras. Este color especificado en términos de color RGB o HSB, dependiendo del modo de color actual según colorMode() (el dominio de color por defecto es RGB, con cada valor en el rango entre 0 y 255). Si se provee un argumento tipo string, los tipos RGB, RGBA y CSS hexadecimal están soportados. Un objeto Color p5 puede ser provisto para definir el color del trazado.", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo, tinte (dependiendo del modo de color actual), o arreglo de color, o string de color CSS.", + "Número: valor de verde o saturación (dependiendo del modo de color actual)", + "Número: valor de azul o brillo (dependiendo del modo de color actual)", + "Número: opacidad del fondo"], + "returns": "el objeto p5" + }, + "arc": { + "description": "Dibuja un arco en la pantalla. Si se llama con solo a, b, c, d, start y stop, el arco se dibuja como un pastel abierto. Si el modo se provee, el arco será dibujado abierto, o como acorde, o como pastel, según lo especificado. El origen puede ser cambiado con la función ellipseMode(). Nota que si dibujas un círculo completo (ej: 0 a TWO_PI) aparecerá en blanco, porque 0 y TWO_PI son la misma posición en el círculo unitario. La mejor manera de manejar esto es usar la función ellipse() para una elipse cerrada, y la función arc() para generar solo secciones de una elipse.", + "params": ["Número: coordenada x del arco de elipse.", + "Número: coordenada y del arco de elipse.", + "Número: ancho del arco de elipse.", + "Número: altura del arco de elipse.", + "Número: ángulo inicial del arco de elipse.", + "Número: ángulo final del arco de elipse.", + "Constante: parámetro opcional para determinar la manera de dibujar el arco."], + "returns": "the p5 object" + }, + "ellipse": { + "description": "Dibuja una elipse (óvalo) en la pantalla. Una elipse con igual ancho y altura es un círculo. Por defecto, los primeros dos parámetros definen la ubicación, y el tercero y cuarto definen el ancho y altura de la figura. Si no especifica una altura, el valor del ancho es usado como ancho y altura. El origen puede ser cambiado con la función ellipseMode().", + "params": ["Número: coordenada x de la elipse.", + "Número: coordenada y de la elipse.", + "Número: ancho de la elipse.", + "Número: altura de la elipse."], + "returns": "the p5 object" + }, + "line": { + "description": "Dibuja una línea (un camino directo entre dos puntos) en la pantalla. La versión de line() con cuatro parámetros dibuja la línea en 2D. Para darle color a una línea, usa la función stroke(). Una línea no puede ser rellenada, por lo que la función fill() no afectará el color de una línea. Las líneas 2D son dibujadas con una ancho de un pixel por defecto, pero esto puede ser cambiado con la función strokeWeight().", + "params": ["Número: coordenada x del primer punto.", + "Número: coordenada y del primer punto.", + "Número: coordenada x del segundo punto.", + "Número: coordenada y del segundo punto."], + "returns": "the p5 object" + }, + "point": { + "description": "Dibuja un punto, una coordenada en el espacio de un pixel de dimensión. El primer parámetro es la coordenada horizontal del punto, el segundo valor es la coordenada vertical del punto. El color del punto es determinado por el trazado actual con la función stroke().", + "params": ["Número: coordenada x.", + "Número: coordenada y ."], + "returns": "the p5 object" + }, + "quad": { + "description": "Dibuja un cuadrilátero, un polígono de cuatro lados. Es similar a un rectángulo, pero los ángulos entre sus bordes no están limitados a noventa grados. El primer par de parámetros (x1, y1) corresponde a las coordenadas del primer vértice y los pares siguientes deben seguir en el mismo orden, según las manecillas del reloj o en contra, alrededor de la figura a definir.", + "params": ["Número: coordenada x del primer punto.", + "Número: coordenada y del primer punto.", + "Número: coordenada x del segundo punto.", + "Número: coordenada y del segundo punto.", + "Número: coordenada x del tercer punto.", + "Número: coordenada y del tercer punto.", + "Número: coordenada x del cuarto punto.", + "Número: coordenada y del cuarto punto."], + "returns": "the p5 object" + }, + "rect": { + "description": "Dibuja un rectángulo en la pantalla. Un rectángulo es una figura de cuatro lados con cada ángulo interior de noventa grados. Por defecto, los dos primeros parámetros definen la ubicación de la esquina superior izquierda, el tercero el ancho y el cuarto la altura. La manera en que estos parámetros son interpretados, sin embargo, puede ser cambiado con la función rectMode(). Los parámetros quinto, sexto, séptimo y octavo, si son especificados, determinan el radio de la esquina superior derecha, superior izquierda, inferior derecha e inferior izquierda, respectivamente. Si se omite un parámetro de radio de esquina, se usa el radio especificado por el valor anterior en la lista.", + "params": ["Número: coordenada x del rectángulo.", + "Número: coordenada y del rectángulo.", + "Número: ancho del rectángulo.", + "Número: altura del rectángulo.", + "Número: radio opcional de la esquina superior izquierda.", + "Número: radio opcional de la esquina superior derecha.", + "Número: radio opcional de la esquina inferior derecha.", + "Número: radio opcional de la esquina inferior izquierda.", + "Número:", + "Número:"], + "returns": "el objeto p5" + }, + "triangle": { + "description": "Un triángulo es un plano creado por la conexión de tres puntos. Los primeros dos argumentos especifican el primer punto, los parámetros centrales especifican el segundo punto, y los dos últimos parámetros especifican el tercer punto.", + "params": ["Número: coordenada x del primer punto.", + "Número: coordenada y del primer punto.", + "Número: coordenada x del segundo punto.", + "Número: coordenada y del segundo punto.", + "Número: coordenada x del tercer punto.", + "Número: coordenada y del tercer punto."], + "returns": "the p5 object" + }, + "ellipseMode": { + "description": "Modifica la ubicación de donde las elipses son dibujadas, cambiando la manera en que los parámetros dados a ellipse() son interpretados. El modo por defecto es ellipseMode(CENTER), que interpreta los dos primeros parámetros de ellipse() como el centro de la figura, mientras que los parámetros tercero y cuarto son el ancho y la altura. ellipseMode(RADIUS) también usa los dos primeros parámetros de ellipse() como el punto central de la figura, pero usa los parámetros tercero y cuarto para especificar la mitad del ancho y la altura de la figura. ellipseMode(CORNER) interpreta los dos primeros parámetros de ellipse() como la esquina superior izquierda de la figura, mientras que los parámetros tercero y cuarto son el ancho y la altura. ellipseMode(CORNERS) interpreta los dos primeros parámetros de ellipse() como la ubicación de una esquina del rectángulo contenedor de la elipse, y los parámetros tercero y cuarto como la ubicación de la esquina opuesta. El parámetro debe ser escrito en MAYÚSCULAS porque Javascript es una lenguaje de programación que distingue entre mayúsculas y minúsculas.", + "params": ["Constante: puede ser CENTER, RADIUS, CORNER, o CORNERS."], + "returns": "the p5 object" + }, + "noSmooth": { + "description": "Dibuja las figuras geométricas con bordes no suaves (aliasing). Notar que smooth() está activo por defecto, así que es necesario ejectuar noSmooth() para deshabilitar el suavizado de las figuras geométricas, imágenes y tipografías.", + "returns": "el objeto p5" + }, + "rectMode": { + "description": "Modifica la ubicación en que los rectángulos son dibujados, cambiando la manera en que los parámetros dados a rect() son interpretados. El modo por defecto es rectMode(CORNER), que interpreta los primeros dos parámetros de rect() como la esquina superior izquierda de la figura, mientras que los parámetros tercero y cuarto son su ancho y altura. rectMode(CORNERS) interpreta los dos primeros parámetros de rect() como la ubicación de una esquina, y los parámetros tercero y cuarto como la ubicación de la esquina opuesta. rectMode(CENTER) interpreta los dos primeros parámetros de rect() como el punto central de la figura, mientas que los parámetros tercero y cuarto son su ancho y altura. rectMode(RADIUS) también usa los dos primeros parámetros de rect()= como el punto central de la figura, pero usa los parámetros tercero y cuarto para especificar la mitad del ancho y la altura de la figura. Los parámetros deben ser escritos en MAYÚSCULAS porque Javascript es un lenguaje que distingue entre mayúsculas y minúsculas.", + "params": ["Constante: puede ser CORNER, CORNERS, CENTER, o RADIUS."], + "returns": "the p5 object" + }, + "smooth": { + "description": "Dibuja todas las figuras geométricas con bordes suaves (sin aliasing). smooth() también mejorará la calidad de las imágenes cuyo tamaño ha sido modificado. Notar que smooth() está activo por defecto; noSmooth() puede ser usado para deshabilitar el suavizado de las figuras geométricas, imágenes y tipografía.", + "returns": "the p5 object" + }, + "strokeCap": { + "description": "Define el estilo de rendering de los extremos de las líneas. Estos extremos pueden ser cuadrados, extendidos o redondeados, cada uno de estos especifados con los parámetros correspondientes: SQUARE, PROJECT, y ROUND. El extremo por defecto es redonedeado (ROUND).", + "params": ["Constante: puede ser SQUARE, PROJECT, o ROUND."], + "returns": "the p5 object" + }, + "strokeJoin": { + "description": "Define el estilo de las uniones que conectan segmentos de líneas. Estas uniones pueden ser tipo inglete, biseladas o redondeadas, y especificadas con los parámetros correspondientes: MITER, BEVEL, y ROUND. La unión por defecto es MITER.", + "params": ["Constante: puede ser MITER, BEVEL, o ROUND."], + "returns": "the p5 object" + }, + "strokeWeight": { + "description": "Define el ancho del trazo usado para dibujar líneas, puntos y los bordes de las figuras geométricas. Todos los anchos son medidos en pixeles.", + "params": ["Número: el peso (en pixeles) del trazado"], + "returns": "the p5 object" + }, + "bezier": { + "description": "Dibuja una curva Bezier cúbica en la pantalla. Estas curvas están definidas por una serie de puntos ancla y de control. Los primeros dos parámetros especifican el primer punto ancla y los dos últimos especifican el otro punto ancla, que se convierten en los puntos primero y último de la curva. Los parámetros en el medio especifican los dos puntos de control que definen la forma de la curva. De forma aproximada, los puntos de control atraen la curva hacia ellos. Las curvas Bezier fueron desarrolladas por el ingeniero automotriz Pierre Bezier, y son comúnmente usadas en gráficas computacionales para definir curvas de pendiente suave. Ver también curve().", + "params": ["Número: coordenada x del primer punto ancla", + "Número: coordenada y del primer punto ancla", + "Número: coordenada x del primer punto de control", + "Número: coordenada y del primer punto de control", + "Número: coordenada x del segundo punto de control", + "Número: coordenada y del segundo punto de control", + "Número: coordenada x del segundo punto ancla", + "Número: coordenada y del segundo punto ancla", + "Número: coordenada z del primer punto ancla", + "Número: coordenada z del primer punto de control", + "Número: coordenada z del segundo punto ancla", + "Número: coordenada z del segundo punto de control"], + "returns": "the p5 object" + }, + "bezierPoint": { + "description": "Evalua la curva Bezier en la posición t para los puntos a, b, c, d. Los parámetros a y d son los puntos primero y último de la curva, mientras que b y c son los puntos de control. El parámetro final t varía entre 0 y 1. Esto puede ser realizado una vez con las coordenadas x y una segunda vez con las coordenadas y para obtener la ubicación de la curva Bezier en t.", + "params": ["Número: coordenada del primer punto de la curva", + "Número: coordenada del primer punto de control de la curva", + "Número: coordenada del segundo punto de control de la curva", + "Número: coordenada del segundo punto de la curva", + "Número: valor entre 0 y 1"], + "returns": "el valor de la curva Bezier en la posición t" + }, + "bezierTangent": { + "description": "Evalua la tangente de la curva Bezier en la posición t para los puntos a, b, c, d. Los parámetros a y d son los puntos primero y último de la curva, mientras que b y c son los puntos de control. El parámetro final t varía entre 0 1.", + "params": ["Número: coordenada del primer punto de la curva", + "Número: coordenada del primer punto de control de la curva", + "Número: coordenada del segundo punto de control de la curva", + "Número: coordenada del segundo punto de la curva", + "Número: valor entre 0 y 1"], + "returns": "la tangente en la posición t" + }, + "curve": { + "description": "Dibuja una línea curva en la pantalla entre dos puntos, dados como los cuatro parámetros centrales. Los dos primeros puntos son un punto de control, como si la curva viniera desde este punto, aunque no sea dibujado. Los dos últimos parámetros de forma similar describen el otro punto de control. SE pueden cerar curvas más largas, por medio del posicionamiento de varias funciones curve() juntas o usando curveVertex(). Una función adicional llamada curveTightness() provee control de la calidad visual de la curva. La función curve() es una implementación de la Catmull-Rom spline.", + "params": ["Número: coordenada x del punto de control inicial", + "Número: coordenada y del punto de control inicial", + "Número: coordenada x del primer punto", + "Número: coordenada y del primer punto", + "Número: coordenada x del segundo punto", + "Número: coordenada y del segundo punto", + "Número: coordenada x del punto de control final", + "Número: coordenada y del punto de control final", + "Número: coordenada z del punto de control inicial", + "Número: coordenada z del primer punto", + "Número: coordenada z del segundo punto", + "Número: coordenada z del punto de control final"], + "returns": "Objeto: el objeto p5" + }, + "curveTightness": { + "description": "Modifica la calidad de las formas creadas con curve() y curveVertex(). El parámetro tightness (tirantez) determina cómo la curva calza con los vértices. El valor 0.0 es el valor por defecto (este valor define las curvas Spline Catmull-Rom) y el valor 1.0 conecta todos los puntos con líneas rectas. Valores en el rango entre -5.0 y 5.0 deformarán las curvas pero las dejarán reconocibles, y a medida que los valores crecen en magnitud, se continuarán deformando.", + "params": ["Número: deformación de los vértices originales"], + "returns": "the p5 object" + }, + "curvePoint": { + "description": "Evalua la curva en la posición t para los puntos a, b, c, d. El parámetro t varía entre 0 y 1, los puntos a y d son puntos en la cruva, y b y c son los puntos de control. Esto puede ser hecho una vez con las coordenadas x y una segunda vez con las coordenadas y para obtener la ubicación de la curva en t.", + "params": ["Número: coordenada del primer punto de la curva", + "Número: coordenada del primer punto de control de la curva", + "Número: coordenada del segundo punto de control de la curva", + "Número: coordenada del segundo punto de la curva", + "Número: valor entre 0 y 1"], + "returns": "the p5 object" + }, + "curveTangent": { + "description": "Evalua la tangente de la curva en la posición t para los puntos a, b, c, d. El parámetro t varía entre 0 y 1, a y d son los puntos de la curva, b y c son los puntos de control.", + "params": ["Número: coordenada del primer punto de la curva", + "Número: coordenada del primer punto de control de la curva", + "Número: coordenada del segundo punto de control de la curva", + "Número: coordenada del segundo punto de la curva", + "Número: valor entre 0 y 1"], + "returns": "la tangente en la posición t" + }, + "beginContour": { + "description": "Usa las funciones beginContour() y endContour() para crear figuras negativas dentro de figuras como el centro de la letra 'O'. beginContour() empieza la grabación de los vértices para la figura y endContour() finaliza la grabación. Los vértices que definen una figura negativa deben ser definidos en la dirección opuesta a la figura exterior. Primero dibuja los vértices de la figura exterior en el orden de las manecillas del reloj, y luego para figuras internas, dibuja vértices en el sentido contrario a las manecillas del reloj. Estas funciones solo pueden ser usadas dentro de un par beginShape()/endShape() y transformaciones como translate(), rotate(), y scale() no funcionan dentro de un par beginContour()/endContour(). Tampoco es posible usar otras figuras, como elupse() o rect() dentro.", + "returns": "el objeto p5" + }, + "beginShape": { + "description": "El uso de las funciones beginShape() y endShape() permiten la creación de figuras más complejas. beginShape() empieza la grabación de vértices para una figura, mientras que endShape() termina la grabación. El valor del parámetro kind (tipo) define qué tipo de figuras serán creadas a partir de los vértices. Si no se especifica un modo, la figura puede ser cualquier polígono irregular. Los parámetros disponibles para beginShape() son POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, y QUAD_STRIP. Después de llamar a la función beginShape(), debe ser seguida por una serie de comandos vertex(). Para detener el dibujo de la figura, ejecuta endShape(). Cada figura será dibujada con el color de trazo y el color de relleno actual. Transformaciones como translate(), rotate(), y scale() no funcionan dentro de beginShape(). Tampoco es posible usar otras figuras como ellipse() o rect() dentro de beginShape().", + "params": ["Constante: puede ser POINTS, LINES, TRIANGLES, TRIANGLE_FAN TRIANGLE_STRIP, QUADS, o QUAD_STRIP"], + "returns": "el objeto p5" + }, + "bezierVertex": { + "description": "Especifica las coordenadas de un vértice para una curva Bezier. Cada llamada a la función bezierVertex() define la posición de dos puntos de control y un punto ancla de una curva Bezier, añadiendo un nuevo segmento a la línea o figura. La primera vez que bezierVertex() es usada dentro de una llamada a beginShape(), debe ser antecedida por una llamada a la función vertex() para definir el primer punto ancla. Esta función debe ser usada entre beginShape() y endShape() y solo cuando no se ha especificado el parámetro MODE (modo) a beginShape().", + "params": ["Número: coordenada x del primer punto de control la curva", + "Número: coordenada y del primer punto de control la curva", + "Número: coordenada x del segundo punto de control la curva", + "Número: coordenada y del segundo punto de control la curva", + "Número: coordenada x del primer punto ancla", + "Número: coordenada y del primer punto ancla"], + "returns": "el objeto p5" + }, + "curveVertex": { + "description": "Especifica las coordenadas de un vértice para una curva. Esta función solo puede ser usada entre beginShape() y endShape() y cuando no se ha especificado el parámetro MODE en la función beginShape(). Los puntos primero y último en una serie de líneas curveVertex() serán usados para guiar el inicio y final de una curva. Un mínimo de cuatro puntos es requerido para dibujar una pequeña curva entre los puntos segundo y tercero, Añadir un quinto punto con curveVertex() dibujará la curva entre los puntos segundo, tercero y cuarto. La función curveVertex() es una implementación de las splines de Catmull-Rom.", + "params": ["Número: coordenada x del vértice", + "Número: coordenada y del vértice"], + "returns": "el objeto p5" + }, + "endContour": { + "description": "Usa las funciones beginContour() y endContour() para crear figuras negativas dentro de figuras como el centro de la letra 'O'. beginContour() empieza la grabación de los vértices para la figura y endContour() finaliza la grabación. Los vértices que definen una figura negativa deben ser definidos en la dirección opuesta a la figura exterior. Primero dibuja los vértices de la figura exterior en el orden de las manecillas del reloj, y luego para figuras internas, dibuja vértices en el sentido contrario a las manecillas del reloj. Estas funciones solo pueden ser usadas dentro de un par beginShape()/endShape() y transformaciones como translate(), rotate(), y scale() no funcionan dentro de un par beginContour()/endContour(). Tampoco es posible usar otras figuras, como elupse() o rect() dentro.", + "returns": "el objeto p5" + }, + "endShape": { + "description": "La función endShape() es compañera de la función beginShape() y solo puede ser ejecutada tras la ejecución de beginShape(). Cuando endshape() es ejecutada, todos los datos de imagen definidos desde la llamada anterior a beginShape() son escritos en el buffer de imagen. La constante CLOSE se usa como valor para el parámetro MODE para cerrar la figura (para conectar el comienzo con el final).", + "params": ["Constante: usa CLOSE para cerrar la figura."], + "returns": "el objeto p5" + }, + "quadraticVertex": { + "description": "Especifica las coordenadas de vértices par curvas Bezier cuadráticas. Cada llamada a quadraticVertex() define la posición de uno de los puntos de control y ancla de una curva Bezier, añadiendo un nuevo segmento a la línea o figura. La primera vez que quadraticVertex() es usada dentro de una llamada a beginShape(), debe ser precedida por una llamada a la función vertex() para definir el primer punto ancla. Esta función debe ser usada entre un par beginShape() y endShape() y solo cuando no se ha especificado el parámetro MODE de beginShape().", + "params": ["Número: coordenada x del punto de control", + "Número: coordenada y del punto de control", + "Número: coordenada x del punto ancla", + "Número: coordenada y del punto ancla"], + "returns": "el objeto p5" + }, + "vertex": { + "description": "Todas las figuras son construidas mediante la conexión de una serie de vértices. vertex() es usado para especificar las coordenadas de los vértices para puntos, líneas, triángulos, cuadriláteros y polígonos. Es usada exclusivamente dentro de un par de funciones beginShape() y endShape().", + "params": ["Número: coordenada x del vértice", + "Número: coordenada y del vértice"], + "returns": "el objeto p5" + }, + "loadModel": { + "description": "Carga un modelo 3d desde un archivo OBJ. Una de las limitaciones del formato OBJ es que no trae incorporado un sentido de escala. Esto significa que los modelos exportados por distintos programas pueden ser de tamaños radicalmente distintos. Si tu modelo no está siendo mostrado en pantalla, trata llamando a la función loadMode() con el parámetro de normalización configurado como verdadero. Esto escalará el tamaño del modelo a una escala apropiada para p5. También puedes hacer cambios adicionales al tamaño final de tu modelo con la función scale().", + "params": ["String: ubicación del modelo a cargar", + "Boolean: Si es verdadero (true), escala el modelo a un tamaño estandarizado al momento de cargarlo.", + "Función(p5.Geometry3D): función a ser llamada cuando el modelo se cargue. Será pasada al modelo del objeto 3D.", + "Función(evento): llamada con el error evento si la imagen no falla al cargar."], + "returns": "el objeto p5.Geometry3D" + }, + "model": { + "description": "Hace el render de un modelo 3D en la pantalla.", + "params": ["p5.Geometry: modelo 3D cargado para realizar render"], + "returns": "el objeto p5" + }, + "plane": { + "description": "Dibuja un plano con ancho y altura dados.", + "params": ["Número: ancho del plano", + "Número: altura del plano", + "Número: número opcional de subdivisiones triangulares en la dimensión x", + "Número: número opcional de subdivisiones triangulares en la dimensión y"], + "returns": "el objeto p5" + }, + "box": { + "description": "Dibuja una caja con ancho, altura y profundidad dados.", + "params": ["Número: ancho de la caja", + "Número: altura de la caja", + "Número: profundidad de la caja", + "Número: número opcional de subdivisiones triangulares en la dimensión x", + "Número: número opcional de subdivisiones triangulares en la dimensión y"], + "returns": "el objeto p5" + }, + "sphere": { + "description": "Dibuja una esfera de radio dado.", + "params": ["Número: radio del círculo", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], + "returns": "el objeto p5" + }, + "cylinder": { + "description": "Dibuja un cilindro de radio y altura dados.", + "params": ["Número: radio de la superficie", + "Número: altura del cilindro", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], + "returns": "el objeto p5" + }, + "cone": { + "description": "Dibuja un cono de radio y altura dados.", + "params": ["Número: radio de la superficie inferior", + "Número: altura del cono", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], + "returns": "el objeto p5" + }, + "ellipsoid": { + "description": "Dibuja un elipsoide de radio dado.", + "params": ["Número: radio x del círculo", + "Número: radio y del círculo", + "Número: radio z del círculo", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24. Evita números mayores a 150 que podrían colapsar el navegador.", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16. Evita números mayores a 150 que podrían colapsar el navegador."], + "returns": "el objeto p5" + }, + "torus": { + "description": "Dibuja un toroide con radio y tubo dado.", + "params": ["Número: radio del anillo completo", + "Número: radio del tubo", + "Número: radio z del círculo", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24.", + "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16."], + "returns": "el objeto p5" + }, + "HALF_PI": { + "description": "HALF_PI es una constante matemática de valor 1.57079632679489661923. Es la mitad de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", + "returns": "el objeto p5" + }, + "PI": { + "description": "PI es una constante matemática de valor 3.14159265358979323846. Es la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", + "returns": "el objeto p5" + }, + "QUARTER_PI": { + "description": "QUARTER_PI es una constante matemática de valor 0.7853982. Es un cuarto de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", + "returns": "el objeto p5" + }, + "TAU": { + "description": "TAU es un alias de TWO_PI, una constante matemática de valor 6.28318530717958647693. Es el doble de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", + "returns": "el objeto p5" + }, + "TWO_PI": { + "description": "TWO_PI es una constante matemática de valor 6.28318530717958647693. Es el doble de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", + "returns": "el objeto p5" + }, + "preload": { + "description": "La función preload() es ejecutada antes de setup(), es usada para manejar la carga asíncrona de archivos externos. Si se define una función preload(), setup() esperará hasta que las llamadas a funciones load hayan terminado. Solo se deben incluir instrucciones de carga dentro de preload() (loadImage, loadJSON, loadFont, loadStrings, etc).", + "returns": "el objeto p5" + }, + "setup": { + "description": "La función setup() es ejecutada una vez, cuando el programa empieza. Es usada para definir propiedades iniciales como amaño de la pantalla y color de fondo y para cargar medios como imágenes y tipografías cuando el programa empieza. Solo puede haber una función setup() en cada programa y no debe ser llamada después de su ejecución inicial. Nota: las variables declaradas dentro de setup() no son accesibles dentro de otras funciones, como draw().", + "returns": "el objeto p5" + }, + "draw": { + "description": "La función draw() es ejecutada después de setup(), y ejecuta contínuamente las líneas de código dentro de su bloque hasta que el programa es detenido o se ejecuta la función noLoop(). Notar que si noLoop() es ejecutada dentro de setup(), draw() igualmente será ejecutado una vez antes de parar. La función draw() es ejecutada automáticamente y nunca debiera ser ejecutada explícitamente. Siempre debería ser controlada con noLoop(), redraw() y loop(). Después de que noLoop() detiene la ejecución del código dentro de draw(), redraw() causa que el código dentro de draw() se ejecute una vez, y loop() causa que el código dentro de draw() siga ejecutándose de forma continua. El número de veces que draw() se ejecuta por segundo puede ser controlado con la función frameRate(). Solo puede haber una función draw() en cada bosquejo, y draw() solo debe existir si quieres que el código corra de forma continua, o para procesar eventos como mousePressed(). Algunas veces, podrías querer ejecutar una función draw() vacía, como se mostró en el ejemplo más arriba. Es importante notar que el sistema de coordenadas de dibujo será reiniciado al principio de cada ejecución de la función draw(). Si cualquier transformación es hecha dentro de draw() (por ejemplo: escalar, rotar, trasladar), sus efectos serán anulados al principio de cada ejecución de draw(), así que las transformaciones no se acumulan en el tiempo. Por el otro lado, el estilo aplicado (color de relleno, color de trazado) sí se mantendrá en efecto. ", + "returns": "el objeto p5" + }, + "remove": { + "description": "Remueve el bosquejo de p5 completamente. Esto removerá el lienzo y cualquier otro elemento creado por p5.js. También detendrá el bucle de dibujo y desvinculará cualquier propiedad o método global de la ventana. Dejará una variable p5 en caso que quieras crear un nuevo bosquejo p5. Si quieres, puedes definir p5 = null para borrar esta variable.", + "returns": "el objeto p5" + }, + "noLoop": { + "description": "Detiene la ejecución continua del código de draw() de p5.js. Si se llama a la función loop(), el código dentro de draw() empieza a correr de forma continua nuevamente. Si se usa noLoop() dentro de setup(), debe ser la última línea de código dentro del bloque. Cuando se usa noLoop(), no es posible manipular o acceder a la pantalla dentro de las funciones que manejan eventos como mousePressed() o keyPressed(). En vez de eso, usa estas funciones para llamar a redraw() o loop(), que permitirán la ejecución de draw(), lo que permite el refresco correcto de la pantalla. Esto significa que cuando noLoop() ha sido ejecutado, no se sigue dibujando, y funciones como saveFrame() o loadPixels() no se pueden usar. Notar que si el bosquejo es escalado, redraw() será llamado para actualizar el bosquejo, incluso si noLoop() ha sido ejecutada. Por otro lado, el bosquejo entrará a un estado singular, hasta que loop() sea ejecutado.", + "returns": "el objeto p5" + }, + "loop": { + "description": "Por defecto, p5.js repite de forma continua la función draw(), ejecutado el código dentro de su bloque. Sin embargo, el bucle de dibujo puede ser detenido llamando a la función noLoop(). En ese caso, el bucle de draw() puede ser retomado con loop().", + "returns": "el objeto p5" + }, + "push": { + "description": "La función push() graba la configuración actual de estilo de dibujo, y pop() restaura esta configuración. Notar que estas funciones siempre son usadas en conjunto. Permiten cambiar las configuraciones de estilo y transformaciones y luego volver a lo que tenías. Cuando un nuevo estado es iniciado con push(), construye encima de la información actual de estilo y transformación. Las funciones push() y pop() pueden ser embebidas para proveer más control (ver el segundo ejemplo para una demostración). push() almacena información relacionada a la configuración de estado de transformación y de estulo actual, controlada por las siguientes funciones: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading().", + "returns": "el objeto p5" + }, + "pop": { + "description": "La función push() graba la configuración actual de estilo de dibujo, y pop() restaura esta configuración. Notar que estas funciones siempre son usadas en conjunto. Permiten cambiar las configuraciones de estilo y transformaciones y luego volver a lo que tenías. Cuando un nuevo estado es iniciado con push(), construye encima de la información actual de estilo y transformación. Las funciones push() y pop() pueden ser embebidas para proveer más control (ver el segundo ejemplo para una demostración). push() almacena información relacionada a la configuración de estado de transformación y de estulo actual, controlada por las siguientes funciones: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading()." + }, + "redraw": { + "description": "Ejecuta una vez el código dentro de la función draw(). Esta función permite al programa actualizar la ventana mostrada solamente cuando es necesario, por ejemplo, cuando un evento registrado por mousePressed() o keyPressed() ocurre. En la estructura de un programa, solo hace sentido llamar a redraw() dentro de eventos como mousePressed(). Esto es porque redraw() no hace que draw() se ejecute de forma inmediata (solo define una indicación de que se necesita un refresco). La función redraw() no funciona de forma correcta cuando se llama dentro de la función draw(). Para habilitar y deshabilitar animaciones, usa las funcioens loop() y noLoop(). Adicionalmente, puedes definir el número de veces que se dibuja por cada llamada a este método. Para esto, añade un entero como parámetro único a la función, que señale cuántas veces se requiere dibujar.", + "params": ["Entero: redibuja n-veces. Por defecto el valor es 1"], + "returns": "el objeto p5" + }, + "print": { + "description": "La función print() escribe en la consola del navegador. Esta función es a menudo de ayuda para observar los datos que un programa está produciendo. Esta función crea una nueva línea de texto por cada ejecución de la función. Elementos individuales pueden ser separados por comillas ('') y unidos con el operador de adición (+). Aunque print() es similar a console.log(), no llama a console.log() directamente, para simular una manera más simple de entender el comportamiento del programa. Por esto mismo, es más lento. Para resultados más rápidos, usar directamente console.log().", + "params": ["Cualquiera: cualquier combinación de número, string, objeto, boolean o arreglo a imprimir"], + "returns": "el objeto p5" + }, + "frameCount": { + "description": "La variable de sistema frameCount contiene el número de cuadros (frames) que se han mostrado desde que el programa empezó a ejecutarse. Dentro de setup() el valor es 0, después de la primera iteración de draw() es 1, etc.", + "returns": "el objeto p5" + }, + "focused": { + "description": "Confirma si la ventana de un programa de p5.js está en foco, lo que significa que el bosquejo aceptará entradas desde el ratón o teclado. Esta variable es verdadera (true) si la ventana está en foco y falsa (false) si no.", + "returns": "el objeto p5" + }, + "cursor": { + "description" : "Define el cursor como un símbolo predeterminado o una imagen, o hace el cursor visible si es que estaba escondido. Si estás tratando de asignar una imagen al cursor, el tamaño recomendado es 16x16 o 32x32 pixeles. No es posible cargar una imagen al cursor si estás exportando tu programa a la Web, y no todos los modos funcionan con todos los navegadores. Los valores de los parámetros x e y deben ser menores a la dimensión de la imagen.", + "params": ["Número|Constante: puede ser ARROW, CROSS, HAND, MOVE, TEXT, o WAIT, o la dirección de una imagen", + "Número: el punto activo horizontal del cursor", + "Número: el punto activo vertical del cursor"], + "returns": "el objeto p5" + }, + "frameRate": { + "description": "Especifica el número de cuadros mostrados por segundo. Por ejemplo, la llamada a la función frameRate(30), tratará de refrescar 30 veces por segundo. Si el procesador no es lo suficientemente rápido para mantener la tasa especificada, la tasa de cuadros por segundo no será lograda. Definir la tasa de cuadros por segundo dentro de setup() es lo recomendable. La tasa por defecto es de 60 veces por segundo. Esto es lo mismo que setFrameRate(val). Llamar a la función frameRate() sin argumentos retorna la tasa actual. Esto es lo mismo que getFrameRate(). Llamar a la función frameRate() con arugmentos que no son de tipo número o no son positivos también retornarán la tasa actual.", + "params": ["Número: número de cuadros a ser mostrados cada segundo."], + "returns": "la tasa de cuadros por segundo (frameRate) actual" + }, + "noCursor": { + "description": "Esconde el cursor.", + "returns": "el objeto p5" + }, + + "displayWidth": { + "description": "Variable de sistema que almacena el ancho de la pantalla mostrada. Esto es usado para correr un programa a pantalla completa en cualquier dimensión de pantalla.", + "returns": "el objeto p5" + }, + "displayHeight": { + "description": "Variable de sistema que almacena la altura de la pantalla mostrada. Esto es usado para correr un programa a pantalla completa en cualquier dimensión de pantalla.", + "returns": "el objeto p5" + }, + "windowWidth": { + "description": "Variable de sistema que almacena el ancho interior de la ventana del navegador, equivale a window.innerWidth.", + "returns": "el objeto p5" + }, + "windowHeight": { + "description": "Variable de sistema que almacena la altura interior de la ventana del navegador, equivale a window.innerHeight.", + "returns": "el objeto p5" + }, + "windowResized": { + "description": "La función windowResized() es llamada cada vez que la ventana del navegador cambia de tamaño. Es un buen lugar para cambiar las dimensiones del lienzo o hacer cualquier otro ajuste necesario para acomodar las nuevas dimensiones de la ventana.", + "returns": "el objeto p5" + }, + "width": { + "description": "Variable de sistema que almacena el ancho del lienzo dibujado. Este valor es definido por el primer parámetro de la función createCanvas(). Por ejemplo, la llamada a la función (320, 240) define la variable width al valor 320. El valor por defecto de ancho es de 100 si es que createCanvas() no ha sido usado en el programa.", + "returns": "el objeto p5" + }, + "height": { + "description": "ariable de sistema que almacena la altura del lienzo dibujado. Este valor es definido por el primer parámetro de la función createCanvas(). Por ejemplo, la llamada a la función (320, 240) define la variable width al valor 240. El valor por defecto de ancho es de 100 si es que createCanvas() no ha sido usado en el programa.", + "returns": "el objeto p5" + }, + "fullscreen": { + "description": "Si se da un argumento, define que el bosquejo esté a pantalla completa basado en el valor del argumento. Si no se da un argumento, retorna el estado actual de pantalla completa. Notar que debido a restricciones del navegador esto solo puede ser llamado con una entrada de parte del usuario, por ejemplo, cuando se presiona el ratón como en el ejemplo.", + "params": ["Boolean: define si el bosquejo debe estar a pantalla completa o no."], + "returns": "Boolean: estado de pantalla completa actual" + }, + "pixelDensity": { + "description": "Define el escalamiento de pixeles para monitores de alta densidad de pixeles. Por defecto, la densidad de pixeles es definida para calzar con la densidad del monitor, ejecuta pixelDensity() para que no sea así. Llamar a pixelDensity() sin argumentos retorna la densidad de pixeles actual del bosquejo.", + "params": ["Número: si es que el bosquejo debe ser escalado y cuánto."], + "returns": "Número: densidad de pixeles actual del bosquejo" + }, + "displayDensity": { + "description": "Retorna la densidad de pixeles del monitor actual en que el bosquejo está corriendo.", + "returns": "Número: la densidad de pixeles actual del monitor" + }, + "getURL": { + "description": "Retorna la URL actual.", + "returns": "String: URL" + }, + "getURLPath": { + "description": "Retorna la dirección URL como un arreglo", + "returns": "Arreglo: los componentes de la dirección" + }, + "getURLParams": { + "description": "Retorna los parámetros de la URL actual como un objeto.", + "returns": "Objeto: parámetros de la URL" + }, + "createCanvas": { + "description": "Crea un elemento canvas en el documento, y define sus dimensiones medidas en pixeles. Este método debe ser llamado solo una vez al comienzo de la función setup(). Llamar a la función createCanvas() más de una vez en un bosquejo puede resultar en comportamientos impredecibles. Si quieres más de un lienzo donde dibujar, debes usar la función createGraphics() (escondido por defecto, pero puede ser mostrado), Las variables de sistema width (ancho) y height (altura) son definidas por los parámetros pasados a la función. Si createCanvas() no es usado, la ventana tendrá un tamaño por defecto de 100 x 100 pixeles. Para más maneras de posicionar el lienzo, ver la sección de posición del lienzo.", + "params": ["Número: ancho del lienzo", + "Número: altura del lienzo", + "Constante: P2D o WEBGL"], + "returns": "Objeto: lienzo generado" + }, + "resizeCanvas": { + "description": "Redimensiona el linezo al ancho y la altura dados. El lienzo será borrado y la función draw() será llamada inmediatamente, permitiendo que el bosquejo se ajuste al nuevo lienzo", + "returns": "el objeto p5" + }, + "noCanvas": { + "description": "Remueve el lienzo por defecto para un bosquejo de p5 que no requiere un lienzo.", + "returns": "el objeto p5" + }, + "createGraphics": { + "description": "Crea y retorna un nuevo objeto p5.Renderer. Usa esta clase si necesitas dibujar fuera de pantalla en un buffer gráfico. Los dos parámetros definen el ancho y la altura en pixeles.", + "params": ["Número: ancho del buffer gráfico fuera de pantalla", + "Número: altura del buffer gráfico fuera de pantalla", + "Constante: P2D o WEBGL, si no se define es P2D por defecto"], + "returns": "buffer gráfico fuera de pantalla" + }, + "blendMode": { + "description": "Combina los pixeles en la ventana según el modo definido. Existen distintas maneras de combinar los pixeles de la fuente (A) con los ya existentes en la pantalla mostrada (B). TODO", + "params": ["Constante: modo de combinar del lienzo"], + "returns": "el objeto p5" + }, + "applyMatrix": { + "description": "Multiplica la matriz actual por la especificada según los parámetros. Esto es muy lento porque tratará de calcular el inverso de la transformada, así que evítalo cuando sea posible", + "params": ["Número: números que definen la matriz 3x2 a multiplicar", + "Número: números que definen la matriz 3x2 a multiplicar", + "Número: números que definen la matriz 3x2 a multiplicar", + "Número: números que definen la matriz 3x2 a multiplicar", + "Número: números que definen la matriz 3x2 a multiplicar", + "Número: números que definen la matriz 3x2 a multiplicar"], + "returns": "el objeto p5" + }, + "resetMatrix": { + "description": "Reemplaza la matriz actual con la matriz identidad", + "returns": "el objeto p5" + }, + "rotate": { + "description": "Rota una figura según el monto especificado por el parámetro ángulo. Esta función toma en cuenta el modo de ángulo definido por angleMode(), así que los ángulos pueden ser ingresados en radianes o grados. Los objetos son siempre rotados según su posición relativa al origen y los números positivos rotan en la dirección de las manecillas del reloj. Las transformaciones se aplican a todo lo que ocurre de forma posterior y las subsecuentes llamadas a la función acumulan el efecto. Por ejemplo, llamar a la función rotate(HALF_PI) y luego rotate(HALF_PI) equivale a una llamada a rotate(PI). Todas las transformaciones son anuladas cuando la función draw() comienza nuevamente. Técnicamente, rotate() multiplica la matriz de transformación actual por una matriz de rotación. Esta función puede ser controlada además con las funciones push() y pop().", + "params": ["Ángulo: el ángulo de rotación, especificado en radianes o grados, dependiendo de angleMode()", + "Número: ángulo en radianes", + "p5.Vector|Arreglo: eje sobre el que se rota"], + "returns": "el objeto p5" + }, + "rotateX": { + "description": "Rota en torno al eje X", + "params": ["Número: ángulo en radianes"], + "returns": "el objeto p5" + }, + "rotateY": { + "description": "Rota en torno al eje Y", + "params": ["Número: ángulo en radianes"], + "returns": "el objeto p5" + }, + "rotateZ": { + "description": "Rota en torno al eje Z,. Sólo disponible en el modo WEBGL.", + "params": ["Número: ángulo en radianes"], + "returns": "el objeto p5" + }, + "scale": { + "description": "Aumenta o decrementa el tamaño de una figura por medio de expandir o contraer sus vértices. Los objetos siempre escalan desde su origen relativo al sistema de coordenadas. Los valores de escalamiento son porcentajes decimales. Por ejemplo, la llamada a la función scale(2.0) aumenta la dimensión de una figura en un 200%. Las transformaciones se aplican a todo lo que ocurre después y llamadas subsecuentes a la función multiplican el efecto. Por ejemplo, llamar a scale(2.0) y luego a scale(1.5) equivale a llamar a scale(3.0). Si la función scale() es llamad dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. El uso de esta función con el parámetro z está solo disponible en el modo WEBGL. Esta función puede también ser controlada con las funciones push() y pop().", + "params": ["Número | p5.Vector| Arreglo: porcentaje a escalar del objeto, o porcentaje a esacalar del objeto en el eje x si se dan múltiples argumentos", + "Número: porcentaje a escalar el objeto en el eje y", + "Número: porcentaje a escalar el objeto en el eje z (sólo en modo WEBGL)"], + "returns": "el objeto p5" + }, + "shearX": { + "description": "Corta la figura en torno al eje x según el monto especificado por el parámetro ángulo. Los ángulos deben ser especificados según el modo actual de ángulo angleMode(). Los objetos son siempre cortados según su posición relativa al origen y los números positivos cortan los objetos en la dirección de las manecillas del reloj. Las transformaciones aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a shearX(PI/2) y luego a shearX(PI/2) equivale a llamar a shearX(PI). Si shearX() es llamado dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. Técnicamente, shearX() multiplica la matriz de transformación actual por una matriz de rotación. La función puede ser controlada con las funciones push() y pop().", + "params": ["Número: ángulo de corte especificado en radianes o grados, dependiendo del modo de ángulo actual angleMode()"], + "returns": "el objeto p5" + }, + "shearY": { + + "description": "Corta la figura en torno al eje y según el monto especificado por el parámetro ángulo. Los ángulos deben ser especificados según el modo actual de ángulo angleMode(). Los objetos son siempre cortados según su posición relativa al origen y los números positivos cortan los objetos en la dirección de las manecillas del reloj. Las transformaciones aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a shearY(PI/2) y luego a shearY(PI/2) equivale a llamar a shearY(PI). Si shearY() es llamado dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. Técnicamente, shearY() multiplica la matriz de transformación actual por una matriz de rotación. La función puede ser controlada con las funciones push() y pop().", + "params": ["Número: ángulo de corte especificado en radianes o grados, dependiendo del modo de ángulo actual angleMode()"], + "returns": "el objeto p5" + }, + "translate": { + "description": "Especifica una cantidad a desplazar los objetos dentro de la ventana mostrada. El parámetro x especifica la traslación de izquierda a derecha, el parámetro y especifica la traslación de arriba a abajo. Las transformaciones son acumulativas y aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a translate(50, 0) y luego a translate(20, 0) equivale a llamar a translate(70, 0). Si translate() es llamado dentro de draw(), la transformación es anulada cada vez que el bucle empieza nuevamente. Esta función peude ser controlada con las funciones push() y pop().", + "params": ["Número: traslación izquierda-derecha", + "Número: traslación arriba-abajo", + "Número: traslación adelante-atrás (solo en modo WEBGL)"], + "returns": "el objeto p5" + }, + "deviceOrientation": { + "description": "La variable de sistema deviceOrientation siempre contiene la orientación del dispositivo. El valor de esta variable será o landscape (paisaje) o portrait (retrato). Si la información no está disponible, su valor será undefined.", + "returns": "el objeto p5" + }, + "accelerationX": { + "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje X. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "accelerationY": { + "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje Y. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "accelerationZ": { + "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje Z. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "pAccelerationX": { + "description": "La variable de sistema pAccelerationX siempré contiene la aceleración del dispositivo en el eje X, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "pAccelerationY": { + "description": "La variable de sistema pAccelerationY siempré contiene la aceleración del dispositivo en el eje Y, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "pAccelerationZ": { + "description": "La variable de sistema pAccelerationZ siempré contiene la aceleración del dispositivo en el eje Z, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", + "returns": "el objeto p5" + }, + "rotationX": { + "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje x. El valor está representado entre 0 y +/-180 grados. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", + "returns": "el objeto p5" + }, + "rotationY": { + "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje x. El valor está representado entre 0 y +/-180 grados. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", + "returns": "el objeto p5" + }, + "rotationZ": { + "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje y. El valor está representado entre 0 y 360 grados. A diferencia de rotationX y rotationY, esta variable está solo disponible en dispositivos equipados con una brújula interna. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", + "returns": "el objeto p5" + }, + "pRotationX": { + "description": "La variable de sistema pRotationX siempre contiene la rotación del dispositivo en el eje x, en el cuadro anterior al actual. El valor está representado entre 0 y +/-180 grados. pRotationX puede ser usado en conjunto con rotationX para determinar la dirección de rotación del dispositivo a lo largo del eje x.", + "returns": "el objeto p5" + }, + "pRotationY": { + "description": "La variable de sistema pRotationY siempre contiene la rotación del dispositivo en el eje x, en el cuadro anterior al actual. El valor está representado entre 0 y +/-90 grados. pRotationY puede ser usado en conjunto con rotationY para determinar la dirección de rotación del dispositivo a lo largo del eje y.", + "returns": "el objeto p5" + }, + "pRotationZ": { + "description": "La variable de sistema pRotationZ siempre contiene la rotación del dispositivo en el eje z, en el cuadro anterior al actual. El valor está representado entre 0 y 359 grados. pRotationZ puede ser usado en conjunto con rotationZ para determinar la dirección de rotación del dispositivo a lo largo del eje z.", + "returns": "el objeto p5" + }, + "setMoveThreshold": { + "description": "La función setMoveThreshold() es usada para definir el umbral para detectar movimiento de la función deviceMoved(). El valor umbral por defecto es 0.5", + "params": ["Número: el valor umbral"], + "returns": "el objeto p5" + }, + "setShakeThreshold": { + "description": "La función setShakeThreshold() es usada para definir el umbral para detectar agitamiento de la función deviceShaken(). El valor umbral por defecto es 30.", + "params": ["Número: el valor umbral"], + "returns": "el objeto p5" + }, + "deviceMoved": { + "description": "La función deviceMoved() es llamada cuando el dispositivo es movido en una cantidad mayor al valor umbral en el eje X, Y o Z. El valor umbral por defecto es 0.5", + "returns": "el objeto p5" + }, + "deviceTurned": { + "description": "La función deviceTurned() es llamada cuando el dispositivo es girado en más de 90 grados de modo continuo. El eje que gatilla la función deviceTurned() es almacenado en la variable turnAxis. El método deviceTurned() puede ser restringido para gatillar en cualquier eje: X, Y o Z, comparando la variable turnAxis con X, Y o Z.", + "returns": "el objeto p5" + }, + "deviceShaken": { + "description": "La función deviceShaken() es llamada cuando la aceleración total de los cambios de accelerationX y accelerationY son mayores al valor umbral. El valor umbral por defecto es 30", + "returns": "el objeto p5" + }, + "keyIsPressed": { + "description": "La variable boolean de sistema keyIsPressed es verdadera (true) cuando cualquier tecla es presionada y falsa (false) si no hay ninguna tecla presionada", + "returns": "el objeto p5" + }, + "key": { + "description": "La variable de sistema key siempre contiene el valor más reciente de la tecla del teclado presionada. Para tener los mejores resultados, es mejor usarla dentro de la función keyTyped(). Para teclas sin valor ASCII, usa la variable keyCode ", + "returns": "el objeto p5" + }, + "keyCode": { + "description": "La variable keyCode es usada para detectar teclas especiales, como BACKSPACE, DELETE, ENTER, RETURN, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. También puedes revisar las teclas especiales buscando el código keyCode de cualquier tecla en internet.", + "returns": "el objeto p5" + }, + "keyPressed": { + "description": "La función keyPressed() es llamada una vez cada vez que una tecla es presionada. El código keyCode de la tecla presionada es almacenado en la variable keyCode. Para las teclas sin valor ASCII, usa la variable keyCode. Puedes comprobar si la variable keyCode es igual a BACKSPACE, DELETE, ENTER, RETURN, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. Para las teclas con valor ASCII que son presionadas, el valor es almacenado en la variable key. Sin embargo, no distingue entre letras mayúsculas y minúsculas. Por esta razón, es recomendable usar la función keyTyped() para leer la variable key, que sí distingue entre mayúsculas y minúsculas. Por la forma en que los sistemas operativos manejan la repetición de teclas, mantener presionada una tecla puede causar múltiples llamadas a keyTyped() (y también keyReleased()). La tasa de repetición es definida por el sistema operativo y según cómo cada computador está configurado. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "returns": "el objeto p5" + }, + "keyReleased": { + "description": "La función keyReleased() es llamada una vez cada vez que una tecla es soltada. Ver key y keyCode para más información. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "returns": "el objeto p5" + }, + "keyTyped": { + "description": "la función keyTyped es llamada cava vez que una tecla es presionada, excepto cuando son presionadas la steclas de acción como Ctrl, Shift y Alt, que son ignoradas. La tecla presionada más reciente será almacenada en la variable key. Por la forma en que los sistemas operativos manejan la repetición de teclas, mantener presionada una tecla puede causar múltiples llamadas a keyTyped() (y también keyReleased()). La tasa de repetición es definida por el sistema operativo y según cómo cada computador está configurado. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "params": ["Número: el valor umbral"], + "returns": "el objeto p5" + }, + "keyIsDown": { + "description": "La función keyIsDown() comprueba si la tecla está presionada. Puede ser usada si tienes un objeto que se mueve, y quieres que varias teclas sean capaces de afectar este comportamiento de manera simultánea, como cuando mueves una imagen de forma diagonal. Puedes ingresar cualquier número representando el código de tecla keyCode de la tecla, o usar cualquier de los nombres de la variable keyCode.", + "params": ["Número: la tecla a buscar"], + "returns": "el objeto p5" + }, + "mouseX": { + "description": "La variable de sistema mouseX siempre contiene la posición horizontal actual del ratón, relativa al origen (0, 0) del lienzo.", + "returns": "el objeto p5" + }, + "mouseY": { + "description": "La variable de sistema mouseY siempre contiene la posición vertical actual del ratón, relativa al origen (0, 0) del lienzo.", + "returns": "el objeto p5" + }, + "pmouseX": { + "description": "La variable de sistema pmouseX siempre contiene la posición horizontal actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) del lienzo.", + "returns": "el objeto p5" + }, + "pmouseY": { + "description": "La variable de sistema pmouseY siempre contiene la posición vertical actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) del lienzo.", + "returns": "el objeto p5" + }, + "winMouseX": { + "description": "La variable de sistema winMouseX siempre contiene la posición horizontal actual del ratón, relativa al origen (0, 0) de la ventana del navegador.", + "returns": "el objeto p5" + }, + "winMouseY": { + "description": "La variable de sistema winMouseY siempre contiene la posición vertical actual del ratón, relativa al origen (0, 0) de la ventana del navegador.", + "returns": "el objeto p5" + }, + "pwinMouseX": { + "description": "La variable de sistema pwinMouseX siempre contiene la posición horizontal actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) de la ventana del navegador.", + "returns": "el objeto p5" + }, + "pwinMouseY": { + "description": "La variable de sistema pwinMouseY siempre contiene la posición vertical actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) de la ventana del navegador.", + "returns": "el objeto p5" + }, + "mouseButton": { + "description": "P5.js automáticamente rastrea si el botón del ratón está presionado y cuál botón está presionado. El valor de la variable de sistema mouseButton es o LEFT, RIGHT o CENTER dependiendo de cual fue el último botón presionado. Advertencia: diferentes navegadores pueden diferir.", + "returns": "el objeto p5" + }, + "mouseIsPressed": { + "description": "La variable boolean de sistema mouseIsPressed es verdadera (true) si el ratón está siendo presionado, y falsa (false) en caso contrario.", + "returns": "el objeto p5" + }, + "mouseMoved": { + "description": "La función mouseMoved() es llamada cada vez que el ratón se mueve y un botón del ratón no está siendo presionado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", + "returns": "el objeto p5" + }, + "mouseDragged": { + "description": "La función mouseDragged() es llamada cada vez que el ratón se mueve y un botón del ratón está siendo presionado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", + "returns": "el objeto p5" + }, + "mousePressed": { + "description": "La función mousePressed() es llamada cada vez que un botón del ratón está siendo presionado. La variable mouseButton (ver la referencia) puede ser usada para determinar cual botón está siendo presionado. Si no se define una función mousePressed(), la función touchStarted() será llamada en su reemplazo, si es que está definida. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", + "returns": "el objeto p5" + }, + "mouseReleased": { + "description": "La función mouseReleased() es llamada cada vez que un botón del ratón es soltado. Si no se define una función mouseReleased(), la función touchEnded() será llamada en su reemplazo, si es que está definida. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", + "returns": "el objeto p5" + }, + "mouseClicked": { + "description": "La función mouseClicked() es llamada cada vez que un botón del ratón es presionado y luego soltado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", + "returns": "el objeto p5" + }, + "mouseWheel": { + "description": "La función mouseWheel() es llamada cada vez que se detecta un evento de rueda de ratón vertical, ya sea gatillado por un ratón o por un touchpad. La propiedad event.delta retorna el monto que el ratón ha avanzado. Estos valores pueden ser positivos o negativos, dependiendo de la dirección de navegación (en OS X con natural scrolling, los signos son invertidos). Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método. Debido al soporte actual del evento wheel en Safari, la función podría solo funcionar si return false es incluido cuando se usa Safari.", + "returns": "el objeto p5" + }, + "touchX": { + "description": "La variable de sistema touchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) del lienzo. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", + "returns": "el objeto p5" + }, + "touchY": { + "description": "La variable de sistema touchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) del lienzo. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", + "returns": "el objeto p5" + }, + "ptouchX": { + "description": "La variable de sistema ptouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) del lienzo, en el cuadro anterior al actual. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", + "returns": "el objeto p5" + }, + "ptouchY": { + "description": "La variable de sistema ptouchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) del lienzo, en el cuadro anterior al actual. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", + "returns": "el objeto p5" + }, + "winTouchX": { + "description": "La variable de sistema winTouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) de la ventana.", + "returns": "el objeto p5" + }, + "winTouchY": { + "description": "La variable de sistema winTouchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) de la ventana.", + "returns": "el objeto p5" + }, + "pwinTouchX": { + "description": "La variable de sistema pwinTouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) de la ventana, en el cuadro anterior al actual.", + "returns": "el objeto p5" + }, + "pwinTouchY": { + "description": "La variable de sistema pwinTouchY siempre contiene la posición verticañ de un dedo, relativo al origen (0, 0) de la ventana, en el cuadro anterior al actual.", + "returns": "el objeto p5" + }, + "touches[]": { + "description": "La variable de sistema touches[] contiene un arreglo de las posiciones de todos los puntos de toque actuales, relativos al origen (0, 0) del lienzo, y también identificadores para cada toque mientras se mueve. Cada elemento en el arreglo es un objeto con las propiedas x, y e identidad.", + "returns": "el objeto p5" + }, + "touchIsDown": { + "description": "La variable boolean de sistema touchIsDown es verdadera (true) si en la pantalla hay un toque y falsa (false) si no.", + "returns": "el objeto p5" + }, + "touchStarted": { + "description": "La función touchStarted() es llamada una vez, cada vez que un toque nuevo es registrado. Si la función touchStarted() no ha sido definida, la función mouseIsPressed() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "returns": "el objeto p5" + }, + "touchMoved": { + "description": "La función touchStarted() es llamada una vez, cada vez que es registrado el movimiento de un toque. Si la función touchMoved() no ha sido definida, la función mouseDragged() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "returns": "el objeto p5" + }, + "touchEnded": { + "description": "La función touchEnded() es llamada una vez, cada vez que un toque finaliza. Si la función touchEnded() no ha sido definida, la función mouseReleased() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", + "returns": "el objeto p5" + }, + "createImage": { + "description": "Crea una nueva p5.Image (el tipo de datos para almacenar imágenes). Esto provee un nuevo buffer de pixeles para jugar. Define el tamaño del buffer con los parámetros de ancho y altuar. .pixels da acceso a un arreglo conteniendo los valores de todos los pixeles en la ventana mostrada. Estos valores son números. Este arreglo es del tamaño (incluyendo un factor apropiado de pixelDensity) de la ventana mostrada x4, representando los valroes R, G, B, A en orden para cada pixel., moviendo de izquierda a derecha en cada fila, y luego bajando de columna. Ver .pixels para mayor información. Podría ser más simple usar set() y get(). Antes de acceder a los pixeles de una imagen, los datos deben ser cargados con la función loadPixels(). Después de que el arreglo de datos ha sido modificado, la función updatePixels() debe ejecutarse para actualizar los cambios.", + "params": ["Entero: ancho en pixeles", + "Entero: altura en pixeles"], + "returns": "el objeto p5" + }, + "saveCanvas": { + "description": "Graba el lienzo actual como una imagen. En Safari, esto abrirá la imagen en la ventana y el usuario deberá proveer su propio nombre de archivo. Otros navegadores o grabarán el archivo de inmediato, o abrirán una ventana de diálogo.", + "params": ["Canvas seleccionado: una variable representando un canvas HTML5 específico (opcional)", + "String", + "String: jpg o png"], + "returns": "el objeto p5" + }, + "saveFrames": { + "description": "Captura una secuencia de cuadros que pueden ser usados para crear una película. Acepta una función callback. Por ejemplo, puedes querer mandar los cuadros a un servidor donde pueden ser almacenados o convertidos en una película. Si no se provee una función callback, el navegador abrirá varios diálogos tratando de descargar todas las imágenes que han sido creadas. Con una función callback provista, los datos de imagen no son grabados por defecto, sino que son pasados como argumento a la función callback como un arreglo de objetos, con el tamaño del arreglo siendo igual al número total de cuadros.", + "params": ["String: ", + "String: jpg o png", + "Número: duración en segundos para grabar los cuadros", + "Número: tasa de cuadros por segundo a grabar", + "Función: una función callback que será ejecutada para manejar los datos de imagen. Esta función deberá aceptar un arreglo como argumento. El arreglo contendrá el número especificado de cuadros como objetos. Cada objeto tiene tres propiedades: datos de imagen imageData, nombre del archivo y extensión"], + "returns": "el objeto p5" + }, + "loadImage": { + "description": "Carga una imagen desde una ruta de archivo y crea un objeto p5.Image. La imagen puede no estar inmediatamente disponible para render. Si quieres asegurarte que esté lista antes de hacer algo con ella, ubica la función loadImage() dentro de preload(). También puedes proveer una función callback para manejar la imagen cuando esté lista. La ruta a la imagen debe ser relativa al archivo HTML de tu bosquejo. Cargar desde una URL u otra ubicación remota podría estar bloqueado por las opciones de seguridad del navegador.", + "params": ["String: ruta de la imagen a cargar", + "Función(p5.Image): función a ser llamada una vez que la imagen sea cargada. Le será pasado el objeto p5.Image", + "Función(evento): llamada con el evento error si es que la carga de la imagen falla."], + "returns": "el objeto p5" + }, + "image": { + "description": "Dibuja una imagen en el lienzo principal del bosquejo p5.js.", + "params": ["p5.Image: la imagen a mostrar", + "Número: la coordenada x donde se ubicará la esquina superior de la imagen", + "Número: la coordenada y donde se ubicará la esquina superior de la imagen", + "Número: ancho de la imagen a dibujar", + "Número: altura de la imagen a dibujar", + "Número: la coordenada x en el lienzo de destino donde se ubicará la esquina superior izquierda de la imagen", + "Número: la coordenada y en el lienzo de destino donde se ubicará la esquina superior izquierda de la imagen", + "Número: ancho de la imagen a dibujar en el lienzo de destino", + "Número: altura de la imagen a dibujar en el lienzo de destino", + "Número: la coordenada x de la esquina superior izquierda del subrectángulo de la imagen original a dibujar en el lienzo de destino", + "Número: la coordenada y de la esquina superior izquierda del subrectángulo de la imagen original a dibujar en el lienzo de destino", + "Número: el ancho del subrectángulo de la imagen original a dibujar en el lienzo de destino", + "Número: la altura del subrectángulo de la imagen original a dibujar en el lienzo de destino"], + "returns": "el objeto p5" + }, + "tint": { + "description": "Define el valor de relleno para mostrar imágenes. Las imágenes pueden ser teñidas en colores específicos o hacerse transparentes al incluir un valor alpha. Para aplicar transparencia a una imagen sin afectar su color, usa blanco como color de teñido y especifica un valor alpha. Por ejemplo, tint(255, 128) hará una imagen 50% transparente (asumiendo el rango alpha por defecto entre 0 y 255, el que puede ser modificado con la función colorMode()). El valor del parámetro gris debe ser menor o igual al actual valor máximo según lo especificado por colorMode(). El valor máximo por defecto es 255.", + "params": ["Número|Arreglo: valor de gris, rojo o tinte (dependiendo del modo de color actual), o un arreglo de colores", + "Número|Arreglo: valor de verde o saturación (dependiendo del modo de color actual)", + "Número|Arreglo: valor de azul o brillo (dependiendo del modo de color actual)", + "Número|Arreglo: opacidad del fondo"], + "returns": "el objeto p5" + }, + "noTint": { + "description": "Remueve el valor actual de relleno para mostrar imágenes y revierte a mostrar las imágenes con sus colores originales.", + "returns": "el objeto p5" + }, + "imageMode": { + "description": "Define el modo de imagen. Modifica la ubicación desde la que las imágenes son dibujadas, por medio de cambiar la manera en que los parámetros dados a image() son interpretados. El modo por defecto es imageMode(CORNER), que interpreta los paráemtros segundo y tercero de image() como la posición de la esquina superior izquierda de la imagen. Si se dan dos parámetros adicionales, son usados para definir el ancho y la altura la imagen. imageMode(CORNERS) interpreta los paráemtros segundo y tercero de image() como la ubicación de una esquina, y los parámetros cuarto y quinto como la ubicación de la esquina opuesta. imageMode(CENTER) interpreta los parámetros segundo y tercero de image() como el punto central de la imagen. Si dos parámetros adicionales son especificados, son usados para definir el ancho y la altura de la imagen.", + "params": ["Constante: puede ser CORNER, CORNERS, o CENTER"], + "returns": "el objeto p5" + }, + "pixels[]": { + "description": "Arreglo tipo Uint8ClampedArray conteniendo los valores de todos los pixeles en la ventana mostrada. Estos valores son números. Este arreglo es del tamaño (incluyendo el factor apropiado de pixelDensity) de la ventana desplegada x4, representando los valores R, G, B, A por cada pixel, moviéndose de izquierda a derecha en cada fila, bajando una columna a la vez. Los monitores Retina y otros de alta densidad tendrán más pixeles en el arreglo (por un factor de pixelDensity al cuadrado). Por ejemplo, si la imagen es de 100 x 100 pixeles, habrán 40.000 valores. En un monitor retina, habrán 160.000. Los primeros cuatro valores (índices 0 a 4) en el arreglo serán los valores R, G, B, A del pixel en la posición (0, 0). Los siguientes cuatro valores (índices 4 a 7) serán los valores R, G, B, A del pixel en la posición (1, 0). De forma más general, para definir los valores de un pixel en (x, y): TODO. Aunque el método descrito es complejo, es lo suficientemente flexible como para trabajar con cualquier densidad de pixeles. Notar que set() inmediatamente se hace cargo de definir los valores apropiados en el arreglo pixels[] para un (x, y) dado a cualquier densidad de pixeles, pero el desempeño puede ser no tan rápido cuando muchas modificaciones son hechas en el arreglo de pixeles. Antes de acceder a este arreglo, los datos deben ser cargados con la función loadPixels(). Después de que el arreglo de datos ha sido modificado, la función updatePixels() debe ser ejecutada para refrescar los cambios. Notar que este no es un arreglo standard de Javascript. Esto significa que las funciones Javascript como slice() o arrayCopy() no funcionan.", + "returns": "el objeto p5" + }, + "blend": { + "description": "Copia una región de pixeles de una imagen a otra, usando un modo específico de mezcla para hacer la operación. Los modos disponibles de mezcla son: BLEND | DARKEST | LIGHTEST | DIFFERENCE | MULTIPLY| EXCLUSION | SCREEN | REPLACE | OVERLAY | HARD_LIGHT | SOFT_LIGHT | DODGE | BURN | ADD | NORMAL", + "params": ["p5.Image: imagen fuente", + "Entero: coordenada x de la esquina superior izquierda de la fuente", + "Entero: coordenada y de la esquina superior izquierda de la fuente", + "Entero: ancho de la imagen fuente", + "Entero: altura de la imagen fuente", + "Entero: coordenada x de la esquina superior izquierda del destino", + "Entero: coordenada y de la esquina superior izquierda del destino", + "Entero: ancho de la imagen destino", + "Entero: altura de la imagen destino", + "Constante: el modo de mezcla"], + "returns": "el objeto p5" + }, + "copy": { + "description": "Copia una región del lienzo a otra región del lienzo desde una imagen usada como el parámetro srcImage en el lienzo. Si la fuente y el destino no son del mismo tamaño, automáticamente redimensionará los pixeles de la fuente para calzar con la región especificada como destino.", + "params": ["p5.Image: imagen fuente", + "Entero: coordenada x de la esquina superior izquierda de la fuente", + "Entero: coordenada y de la esquina superior izquierda de la fuente", + "Entero: ancho de la imagen fuente", + "Entero: altura de la imagen fuente", + "Entero: coordenada x de la esquina superior izquierda de destino", + "Entero: coordenada y de la esquina superior izquierda de destino", + "Entero: ancho de la imagen de destino", + "Entero: altura de la imagen de destino"], + "returns": "el objeto p5" + }, + "filter": { + "description": "Aplica un filtro al lienzo. Las opciones posibles son: THRESHOLD, que convierte la imagen a pixeles blancos y negros dependiendo de si están arriba o abajo del umbral definido por el parámetro. El parámetro debe estar entre 0.0 (negro) y 1.0 (blanco). Si no se especifica ningún valor, el valor por defecto es 0.5. GRAY, convierte cualquier color en la imagen a un equivalente en la escala de grises, no tiene parámetros. OPAQUE, hace que el canal alpha sea totalmente opaco, no tiene parámetros. INVERT, hace que cada pixel tenga su valor inverso, no tiene parámetros. POSTERIZE, limita cada canal de la imagen a un número de colores especificado como parámetro. El parámetro puede definir entre 2 y 255 valores, pero los resultados más notorios se dan con valores bajos. BLUR, hace que la imagen sea borrosa con un proceso Gaussiano, siendo el parámetro el nivel de cuán borroso es el resultado, si no se usa ningún parámetro, el parámetro por defecto es 1, a mayores valores es más borroso el resultado. ERODE, reduce las áreas claras, no tiene parámetros. DILATE, aumenta las áreas claras, no tiene parámetros.", + "params": ["Constante: ", + "Número: un parámetro opcional único a cada filtro, ver más arriba"], + "returns": "el objeto p5" + }, + "get": { + "description": "Retorna un arreglo de valores RGBA por cada pixel o toma una sección de una imagen. Si no especifican parámetros, se retorna la imagen entera. Usa los parámetros x e y para obtener el valor de un pixel. Toma una sección de la ventana mostrada si especificas los parámetros adicionales w y h. Cuando se obtiene una imagen, los parámetros x e y definen las coordenadas de la esquina superior izquierda de la imagen, sin importar el actual mode imagen definido por imageMode(). Si el pixel solicitado está fuera de la imagen, se retorna el valor [0, 0, 0, 255]. Para obtener los números escalados según los rangoes de color actuales y tomar en cuenta el modo de color según colorMode(), usa getColor() en vez de get(). Tomar el valor de un pixel con get(x, y) es fácil, pero no tan rápido como tomar los datos directamente desde pixels[]. La instrucción equivalente a get(x, y) usando pixels[] con densidad de pixeles d es var off = (y width + x) d * 4; [pixels[off], pixels[off+1], pixels[off+2], pixels[off+3]]. Ver la referencia de pixels[] para mayor información.", + "params": ["Número: coordenada x del pixel", + "Número: coordenada y del pixel", + "Número: ancho", + "Número: altura"], + "returns": "Arreglo|p5.Image: valores de pixel en la posición (x, y) en formato arreglo RGBAs o p5.Image" + }, + "loadPixels": { + "description": "Carga los datos de los pixeles en pantalla al arreglo pixels[]. Esta función siempre debe ser llamada antes de leer o escribir en el arreglo pixels[]", + "returns": "el objeto p5" + }, + "set": { + "description": "Cambia el color de cualquier pixel, o pone una imagen directamente en la ventana. Los parámetros x e y especifican el pixel a cambiar y c especifica el valor del color. Puede ser un objeto p5.Color o un arreglo de pixeles RGBA. También puede ser un valor único en escala de grises. Cuando se define una imagen, los parámetros x e y definen las coordenadas de la esquina superior izquierda de la imagen, sin importar el modo actual de imagen según imageMode(). Después de usar set(), debes llamar a updatePixels()' para que tus cambios aparezcan. Esta función debería ser llamada una vez que todos los pixeles han sido definidos. Definir el color de un solo pixel con set(x, y) es fácil, pero es tan rápido como poner los datos directamente en el arreglo pixels[]. Definir los valores de pixels[] directamente puede ser complicado cuando se trabaja con un monitor retina, pero tendrá un mejor desempeño cuando muchos pixeles necesiten ser definidos directamente en cada iteración. Ver la referencia de pixels[] para mayor información.", + "params": ["Número: coordenada x del pixel", + "Número: coordenada x del pixel", + "Número: coordenada y del pixel", + "Número|Arreglo|Objeto: inserta un valor en escala de grises | un arreglo de pixeles | un objeto p5.Color | un objeto p5.Image a copiar"], + "returns": "el objeto p5" + }, + "updatePixels": { + "example": "", + + "description": "Actualiza la ventana mostrada con los datos del arreglo pixels[]. Se usa en conjunto con loadPixels(). Si solo estás leyendo pixeles desde el arreglo, no hay necesidad de llamar a updatePixels() - actualizar es solo necesario para aplicar cambios. updatePixels() debe ser llamada cada vez que el arreglo de pixeles es manipulado o si se llama a la función set().", + "params": ["Número: coordenada x de la esquina superior izquierda de la región a actualizar", + "Número: coordenada y de la esquina superior izquierda de la región a actualizar", + "Número: ancho de la región a actualizar", + "Número: altura de la región a actualizar"], + "returns": "el objeto p5" + }, + "loadFont": { + "description": "Carga un archivo de fuente de letra (.otf, .ttf) desde un archivo o URL, y retorna un objeto PFont. Este método es asíncrono, lo que significa que puede que no finalice antes de que la siguiente línea en tu bosquejo sea ejecutada. La ubicación del archivo debe ser relativo al archivo HTML que lo vincula con tu bosquejo. Cargar desde una URL u otra ubicación remota puede ser bloqueado por las opciones de seguridad del navegador.", + "params": ["String: número del archivo o URL a cargar", + "Función: función a ser ejecutada después de que loadFont() es completada"], + "returns": "Objeto: objeto p5.Font" + }, + "loadJSON": { + "description": "Carga un archivo JSON desde un archivo o una URL, y retorna un objeto o un arreglo. Este método es asíncrono, lo que significa que puede que no termine antes que se ejecute la siguiente línea en tu bosquejo.", + "params": ["String: nombre de archivo o URL a cargar", + "Función: función a ser ejecutada después de que loadJSON() finalice, los datos son pasados como primer argumento", + "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento", + "String: json o jsonp"], + "returns": "Objeto|Arreglo: datos JSON" + }, + "loadStrings": { + "description": "Lee los contenidos de un archivo y crea un arreglo de Strings de sus líneas individuales. Si el nombre del archivo es usado como parámetro, como en el ejemplo anterior, el archivo debe estar ubicado en el directorio del bosquejo. Alternativamente, el archivo puede ser cargado desde cualquier lugar del computador local usando una dirección absoluta (empieza con / en Unix y Linux, o una letra representando el disco en Windows), o el parámetro de nombre de archivo puede ser una URL donde esté el archivo dentro de una red. Este método es asíncrono, lo que significa que puede ser que su ejecución no termine antes de que se ejecute la siguiente línea del bosquejo.", + "params": ["String: nombre de archivo o URL a cargar", + "Función: función a ser ejecutada después de que loadStrings() finalice, el arreglo es pasado como primer argumento", + "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], + "returns": "Arreglo: un arreglo de Strings" + }, + "loadTable": { + "description": "Lee los contenidos de un archivo o URL y crea un objeto p5.Table con sus valores. Si un archivo es especificado, debe ser ubicado en el directorio data del bosquejo. El parámetro de nombre de archivo puede también ser una URL de un archivo en línea. Por defecto, se asume que el archivo está separado por comas (formato CSV), La tabla sólo busca una fila de encabezado si es que se incluye la opción header. Las opciones posibles incluyen: csv: se procesan los datos como valores separados por comas, tsv: se procesan los datos como separados por tabulación, header: la tabla tiene una fila de encabezados (títulos). Si se incluyenn múltiples opciones, se deben ingresar como parámetros separados por comas. Todos los archivos son cargados y grabados usando codificación UTF-8. Este método es asíncrono, lo que significa que su ejecución puede no haber terminado antes de que se ejecute la siguiente línea del bosquejo. Si se llama a loadTable() dentro de preload() se garantiza que se complete la operación antes de que setup() y draw() sean llamadas. Fuera de preload(), puedes suplir una función callback para manejar el objeto.", + "params": ["String: nombre de archivo o URL a cargar", + "String|Strings: header, csv, tsv", + "Función: función a ser ejecutada después de que loadTable() finalice, el arreglo es pasado como primer argumento. Si es exitosa, el objeto Table es pasado como primer argumento, en caso contrario se pasa el valor boolean false."], + "returns": "Objeto Table conteniendo los datos" + }, + "loadXML": { + "description": "Lee los contenidos de un archivo y crea un objeto XML con sus valores. Si el nombre del archivo es usado como parámetro, el archivo debe estar ubicado en el directorio del bosquejo. Alternativamente, el archivo puede ser cargado desde cualquier lugar del computador local usando una dirección absoluta (que empieza con / en Unix y Linux, o con una letra que simbolice el disco duro en Windows). También se puede usar como parámetro de nombre de archivo una URL para un archivo en una red. Este método es asíncrono, lo que significa que su ejecución puede no estar completa antes de que se ejecute la siguiente línea de código en el bosquejo. Llamar a loadXML() dentro de preload() garantiza que la operación se complete antes de que setup() y draw() sean llamados. Fuera de preload(), puedes suplir una función callBack para manejar el objeto.", + "params": ["String: nombre de archivo o URL a cargar", + "Función: función a ser ejecutada después de que loadXML() finalice, el objeto XML es pasado como primer argumento", + "Función: la función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], + "returns": "objeto XML que contiene los datos" + }, + "httpGet": { + "description": "Método para ejecutar una solicitud HTTP GET. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto.", + "params": ["String: nombre del archivo o URL a cargar", + "Objeto: parámetro de datos pasados con la solicitud enviada", + "String: json, jsonp, xml o text", + "Función: función a ser ejecutada después de que httpGet() finalice, los datos son pasados como primer argumento", + "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], + "returns": "el objeto p5" + }, + "httpPost": { + "description": "Método para ejecutar una solicitud HTTP POST. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto.", + "params": ["String: nombre del archivo o URL a cargar", + "Objeto: parámetro de datos pasados con la solicitud enviada", + "String: json, jsonp, xml o text", + "Función: función a ser ejecutada después de que httpPost() finalice, los datos son pasados como primer argumento", + "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], + "returns": "el objeto p5" + }, + "httpDo": { + "description": "Método para ejecutar una solicitud HTTP. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto. También puedes pasar un objeto especificando todos los parámetros de la solicitud siguiendo los ejemplos dentro de las llamadas de reqwest()", + "params": ["String: nombre del archivo o URL a cargar", + "Objeto: parámetro de datos pasados con la solicitud enviada", + "String: json, jsonp, xml o text", + "Función: función a ser ejecutada después de que httpDo() finalice, los datos son pasados como primer argumento", + "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], + "returns": "el objeto p5" + }, + "save": { + "description": "Graba una imagen, text, json, csv, wav o html. Hace que la descarga ocurra en el computador cliente. Notar que no es recomendado llamar a save() dentro de draw() si está en bucle, porque la función save() abrirá una ventana de diálogo en cada cuadro. El comportamiento por defecto es grabar el lienzo como una imagen. Puedes opcionalmente especificar un nombre de archivo. Por ejemplo: TODO. Alternativamente, el primer parámetro puede ser un puntero a un lienzo p5.Element, un arreglo de Strings, un arreglo de JSON, un objeto JSON, un p5.Table, un p5.Image, o un p5.SoundFile (requiere p5.sound). El segundo parámetro es el nombre del archivo (incluyendo la extensión). El tercer parámetro es para opciones específicas a este tipo de objeto. Este método grabará un archivo que se austa a los parámetros dados. Por ejemplo: TODO. ", + "params": ["Objeto|String: si se provee un nombre de archivo, se grabará el lienzo como una imagen con la extensión png o jpg, dependiendo del nombre del archivo. Si se provee un objeto, se grabará dependiendo del objeto y el nombre del archivo (ver los ejemplos anteriores)", + "String: Si se provee un objeto como el primer parámetro, entonces el segundo parámetro indica el nombre del archivo, y debe incluir la extensión apropiada (ver los ejemplos anteriores).", + "Boolean|String: opciones adicionales depndiendo del tipo de archivo. Por ejemplo, cuando se graba un archivo JSON, true indica que la salida será optimizada según el tamaño del archivo, en vez de por legibilidad."], + "returns": "el objeto p5" + }, + "saveJSON": { + "description": "Escribe los contenidos de un arreglo o un objeto JSON a un archivo .json. El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", + "params": ["Arreglo|Objeto:", + "String: ", + "Boolean: si es verdadero (true), remueve los saltos de línea del archivo de salida para optimizar el tamaño del archivo, en desmedro de la legibilidad."], + "returns": "el objeto p5" + }, + "saveStrings": { + "description": "Escribe un arreglo de Strings a un archivo de texto, una línea por String. El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", + "params": ["Arreglo: arreglo de Strings a ser escrito", + "String: nombre del archivo de salida"], + "returns": "el objeto p5" + }, + "saveTable": { + "description": "Escribe los contenidos de un objeto Table a un archivo. Por defecto es un archivo de texto con valores separados por coma (csv), pero también puede usar separación por tabulación (tsv), o generar una tabla HTML (html). El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", + "params": ["Table: el objeto Table a ser grabado en un archivo", + "String: el nombre del archivo en el que Table será grabado", + "String: puede ser tsv, csv o html."], + "returns": "el objeto p5" + }, + "p5.Table": { + "description": "Los objetos Table almacenan datos con múltiples filas y columnas, tal como una hoja de cálculo tradicional. Los objetos Table pueden ser generados desde cero, dinámicamente, o usando datos desde un archivo existente.", + "params": ["Arreglo: un arreglo de objetos p5.TableRow"], + "returns": "p5.Table: el objeto p5.Table generado" + }, + "p5.TableRow": { + "description": "Un objeto TableRow representa una única fila de datos, grabados en columnas, de una tabla. Un objeto TableRow contiene tanto un arreglo ordenado, como un objeto JSON desordenado.", + "params": ["String: opcional, puebla la fila con una serie de valores, separados por el separador", + "String: por defecto, valores separados por coma (csv)"], + "returns": "el objeto p5" + }, + "day": { + "description": "p5.js se comunica con el reloj de tu computador. La función day() retorna el día actual como un valor entre 1 y 31.", + "returns": "Número: el día actual" + }, + "hour": { + "description": "p5.js se comunica con el reloj de tu computador. La función hour() retorna la hora actual como un valor entre 0 y 23.", + "returns": "Número: la hora actual" + }, + "minute": { + "description": "p5.js se comunica con el reloj de tu computador. La función minute() retorna el minuto actual como un valor entre 0 y 59.", + "returns": "Número: el minuto actual" + }, + "millis": { + "description": "Retorna el número de milisegundos (milésimas de segundo) desde que el programa empezó a correr. La información es usada a menudo para temporizar eventos y animar secuencias", + "returns": "Número: el número de milisegundos desde que empezó el programa" + }, + "month": { + "description": "p5.js se comunica con el reloj de tu computador. La función month() retorna el mes actual como un valor entre 1 y 12.", + "returns": "Número: el mes actual" + }, + "second": { + "description": "p5.js se comunica con el reloj de tu computador. La función second() retorna el mes actual como un valor entre 0 y 59.", + "returns": "Número: el segundo actual" + }, + "year": { + "description": "p5.js se comunica con el reloj de tu computador. La función year() retorna el año actual como un entero (2014, 2015, 2015, etc).", + "returns": "Número: el año actual" + }, + "p5.XML": { + "description": "XML es una representación de un objeto XML, capaz de procesar código XML. Usa loadXML() para cargar archivos externos XML y crear objetos XML", + "params": ["String:"], + "returns": "p5.XML: el objeto p5.XML generado" + }, + "createVector": { + "description": "Crea un nuevo objeto p5.Vector (el tipo de datos para almacenar vectores). Esto provee un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección.", + "params": ["Número: componente x del vector", + "Número: componente y del vector", + "Número: componente z del vector"], + "returns": "el objeto p5" + }, + "p5.Vector": { + "description": "Una clase para describir un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección. El tipo de datos, sin embargo, graba los componentes del vector (x, y para 2D y x,y,z para 3D). La magnitud y la dirección pueden ser calculados con los métodos mag() y heading(). En muchos de los ejemplos de p5.js, verás que p5.Vector es usado para describir una posición, velocidad o aceleración. Por ejemplo, si consideras un rectángulo moviéndose a lo largo de la pantalla, en cada instante tiene una posición (un vector que apunta desde el origen hasta su ubicación), una velocidad(la tasa a la que la posición del objeto cambia por unidad de tiempo, expresada como vector), y aceleración (la tasa a la que la velocidad del objeto cambia por unidad de tiempo, expresada como vector). Como los vectores representan grupos de valores, no podemos simplemente usar las operaciones tradicionales de adición, multiplicación, etc. En vez de eso, necesitaremos hacer matemática de vectores, lo que es simplificado con los métodos dentro de la clase p5.Vector.", + "params": ["Número: componente x del vector", + "Número: componente y del vector", + "Número: componente z del vector"], + "returns": "el objeto p5" + }, + "abs": { + "description": "Calcula el valor absoluto (magnitud) de un número. Usa Math.abs(). El valor absoluto de un número es siempre positivo.", + "params": ["Número: número a computar"], + "returns": "Número: valor absoluto del número dado" + }, + "ceil": { + "description": "Calcula el entero más cercano que es mayor o igual que el valor del paráemtro. Usa Math.ceil(). Por ejemplo, ceil(9.03) retorna el valor 10.", + "params": ["Número: número a redondear"], + "returns": "Número: número redondeado hacia arriba" + }, + "constrain": { + "description": "Restringe un valor a estar entre un valor mínimo y uno máximo.", + "params": ["Número: número a restringir", + "Número: límite mínimo", + "Número: límite máximo"], + "returns": "Número: número restringido" + }, + "dist": { + "description": "Calcula la distancia entre dos puntos", + "params": ["Número: la coordenada x del primer punto", + "Número: la coordenada y del primer punto", + "Número: la coordenada z del primer punto", + "Número: la coordenada x del segundo punto", + "Número: la coordenada y del segundo punto", + "Número: la coordenada z del segundo punto"], + "returns": "Número: distancia entre los dos puntos" + }, + "exp": { + "description": "Retorna el número de Euler (2.71828...) elevado al parámetro n. Usa Math.exp().", + "params": ["Número: exponente a elevar"], + "returns": "e^n" + }, + "floor": { + "description": "Calcula el valor entero más cercano que es menor o igual al parámetro. Usa Math.floor().", + "params": ["Número: número a ser redondeado hacia abajo"], + "returns": "Número: número redondeado hacia abajo" + }, + "lerp": { + "description": "Calcula un número entre dos números a un incremento específico. El parámetro amt es la cantidad a interpolar entre los dos valores donde 0.0 es igual al primer punto, 0.1 está muy cerca del primer punto, 0.5 está a medio camino entre ambos números, etc. La función lerp es conveniente para crear movimiento a lo largo de un camino recto y para dibujar líneas punteadas.", + "params": ["Número: primer valor", + "Número: segundo valor", + "Número: número entre 0.0 y 1.0"], + "returns": "Número: valor interpolado" + }, + "log": { + "description": "Calcula el logaritmo natural (logaritmo con base e) de un número. Esta función espera que el parámetro n sea de un valor más grande que 0.0. Usa Math.log().", + "params": ["Número: número más grande que 0"], + "returns": "Número: logaritmo naturla de n" + }, + "mag": { + "description": "Calcula la magnitud (o tamaño) de un vector. Un vector es una dirección en el espacio comúnmente usada en gráfica computacional y álgebra lineal. Como no tiene posición de inicio, la magnitud del vector puede ser pensada como la distancia entre la coordenada 0,0 a su valor x,y. Por lo tanto, mag() es un atajo a escribir dist(0, 0, x, y).", + "params": ["Número: primer valor", + "Número: segundo valor"], + "returns": "Número: magnitud del vector entre (0, 0) y (a, b)" + }, + "map": { + "description": "Escala un nombre de un rango a otro rango. En el primer ejemplo anterior, el número 25 es convertido de un valor en el rango entre 0 y 100 a un valor cuyo rango está entre el borde izquierdo de la ventana (0) y el borde derecho (ancho).", + "params": ["Número: el valor a ser convertido", + "Número: límite inferior del rango actual", + "Número: límite superior del rango actual", + "Número: límite inferior del rango deseado", + "Número: límite superior del rango deseado"], + "returns": "Número: número escalado" + }, + "max": { + "description": "Determina el valor más grande en una secuencia de números, y luego retorna ese valor. max() acepta cualquier número de parámetros tipo número, o un arreglo de cualquier largo.", + "params": ["Número|Arreglo: números a comparar"], + "returns": "Número: número máximo" + }, + "min": { + "description": "Determina el valor más pequeño en una secuencia de números, y luego retorna ese valor. max() acepta cualquier número de parámetros tipo número, o un arreglo de cualquier largo.", + "params": ["Número|Arreglo: números a comparar"], + "returns": "Número: número mínimo" + }, + "norm": { + "description": "Normaliza un número de un rango a otro rango entre 0 y 1. Es idéntico a map(value, low, high, 0, 1). Los números fuera del rango no son saturados a 0 o 1, porque los números fuera de rango son muchas veces intencionales y útiles (ver el segundo ejemplo más arriba)", + "params": ["Número: valor entrante a ser normalizado", + "Número: límite inferior del rango actual", + "Número: límite superior del rango actual"], + "returns": "Número: número normalizado" + }, + "pow": { + "description": "Facilita las expresiones exponenciales. La función pow() es una manera eficiente de multiplicar números po sí mismos (o sus recíprocos) en grandes cantidades. Por ejemplo, pow(3, 5) es equivalente a la expresión 3*3*3*3*3 y pow (3, -5) es equivalente a 1/3*3*3*3*3. Usa Math.pow().", + "params": ["Número: base de la expresión exponencial", + "Número: potencia a la que se eleva la base"], + "returns": "n^e" + }, + "round": { + "description": "Calcula el entero más cercano al parámetro n. Por ejemplo, round(133.8) retorna el valor 134. Usa la función Math.round().", + "params": ["Número: número a redondear"], + "returns": "Número: número redondeado" + }, + "sq": { + "description": "Eleva al cuadrado un número (lo multiplica por sí mismo), El resultado es siempre un número positivo, porque multiplicar dos números negativos siempre resulta en un número positivo.", + "params": ["Número: número a elevar al cuadrado"], + "returns": "Número: número elevado al cuadrado" + }, + "sqrt": { + "description": "Calcula la raíz cuadrada de un número. La raíz cuadrada de un número es siempre positiva, aunque puede haber una raíz cuadrada válida que sea negativa. La raíz cuadrada s de un número a es tal que s*s = a. Es lo opuesto a elevar al cuadrado. Usa Math.sqrt().", + "params": ["Número: número no negativo al que se le calcula la raíz cuadrada"], + "returns": "Número: raíz cuadrada del número" + }, + "noise": { + "description": "Retorna el valor del ruido Perlin en las coordenadas específicas. El ruido Perlin es un generador de secuencias aleatorias produciendo una sucesión de números más naturalmente ordenada y armónica, en comparación con la función estándar random(). Fue inventada por Ken Perlin en los 1980s y ha sido usada desde entonces en aplicaciones gráficas para producir texturas procedurales, movimiento natural, figuras, terrenos, etc. La principal diferencia con la función random() es definida en una espacio infinito n-dimensional donde cada par de coordenadas corresponde a un valor fijo semi-aleatorio (fijado solo durante el tiempo de vida del programa; ver la función noiseSeed()). p5.js puede calcular ruido 1D, 2D y 3D, dependiendo del número de coordenadas dado. El valor resultante siempre estará entre 0.0 y 1.0. El valor de ruido puede ser animado moviéndose a través del espacio del ruido como fue demostrado en el ejemplo superior. Las dimensiones segunda y tercera también pueden ser interpretadas como tiempo. El ruido está estructurado de forma similar a una señal de audio, con respecto al uso de la función de las frecuencias. De forma similar al conecpto de armónicas en física, el ruido Perlin es calculado a lo largo de varias octavas que se han sumado para dar forma al resultado final. Otra manera de ajustar el caracter de la secuencia resultante es la escala de las coordenadas de entrada. Como la función trabaja en un espacio infinito, el valor de las coordenadas no importa como tal, solo la distancia entre las coordenadas sucesivas importa (por ejemplo: cuando se usa noise() dentro de un bucle). Como regla general, a menor la diferencia entre coordenadas, más suave es el ruido resultante. Pasos entre 0.005 y 0.03 funcionan mejor para la mayor parte de las aplicaciones, pero esto diferirá dependiendo del uso.", + "params": ["Número: coordenada x en el espacio del ruido", + "Número: coordenada y en el espacio del ruido", + "Número: coordenada z en el espacio del ruido"], + "returns": "valor de ruido Perlin (entre 0 y 1) en las coordenadas especificadas" + }, + "noiseDetail": { + "description": "Ajusta el caracter y nivel de detalle producido por la función de ruido Perlin. Similar al concepto de armónicas en física, el ruido es calculado a lo largo de varias octavas. Las octavas más graves contribuyen de forma más significativa a la señal de salida y como define la intensidad general del ruido, mientras que las octavas más altas crean detalles más finos en la secuencia de ruido. Por defecto, el ruido es calculado a lo largo de 4 octavas, con cada octava contribuyendo exactamente la mitad que su predecesora, partiendo con una intensidad de 50% para la primera octava. Este tamaño de caída puede ser cambiado al añadir un parámetro adicional a la función. Por ejemplo, un factor de caída de 75% significa que cada octava tendrá un 75% de impacto (25% menos) que la octava anterior. Cualquier valor entre 0.0 y 1.0 es válido, sin embargo nota que valores superiores a 0.5 pueden resultar en que noise() retorne valores mayores a 1.0. Al cambiar estos parámetros, la señal creada por noise() puede ser adaptada para calzar con necesidades y características específicas.", + "params": ["Número: número de octavas a ser usadas por el ruido", + "Número: factor de caída para cada octava"], + "returns": "el objeto p5" + }, + "noiseSeed": { + "description": "Define el valor semilla para la función noise(). Por defecto, noise() produce diferentes resultados cada vez que el programa es ejecutado. Defines el parámetro value a una constante para que retorne la misma secuencia de números pseudo-aleatorios cada vez que el programa es ejecutado", + "params": ["Número: el valor semilla"], + "returns": "el objeto p5" + }, + "acos": { + "description": "El inverso de la función cos(), retorna el arcocoseno de un valor. Esta función espera valores entre -1 y 1 y los valores retornados están en el rango entre 0 y PI (3.1415927).", + "params": ["Número: el valor al que se aplica arcocoseno"], + "returns": "Número: el arcocoseno del valor" + }, + "asin": { + "description": "El inverso de la función sin(), retorna el arcoseno de un valor. Esta función espera valores entre -1 y 1 y los valores retornados están en el rango entre -PI/2 y PI/2 .", + "params": ["Número: el valor al que se aplica arcoseno"], + "returns": "Número: el arcoseno del valor" + }, + "atan": { + "description": "El inverso de la función tan(), retorna el arcotangente de un valor. Esta función espera valores entre -Infinito e Infinito (exclusivo) y los valores retornados están en el rango entre -PI/2 y PI/2 .", + "params": ["Número: el valor al que se aplica arcotangente"], + "returns": "Número: el arcotangente del valor" + }, + "atan2": { + "description": "Calcula el ángulo (en radianes) desde un punto específico al origen, medido desde el eje x positivo. Los valores retornados son de tipo float entre -PI/2 y PI/2. La función atan2() es más frecuentemente usada para orientar figuras figuras geométricas según la posición del cursor. Nota: la coordenada y del punto es el primer parámetro, y la coordenada x es el segundo parámetro, debido a la estructura para calcular la tangente.", + "params": ["Número: coordenada y del punto", + "Número: coordenada x del punto"], + "returns": "Número: el arcotangente del punto dado" + }, + "cos": { + "description": "calcula el coseno de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", + "params": ["Número: el ángulo"], + "returns": "Número: el coseno del ángulo" + }, + "sin": { + "description": "calcula el seno de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", + "params": ["Número: el ángulo"], + "returns": "Número: el seno del ángulo" + }, + "tan": { + "description": "calcula la tangente de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", + "params": ["Número: el ángulo"], + "returns": "Número: la tangente del ángulo" + }, + "degrees": { + "description": "Convierte una medida en radianes a su correspondiente valor en grados. Radianes y grados son dos maneras de calcular lo mismo. Hay 360 grados en un círculo y 2*PI radianes en un círculo. Por ejemplo, 90 grados equivalen a PI/2 radianes.", + "params": ["Número: valor en radianes a ser convertido a grados."], + "returns": "el ángulo convertido" + }, + "radians": { + "description": "Convierte una medida en grados a su correspondiente valor en radianes. Radianes y grados son dos maneras de calcular lo mismo. Hay 360 grados en un círculo y 2*PI radianes en un círculo. Por ejemplo, 90 grados equivalen a PI/2 radianes.", + "params": ["Número: valor en grados a ser convertido a radianes."], + "returns": "el ángulo convertido" + }, + "angleMode": { + "description": "Define el modo actual de p5 para interpretar ángulos. El modo por defecto es en RADIANS (radianes).", + "params": ["CONSTANTE: puede ser RADIANS (radianes) o DEGREES (grados)"], + "returns": "el objeto p5" + }, + "randomSeed": { + "description": "Define la semilla para la función random(). Por defecto, la función random() produce diferentes resultados cada vez que el programa es ejecutado. Definir el parámetro semilla como una constante hace que retorne la misma secuencia de números pseudo-aleatorios cada vez que el programa es ejecutado.", + "params": ["Número: el valor semilla"], + "returns": "el objeto p5" + }, + "random": { + "description": "Retorna un número aleaotorio de tipo float (punto flotante). Acepta 0, 1 o 2 argumentos. Si no se le da un argumento, retorna un número aleatorio entre 0 y 1 (sin incluir 1). Si se da un argumento y es un número, retorna un número aleatorio entre 0 y hasta (pero sin incluir) el parámetro. Si se da un argumento y es un arreglo, retorna una elemento al azar del arreglo. Si se dan dos argumentos, retorna un número aleatorio entre el primer argumento y hasta (pero sin incluir) el segundo argumento.", + "params": ["Número: el límite inferior (inclusivo)", + "Número: el límite superio (exclusivo)", + "Arreglo: el arreglo del cual se elige"], + "returns": "Número: el número aleatorio o un elemento aleatorio de un conjunto de opciones" + }, + "randomGaussian": { + "description": "Retorna un número aleatorio ajjustado a una distribución Gaussiana o normal. No existe teóricamente un valor mínimo o máximo que la función randomGaussian() pueda retornar. En vez de eso, existe solo una muy baja probabilidad de retornar valores lejos de la media, y una alta probabilidad de retornar números cercanos a la media. Acepta 0, 1 o 2 argumentos. Si no tiene argumentos, retorna una media de 0 y una desviación estándar de 1. Si tiene un argumento, el argumento es la media (y la desviación estándar es 1). Si tiene dos argumentos, el primero es la media y el segundo es la desviación estándar.", + "params": ["Número: la media", + "Número: la desviación estándar"], + "returns": "el número aleatorio" + }, + "textAlign": { + "description": "Define el alineamiento actual para dibujar texto. Acepta dos argumentos: horizAlign(LEFT, CENTER o RIGHT) y vertAlign(TOP, BOTTOM, CENTER, o BASELINE). El parámetro horizAlign se refiere al valor x de la función text(), mientras que vel parámetro vertAlign al valor y. Así que si escribes textAlign(LEFT), estás alineando el borde izquierdo de tu texto al valor x dado en la función text(). Si escribes textAlign(RIGHT, TOP), estás alineando el borde derecho de tu texto con el valor x y el borde superior con el valor y del texto.", + "params": ["Constante: alineamiento horizontal, puede ser LEFT, CENTER o RIGHT", + "Constante: alineamiento vertical, puede ser TOP, BOTTOM, CENTER o BASELINE"], + "returns": "el objeto p5" + }, + "textLeading": { + "description": "Define o retorna el espaciado, en pixeles, entre líneas de texto. Esta configuración será usada en todas las llamadas posteriores a la función text().", + "params": ["Número: el tamaño en pixeles de espaciamiento entre líneas"], + "returns": "el objeto p5" + }, + "textSize": { + "description": "Define o retorna el tamaño actual de la tipografía. Este tamaño será usado en todas las llamadas posteriores a la función text(). El tamaño de la tipografía es medido en pixeles.", + "params": ["Número: el tamaño en pixeles de las letras en pixeles"], + "returns": "el objeto p5" + }, + "textStyle": { + "description": "Define o retorna el estilo actual de la tipografía. Puede ser NORMAL (normal), ITALIC (cursivo) o BOLD (destacado). Notar que puede ser anulado por estilo CSS. Para tipografías que no sean de sistema (opentype, truetype, etc.), usa loadFont().", + "params": ["Número|Constante: estilo del texto, puede ser NORMAL, ITALIC o BOLD"], + "returns": "el objeto p5" + }, + "textWidth": { + "description": "Calcula y retorna el ancho de cualquier caracter o string.", + "params": ["String: el String de caracteres a medir"], + "returns": "Número" + }, + "text": { + "description": "Dibuja texto en la pantalla. Muestra la información especificada en el primer parámetro en la pantalla, en la posición especificada por los parámetros adicionales. Una fuente por defecto será usada a menos que una fuente sea definida por la función textFont() y un tamaño por defecto será usado a menos que se use la función textSize(). Cambia el color del texto con la función fill(). Cambia la apariencia del texto con las funciones stroke() y strokeWeight(). El texto se muestra en relación a la función textAlign(), que da la opción de dibujar a la izuiqerda, derecha y centro de las coordenadas. Los parámetros x2 e y2 definen un área rectangular donde mostrar el texto y solo puede ser usado por los datos tipo String. Cuando estos parámetros son especificados, son interpretados según la configuración de rectMode(). El texto que no cabe completamente dentro del rectángulo especificado no será dibujado en pantalla.", + "params": ["String: símbolos alfanuméricos a ser mostrados", + "Número: coordenada x del texto", + "Número: coordenada y del texto", + "Número: por defecto, el ancho de la caja contenedora del texto, ver rectMode() para más información", + "Número: por defecto, la altura de la caja contenedora del texto, ver rectMode() para más información"], + "returns": "Objeto" + }, + "textFont": { + "description": "Define la función actual con la que se dibujará el contenido de la función text()", + "params": ["Objeto|String: una fuente cargada con loadFont(), o un String representando una tipografía segura de la web (una fuente ampliamente disponible a lo largo de todos los sistemas)."], + "returns": "Objeto" + }, + "p5.Font": { + "description": "Clase base para manipulación de tipografía", + "params": ["Objeto: puntero a la instancia p5"], + "returns": "el objeto p5" + }, + "append": { + "description": "Añade un valor al final de un arreglo. Extiende el largo de un arreglo en una unidad. Usa la función Array.push()", + "params": ["Arreglo: Arreglo al que se agregará el dato", + "Cualquiera: a ser añadido al arreglo"], + "returns": "el objeto p5" + }, + "arrayCopy": { + "description": "Copia el arreglo (o una parte del arreglo) a otro arreglo. El arreglo fuente es copiado al arreglo de destino, empezando por la posición especificada por srcPosition y a la posición especificada por dstPosition. El número de elementos a copiar es determinado por el largo. Notar que al copiar valores se sobreescriben los valores existentes en el arreglo de destino. Para anexar valores en vez de sobreescribirlos, usa la función concat(). La versión simplificada con dos argumentos, arrayCopy(src, dest), copia un arreglo entero a otro del mismo tamaño. Es equivaletne a arrayCopy(src, 0, dst, 0, src.length). Usar esta función es mucho más eficiente para copiar datos de un arreglo que iterar con un bucle for() y copiar cada elemento individualmente. ", + "params": ["Arreglo: el arreglo fuente", + "Número: posición inicial en el arreglo fuente", + "Arreglo: el arreglo de destino", + "Número: posición inicial del arreglo de destino", + "Número: númeor de elementos del arreglo a ser copiados"], + "returns": "el objeto p5" + }, + "concat": { + "description": "Concatena dos arreglos, usa la función Array.concat(). No modifica los arreglos de entrada.", + "params": ["Arreglo: primer arreglo a concatenar", + "Arreglo: segundo arreglo a concatenar"], + "returns": "Arreglo: el arreglo concatenado" + }, + "reverse": { + "description": "Invierte el orden un arreglo, usa Array.reverse().", + "params": ["Arreglo: arreglo a ser invertido"], + "returns": "el objeto p5" + }, + "shorten": { + "description": "Disminuye un arreglo en un elemento y retorna el arreglo más corto, usa Array.pop().", + "params": ["Lista: arreglo a acortar"], + "returns": "Arreglo: el arreglo acortado" + }, + "shuffle": { + "description": "Ordena aleatoriamente los elementos de un arreglo. Implementa el algoritmo Fisher Yates.", + "params": ["Arreglo: Arreglo a ordenar", + "Boolean: modifica el arreglo"], + "returns": "Arreglo: retorna el arreglo ordenado" + }, + "sort": { + "description": "Ordena un arreglo de números, desde el más pequeño al más grande, o pone un arreglo de palabras en orden alfabético. El arreglo original no es modificado, un nuevo arreglo ordenado es retornado. El parámetro count define el número de elementos a ordenar. Por ejemplo, si hay 12 elementos en un arreglo y count es 5, los primeros 5 elementos del arreglo serán ordenados.", + "params": ["Arreglo: arreglo a ordenar", + "Número: número de elementos a ordenar, empezando desde 0"], + "returns": "el objeto p5" + }, + "splice": { + "description": "Inserta un valor o un arreglo de valores en un arreglo existente El primer parámetro especifica el arreglo inicial a ser modificado, y el segundo parámetro define los datos a insertarse. El tercer parámetro es un índice que especifica la posición del arreglo a partir de la que se insertarán los datos. Recuerda que el índice del arreglo empieza en 0, así que la primera posición es 0, la segunda es 1, etc.", + "params": ["Arreglo: arreglo a ser modificado", + "Cualquiera: valor a ser introducido", + "Número: posición del arreglo donde se inserta el dato"], + "returns": "el objeto p5" + }, + "subset": { + "description": "Extrae un arreglo de elementos de un arreglo existente. El parámetro list define el arreglo desde el cual los elementos serán copiados, y los parámetros start y count especifican cuáles elementos extraer. Si no especifica count, los elementos serán extraidos desde el principio. Esta función no modifica el arreglo original", + "params": ["Arreglo: arreglo del cual se extrae", + "Número: posición de donde empezar a extraer", + "Número: número de valores a extraer"], + "returns": "Arreglo: arreglo de elementos extraidos" + }, + "float": { + "description": "Convierte un String a su representación de punto flotante. Los contenidos de un String deben parecerse a un número, en otro caso NaN es retornado. Por ejemplo, float('1234.56') evalua a 1234.56, pero float('giraffe') retorna NaN. Cuando un arreglo de valores es pasado, un arreglo de floats del mismo largo es retornado.", + "params": ["String: string a ser procesado"], + "returns": "Número: representación en punto flotante de un string" + }, + "int": { + "description": "Convierte un boolean, string o float a su representación en número entero. Cuando un arreglo de valores es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", + "params": ["String|Boolean|Número|Arreglo: valor a procesar"], + "returns": "Número: valor representado como entero" + }, + "str": { + "description": "Convierte un boolean, string, o número a su representación en string. Cuando un arreglo de valores es introducido, entonces un arreglo de strings de la misma longitud es retornado.", + "params": ["String|Boolean|Número|Arreglo: valor a procesar"], + "returns": "String: valor representado como string" + }, + "boolean": { + "description": "Convierte un número o string a su representación en boolean. Para números, cualquier valor distinto de cero (positivo o ne gativo), evalua a true, mientras que cero evalua a falso. Para un string, el valor true evalua a true, mientras que cualquier otro valor evalua a falso. Cuando un arreglo de números o strings es introducido, entonces un arreglo de booleans de la misma longitud es retornado.", + "params": ["String|Boolean|Número|Arreglo: valor a procesar"], + "returns": "Boolean: representación en formato boolean del valor" + }, + "byte": { + "description": "Convierte un número, string o boolean a su representación en byte. Un byte puede solo ser un número entero entre -128 y 127, así que cuando un valor fuera de este rango es convertido, se hace wrap a la representación correspondiente en byte. Cuando un arreglo de números, string, o booleans es introducido, entonces un arreglo de bytes de la misma longitud es retornado.", + "params": ["String|Boolean|Número|Arreglo: valor a procesar"], + "returns": "Número: representación en formato byte del valor" + }, + "char": { + "description": "Convierte un número o string a su representaciómo como un string de un único caracter. Si se provee un parámetro, es primero pasado como entero y luego evaluado como un string de un único caracter. Cuando un arreglo de números o strings es introducido, entonces un arreglo de strings de un único caracter de la misma longitud es retornado.", + "params": ["String|Número|Arreglo: valor a procesar"], + "returns": "String: representación en formato string del valor" + }, + "unchar": { + "description": "Convierte un string de un único caracter a su correspondiente representación como valor entero. Cuando un arreglo de strings de un caracter es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", + "params": ["String|Arreglo: valor a procesar"], + "returns": "Número: representación en formato entero del valor" + }, + "hex": { + "description": "Convierte un número a su correspondiente representación como hexadecimal. Si se ingersa un segundo parámetro, es usado para definir el número de caracteres a generar en la notación hexadecimal. Cuando un arreglo es introducido, entonces un arreglo de strings en notación hexadecimal de la misma longitud es retornado.", + "params": ["Número|Arreglo: valor a procesar"], + "returns": "String: representación en formato string hexadecimal del valor" + }, + "unhex": { + "description": "Convierte una representación en string de un número hexadecimal a su correspondiente representación como valor entero. Cuando un arreglo de strings en notación hexadecimal es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", + "params": ["String|Arreglo: valor a procesar"], + "returns": "Número: representación en formato entero del valor hexadecimal" + }, + "join": { + "description": "Combina una arreglo de Strings en un String, cada uno separado por los caracteres usados como parámetro separator. Para unir arreglos de enteros o floats, es necesario primero convertirlos a Strings usando las funciones nf() o nfs().", + "params": ["Arreglo: arreglo de Strings a ser unidos", + "String: String a ser posicionado entre cada item"], + "returns": "String: String unificado" + }, + "match": { + "description": "Esta función es usada para aplicar una expresión regular a una porción de texto, y retorna grupos coincidentes (elementos encontrados entre paréntesis) como un arreglo de Strings. Si no existen coincidencias, se retorna el valor null. Si no se especifican grupos en la expresión regular, pero la secuencia coincide, un arreglo de largo 1 (con el texto coincidente como primer elemento del arreglo) será retornado. Para usar la función, primero comprueba si el resultado es null. Si el resultado es null, entonces la secuencia no tuvo coincidencias. Si la secuencia tuvo coincidencias, retorna un arreglo. Si exsiten grupos (especificados como conjuntos de paréntesis) en la expresión regular, entonces los contenidos de cada uno serán retornados en el arreglo. El elemento[0] de una coincidencia de expresión regular retorna el string coincidente, y el grupo de coincidencia empieza en el elemento[1] (el primer grupo es [1], el segundo es [2], etc).", + "params": ["String: el String a ser buscado", + "String: la expresión regular a ser usada para buscar coincidencias"], + "returns": "Arreglo: arreglo de Strings encontrados" + }, + "matchAll": { + "description": "Esta función es usada para aplicar una expresión regular a una porción de texto, y retorna una lista de grupos coincidentes (elementos encontrados entre paréntesis) como un arreglo de Strings bidimensional. Si no existen coincidencias, se retorna el valor null. Si no se especifican grupos en la expresión regular, pero la secuencia coincide, un arreglo de dos dimensiones es retornado, pero es de largo 1. Para usar la función, primero comprueba si el resultado es null. Si el resultado es null, entonces la secuencia no tuvo coincidencias. Si la secuencia tuvo coincidencias, retorna un arreglo 2D. Si exsiten grupos (especificados como conjuntos de paréntesis) en la expresión regular, entonces los contenidos de cada uno serán retornados en el arreglo. El elemento[i][0] de una coincidencia de expresión regular retorna el string coincidente completo, y el grupo de coincidencia empieza en el elemento[i][1] (el primer grupo es [i][1], el segundo es [i][2], etc).", + "params": ["String: el String a ser buscado", + "String: la expresión regular a ser usada para buscar coincidencias"], + "returns": "Arreglo: arreglo 2D de Strings encontrados" + }, + "nf": { + "description": "Función de utilidad para formatear números a strings. Existen dos veriones: una para formatear floats, y una para formatear enteros. Los valores de los dígitos y los parámetros left y right siempre deben ser enteros positivos", + "params": ["Número|Arreglo: el número a formatear", + "Número: número de dígitos a la izquierda del punto decimal", + "Número: número de dígitos a la derecha del punto decimal"], + "returns": "String|Arreglo: String formateada" + }, + "nfc": { + "description": "Función de utilidad para formatear números en strings y poner las comas apropiadas para señalar múltiplos de mil. Hay dos versiones: una para números enteros y otra para arreglos de enteros. El valor del parámetro right debe siempre ser un entero positivo.", + "params": ["Número|Arreglo: el número a formatear", + "Número: número de dígitos a la derecha del punto decimal"], + "returns": "String|Arreglo: String formateada" + }, + "nfp": { + "description": "Función de utilidad para formatear números en strings. Similar a nf() pero pone un signo + en frente de los números positivos y un signo - en frente de números negativos. Hay dos versiones, una para formatear floats y otra para formatear enteros. Los valores de los parámetros left y right deben siempre ser enteros positivos.", + "params": ["Número|Arreglo: el número a formatear", + "Número: número de dígitos a la izquierda del punto decimal", + "Número: número de dígitos a la derecha del punto decimal"], + "returns": "String|Arreglo: String formateada" + }, + "nfs": { + "description": "Función de utilidad para formatear números en strings. Similar a nf() pero pone un espacio en frente de los números positivos y un signo - en frente de números negativos. Hay dos versiones, una para formatear floats y otra para formatear enteros. Los valores de los parámetros left y right deben siempre ser enteros positivos.", + "params": ["Número|Arreglo: el número a formatear", + "Número: número de dígitos a la izquierda del punto decimal", + "Número: número de dígitos a la derecha del punto decimal"], + "returns": "String|Arreglo: String formateada" + }, + "split": { + "description": "La función split usa String.split(), corta un String en pedazos usando un caracter o String como delimitador. El parámetro delim especifica el caracter o caracteres que marcan los bordes entre cada pieza. Un arreglo String[] es retornado, que contiene cada una de las piezas. La función splitTokens() funciona de forma similar, excepto que divide usango un rango de caracteres en vez de usar un caracter o una secuencia de caracteres específicos.", + "params": ["String: el String a ser dividido", + "String: el String usado para separar los datos"], + "returns": "Arreglo: arreglo de Strings" + }, + "splitTokens": { + "description": "La función splitTokens() divide un String en uno o varios caracteres delimitadores o tokens. El parámetro delim especifica el o los caracteres a ser usados como borde. Si no se especifican caracteres delim, cualquier caracter tipo whitespace será usado para dividir. Los caracteres whitespace incluyen tabulación (\t), nueva línea (\n), retorno de carro (\r), entrada de formulario (\f), y espacio.", + "params": ["String: el String a ser dividido", + "String: lista de Strings individuales que serán usados como separadores"], + "returns": "Arreglo: arreglo de Strings" + }, + "trim": { + "description": "Remueve caracteres tipo whitespace (espacio en blanco) del comienzo y el final de un String. En adición a los caracteres estámdar de whitespace como espacio, retorno de carro y tabulación, esta función también remueve el caracter Unicode nbsp.", + "params": ["String|Arreglo: un String o arreglo de Strings a ser recortados."], + "returns": "String|Arreglo: un String o arreglo de Strings recortados." + }, + "camera": { + "description": "Define la posición de la cámara", + "params": ["Número: valor de la posición de la cámara en el eje x", + "Número: valor de la posición de la cámara en el eje y", + "Número: valor de la posición de la cámara en el eje z"], + "returns": "p5: el objeto p5" + }, + "perspective": { + "description": "Define la perspectiva de la cámara", + "params": ["Número: frustum del campo de visión vertical de la cámara, de abajo hacia arriba, en grados", + "Número: frustum de la relación de aspecto de la cámara", + "Número: frustum del largo del plano cercano", + "Número: frustum del largo del plano lejano"], + "returns": "p5: el objeto p5" + }, + "ortho": { + "description": "Define la cámara ortogonal", + "params": ["Número: define el frustum del plano izquierdo de la cámara", + "Número: define el frustum del plano derecho de la cámara", + "Número: define el frustum del plano inferior de la cámara", + "Número: define el frustum del plano superior de la cámara", + "Número: define el frustum del plano cercano de la cámara", + "Número: define el frustum del plano lejano de la cámara"], + "returns": "p5: el objeto p5" + }, + "ambientLight": { + "description": "Crea una luz ambiente con color", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", + "Número: opcional, valor de verde o saturación", + "Número: opcional, valor de azul o brillo", + "Número: opcional, valor de opacidad"], + "returns": "el objeto p5" + }, + + "directionalLight": { + "description": "Crea una luz direccional con color y dirección", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", + "Número: opcional, valor de verde o saturación", + "Número: opcional, valor de azul o brillo", + "Número: opcional, valor de opacidad", + "Número|p5.Vector: dirección del eje x o un p5.Vector", + "Número: opcional, dirección del eje y", + "Número: opcional, dirección del eje z"], + "returns": "el objeto p5" + }, + "pointLight": { + "description": "Crea una luz puntual con color y posición", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", + "Número: opcional, valor de verde o saturación", + "Número: opcional, valor de azul o brillo", + "Número: opcional, valor de opacidad", + "Número|p5.Vector: dirección del eje x o un p5.Vector", + "Número: opcional, dirección del eje y", + "Número: opcional, dirección del eje z"], + "returns": "p5: el objeto p5" + }, + "normalMaterial": { + "description": "Material normal para geometría. Puedes ver todos los posibles materiales en este ejemplo (TODO).", + "returns": "p5: el objeto p5" + }, + "texture": { + "description": "Textura para geometría. Puedes ver todos los posibles materiales en este ejemplo (TODO).", + "params": ["p5.Image|p5.MediaElement|p5.Graphics: gráfica bidimensional para hacer render como textura."], + "returns": "p5: el objeto p5" + }, + "ambientMaterial": { + "description": "Material ambiente para geometría con un color dado. Puedes ver todos los posibles materiales en este ejemplo (TODO).", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color), o arreglo de color, o String de color CSS", + "Número: opcional, valor de verde o saturación", + "Número: opcional, valor de azul o brillo", + "Número: opcional, valor de opacidad"], + "returns": "p5: el objeto p5" + }, + "specularMaterial": { + "description": "Material espejo para geometría con un color dado. Puedes ver todos los posibles materiales en este ejemplo (TODO).", + "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color), o arreglo de color, o String de color CSS", + "Número: opcional, valor de verde o saturación", + "Número: opcional, valor de azul o brillo", + "Número: opcional, valor de opacidad"], + "returns": "p5: el objeto p5" + }, + "p5.RendererGL": { + "description": "TODO", + "returns": "p5: el objeto p5" + }, + "p5.Shader": { + "description": "Clase Shader para el modo WEBGL", + "params": ["p5.RendererGL: una instancia de p5.RendererGL que servirá de contexto GL para este nuevo p5.Shader", + "String: código fuente para el vertex shader (en forma de string)", + "String: código fuente para el fragment shader (en forma de string)"], + "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."] + } + }, + "p5.Image": { + "loadPixels": { + "description": "blah", + "params": ["Numero: blah", + "Numero: blah"], + "returns": "TODO" + } + }, + "p5.Element": { + "description": "Clase base para todos los elementos añadidos al bosuqejo, incluyendo lienzo, buffers de gráficas, y otros elementos HTML. Los métodos en azul están incluidos en la funcionalidad base, los métodos en marrón son añadidos con la biblioteca p5.dom. No se ejecutan directamente, pero los objetos p5.Element son creados llamando a las funciones createCanvas(), createGraphics(), o en la biblioteca p5.dom, createDiv, createImg, createInput, etc.", + "params": ["String: node DOM envolvente.", + "Objeto: puntero a instancia p5."], + "returns": "TODO" + } +} diff --git a/src/templates/pages/reference/index.hbs b/src/templates/pages/reference/index.hbs index ec36711d21..d8e96686c1 100644 --- a/src/templates/pages/reference/index.hbs +++ b/src/templates/pages/reference/index.hbs @@ -41,7 +41,7 @@ slug: reference/ var translations; $(document).ready(function() { - var langs = ['es', 'zh-Hans']; + var langs = ['es', 'ko', 'zh-Hans']; var routes = window.location.pathname.split('/'); var lang = routes[1]; if (langs.indexOf(lang) != -1) { From 4c05f07a5b2f308e084eeaf8aa89334fecdd3d6d Mon Sep 17 00:00:00 2001 From: Yeseul Song Date: Sun, 7 Apr 2019 17:56:58 -0400 Subject: [PATCH 02/36] Adding first push of korean translations --- src/data/ko.yml | 290 ++++++++++++++++++------------------- src/data/reference/ko.json | 167 ++++++++++++--------- 2 files changed, 240 insertions(+), 217 deletions(-) diff --git a/src/data/ko.yml b/src/data/ko.yml index 901cd08c33..b757af284c 100644 --- a/src/data/ko.yml +++ b/src/data/ko.yml @@ -1,43 +1,43 @@ -Home: "Home" -Download: "Download" -Start: "Start" -Reference: "Reference" -Libraries: "Libraries" -Learn: "Learn" -Examples: "Examples" -Books: "Books" -Community: "Community" -Contribute: "Contribute" -Forum: "Forum" +Home: "홈" +Download: "다운로드" +Start: "시작하기" +Reference: "레퍼런스" +Libraries: "라이브러리" +Learn: "학습" +Examples: "예제" +Books: "관련 책" +Community: "커뮤니티" +Contribute: "기여하기" +Forum: "포럼" -footer1: "p5.js was created by " -footer2: " and is developed by a community of collaborators, with support from the " -footer3: " and " -footer4: "Identity and graphic design by " +footer1: "p5.js는 " +footer2: "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 " +footer3: " 과 " +footer4: "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 : " -tagline1: "Processing fun times JavaScript quirkiness" -tagline2: "Processing simplicity times JavaScript flexibility" -tagline3: "Processing intuition times JavaScript power" -tagline4: "Processing creativity times JavaScript dynamism" -tagline5: "Processing community times JavaScript community" -tagline6: "the power of Processing times the reach of JavaScript" +tagline1: "Processing의 즐거움에 JavaScript의 매력을 곱하다" +tagline2: "Processing의 간명함에 JavaScript의 유연성을 곱하다" +tagline3: "Processing의 직관성에 JavaScript의 강력함을 곱하다" +tagline4: "Processing의 창조성에 JavaScript의 활력을 곱하다" +tagline5: "Processing 커뮤니티에 JavaScript 커뮤니티를 곱하다" +tagline6: "Processing의 강력함에 JavaScript의 범용성을 곱하다" home: - Download: "Download" - Start: "Start" - Reference: "Reference" - Libraries: "Libraries" - Learn: "Learn" - Community: "Community" - p1x1: "안녕하세요! p5.js is a JavaScript library that starts with the original goal of " - p1x2: ", to make coding accessible for artists, designers, educators, and beginners, and reinterprets this for today's web." - p2x1: "Using the original metaphor of a software sketchbook, p5.js has a full set of drawing functionality. However, you're not limited to your drawing canvas, you can think of your whole browser page as your sketch! For this, p5.js has addon" - libraries: " libraries" - p2x2: " that make it" - interact: " easy to interact" - p2x3: " with other HTML5 objects, including text, input, video, webcam, and sound." - p3x1: "p5.js is a new interpretation, not an emulation or port, and it is in active development." - p3x2: "Try it out now in the new p5.js Web Editor!" + Download: "다운로드" + Start: "시작하기" + Reference: "레퍼런스" + Libraries: "라이브러리" + Learn: "학습" + Community: "커뮤니티" + p1x1: "안녕하세요! p5.js는 " + p1x2: "의 목표를 지키고 이를 온라인 공간으로 확장하고자 시작된 자바스크립트 라이브러리로, 예술가, 디자이너, 교육자, 초보자를 위해 만들어졌습니다. " + p2x1: "마치 다양한 미술 도구로 스케치북에 그림을 그리듯이, p5.js를 이용하면 인터넷 브라우저의 '캔버스(canvas)'를 스케치북 삼아 그림을 그릴 수 있습니다. 뿐만 아니라, p5.js의 추가 " + libraries: " 라이브러리" + p2x2: "를 이용하면 텍스트, 입력값, 비디오, 웹캠, 소리와 같은 HTML5 오브젝트를 " + interact: "쉽게 다루고 " + p2x3: " , '캔버스'를 너머 인터넷 브라우저 자체를 당신의 스케치북으로 삼을 수 있습니다." + p3x1: "새로운 해석을 제안하는 p5.js는 지금도 활발하게 개발 중인 프로젝트입니다." + p3x2: "새로운 p5.js 웹에디터를 지금 바로 체험해보세요!" sketch_by: "by" sketch_info: "CC Fest! November 10 @ NYU ITP" sketch_info_link: "http://ccfest.rocks/" @@ -49,70 +49,70 @@ copyright: copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited." get started: - get-started-title: "Get Started" - get-started1: "This page walks you through setting up a p5.js project and making your first sketch." - get-started2: "If you'd like to start with the new " - get-started3: "p5.js Web Editor" - get-started4: ", you can jump down to" - get-started5: "Your First Sketch" - download-title: "Download and File Setup" - download1: "The easiest way to start is by using the empty example that comes with the " + get-started-title: "시작하기" + get-started1: "본 페이지는 p5.js 프로젝트를 셋업하고 나의 첫 스케치를 만드는 방법을 소개합니다." + get-started2: "" + get-started3: "p5.js 웹에디터" + get-started4: "를 사용한다면, 아래 두 항목를 생략하고 이곳으로 건너뛰세요:" + get-started5: "첫 스케치 만들기" + download-title: "다운로드, 파일 셋업" + download1: "가장 쉬운 방법은 " download2: "p5.js complete" - download3: " download." - download4: "If you look in index.html, you'll notice that it links to the file p5.js. If you would like to use the minified version (compressed for faster page loading), change the link to p5.min.js." - download5: "Alternatively, you can link to a p5.js file hosted online. All versions of p5.js are stored in a CDN (Content Delivery Network). You can see a history of these versions here: " - download6: ". In this case you can change the link to:" - download7: "A sample HTML page might look like this:" - download8: "You can also start with this template from " + download3: "와 함께 제공되는 빈 예제파일을 이용하는 것입니다." + download4: "index.html 파일을 살펴보세요. index.html 파일이 p5.js 링크를 포함하고 있죠? 만약 빠른 로딩을 위해 압축된 간략 버전을 이용하고 싶다면, 아래와 같이 p5.js 링크를 p5.min.js로 변경하면 됩니다." + download5: "혹은, 온라인에 저장된 p5.js 파일에 링크를 하는 방법도 있습니다. p5.js의 모든 버전은 CDN (Content Delivery Network)에 저장되어 있으며, 버전들의 히스토리는 이곳에서 보실 수 있습니다: " + download6: ". 이 방법을 따르는 경우, 링크를 다음과 같이 변경하세요:" + download7: "아래는 HTML 페이지 샘플입니다:" + download8: "위 HTML 페이지 템플릿을 코드펜(codepen)에 붙여넣어 프로젝트를 시작하는 것도 한 방법입니다: " download9: "." - environment-title: "Environment" - environment1: "You can use the " + environment-title: "개발환경" + environment1: "어떠한 것이든, 당신이 선호하는 " environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor" - environment2: " code editor " - environment3: "of your choice. Instructions for getting set up with " - environment4: " are included below, other good editor options include " - environment5: " and " - environment6: "If you are a screen reader user and not using the p5 web editor, you may want to use " - environment7: " or " - environment8: "Open Sublime. Go to the File menu and choose Open... and choose the folder that your html and js files are located in. On the left sidebar, you should now see the folder name at the top, with a list of the files contained in the folder directly below." - environment9: "Click on your sketch.js file and it will open on the right where you can edit it. " - environment10: "p5 starter code opened up in sublime editor." - environment11: "Open the index.html file in your browser by double clicking on it in your file manager or type:" + environment2: "코드 에디터" + environment3: "를 사용하면 됩니다. 아래에 " + environment4: "에서 세팅하는 경우에 대한 설명이 있습니다. " + environment5: " 과 " + environment6: "또한 추천할만한 에디터입니다. 당신이 스크린리더 유저인데 p5 웹에디터를 이용하지 않는다면, 다음의 에디터들을 고려해보세요: " + environment7: " 나 " + environment8: "먼저, Sublime 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, 당신의 html 파일과 js 파일이 위치한 폴더를 선택하세요. 폴더 이름과 폴더에 포함된 파일 리스트가 왼쪽 사이드바에 보일 것입니다" + environment9: "sketch.js 파일을 선택하면, 오른쪽 편집 영역에서 파일이 열립니다. " + environment10: "Sublime 에디터에서 p5 템플릿 코드를 편집중인 화면" + environment11: "index.html 파일을 브라우저에서 열어볼까요? 파일 관리 시스템에서 index.html 파일을 더블클릭하거나 브라우저 주소창에 다음을 입력하세요:" environment12: "file:///the/file/path/to/your/html" - environment13: " in the address bar to view your sketch." - your-first-sketch-title: "Your First Sketch" - your-first-sketch-intro1: "Processing users may want to check out the " + environment13: "" + your-first-sketch-title: "나의 첫 스케치" + your-first-sketch-intro1: "Processing 사용자라면, 다음의 페이지를 읽어보세요: " your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition" - your-first-sketch-intro3: "Processing transition tutorial" - your-first-sketch-intro4: "In your editor, type the following:" - your-first-sketch2: "This line of code means \"draw an ellipse, with the center 50 pixels over from the left and 50 pixels down from the top, with a width and height of 80 pixels\"." - your-first-sketch3: "Save your sketch and refresh your page view in your browser. If you've typed everything correctly, you'll see this appear in the display window:" - your-first-sketch4: "Note: If you are using a screen reader, you must either turn on the accessible outputs in the p5 online editor, outside the editor you must add the accessibility library in your html. To learn about " - your-first-sketch5: "using p5 with a screen reader click here" - your-first-sketch6: " and to learn more about " - your-first-sketch7: "the accessibility library here" - your-first-sketch8: "canvas has a circle of width and height 50 at position 80 x and 80 y" - your-first-sketch9: "If you didn't type it correctly, you might not see anything. If this happens, make sure that you've copied the example code exactly: the numbers should be contained within parentheses and have commas between each of them, and the line should end with a semicolon." - your-first-sketch10: "One of the most difficult things about getting started with programming is that you have to be very specific about the syntax. The browser isn't always smart enough to know what you mean, and can be quite fussy about the placement of punctuation. You'll get used to it with a little practice. Depending on the browser you are using, you can also see errors by looking at the JavaScript \"console\". In Chrome, for example, this is under View > Developer > JavaScript Console." - your-first-sketch11: "Next, we'll skip ahead to a sketch that's a little more exciting. Delete the text from the last example, and try this:" - your-first-sketch12: "This program creates a canvas that is 640 pixels wide and 480 pixels high, and then starts drawing white circles at the position of the mouse. When a mouse button is pressed, the circle color changes to black. We'll explain more about the elements of this program in detail later. For now, run the code, move the mouse, and click to experience it." - your-first-sketch13: "canvas has multiple circles drawn on it following the path of the mouse" - what-next-title: "What Next?" - processing-transition1: "Read the " + your-first-sketch-intro3: "Processing에서 p5.js로 이전하기 튜토리얼" + your-first-sketch-intro4: "에디터에 다음을 입력하세요:" + your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다. \"왼쪽 위 모서리에서 아래로 50px, 오른쪽으로 50px 떨어진 위치를 중심으로 하는 타원을 그린다. 타원의 폭과 높이는 동일하게 80px로 한다.\"" + your-first-sketch3: "스케치 저장 후, 브라우저 페이지에서 새로고침을 해보세요. 입력한 코드에 문제가 없는 한, 다음과 같은 화면을 보실겁니다:" + your-first-sketch4: "주의: 스크린리더를 사용하는 경우, p5 웹에디터에서 Accessibile Outputs를 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: " + your-first-sketch5: "스크린리더에서 p5를 사용하는 방법" + your-first-sketch6: ", " + your-first-sketch7: "접근성 라이브러리란?" + your-first-sketch8: "캔버스에 폭과 높이가 50인 타원이 x 80, y 80의 위치에 그려져있다" + your-first-sketch9: "코드를 제대로 입력하지 않았다면, 화면에 아무것도 나타나지 않을 수 있습니다. 이러한 경우, 예제 코드를 정확하게 따라 썼는지 확인하세요. 숫자는 괄호 안에 포함하되 각 숫자는 쉼표로 구분해야 하고, 각 라인은 세미콜론을 끝나야 합니다." + your-first-sketch10: "프로그래밍을 시작할 때 가장 어려운 것 중 하나는 문법이 매우 까다롭다는 점입니다. 브라우저는 사용자가 의미하는 바가 무엇인지 이해할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감합니다. 처음에는 이런 점들이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바스크립트 '콘솔'을 제공합니다. 크롬의 경우, 보기 > 개발자 > 자바스크립트 콘솔을 클릭해 '콘솔'을 활성화하할 수 있습니다." + your-first-sketch11: "이제 한층 더 재미있는 스케치를 만들 차례입니다다. 지난 예제의 코드를 삭제하고 다음의 코드를 입력해 보세요:" + your-first-sketch12: "이 프로그램은 폭이 640px이고 높이가 480인 캔버스를 생성하고, 마우스 커서 위치에서 흰 원을 그리기 시작합니다. 마우스 버튼을 누르고 있을 때는 원의 색이 검정색으로 바뀝니다. 마우스 위치에 대한 설명은 추후에 더 하기로 하고, 일단 여기서는 코드를 실행하고 마우스를 움직이고 클릭하며 스케치의 변화를 살펴보세요." + your-first-sketch13: "캔버스에 마우스 궤적을 따라 여러개의 원이 그려져있다" + what-next-title: "다음 단계" + processing-transition1: "Processing을 p5.js로 전환하려면 어떻게 해야하며, 둘이 어떻게 다른지 궁금하다면, " processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition" - processing-transition3: "Processing transition tutorial" - processing-transition4: " to learn how to convert from Processing to p5.js, and the main differences between them." - reference1: "View the " - reference2: " reference" - reference3: " for full documentation." - learn1: "Check out the " - learn2: "learn" - learn3: " page and " - learn4: "examples" - learn5: " page for more." - learn6: "If you wish to use p5 with a screenreader, check out the " - learn7: "p5 with a screenreader tutorial" - book1: "Parts of this tutorial were adapted from the book, Getting Started with p5.js, by Lauren McCarthy, Casey Reas, and Ben Fry, O'Reilly / Make 2015. Copyright " + processing-transition3: "Processing에서 p5.js로 이전하기 튜토리얼" + processing-transition4: "을 읽어보세요." + reference1: "p5.js에 대한 전체 다큐멘테이션을 보려면, " + reference2: "레퍼런스" + reference3: "를 읽어보세요." + learn1: "더 많은 정보가 필요하다면, " + learn2: "학습" + learn3: " 페이지와 " + learn4: "예제" + learn5: " 페이지를 살펴보세요." + learn6: "스크린리더에서 p5를 사용하고 싶다면, 다음 페이지를 읽어보세요: " + learn7: "스크린리더에서 p5 사용하기 튜토리얼" + book1: "본 튜토리얼의 일부는 다음의 책에서 발췌하였습니다: Getting Started with p5.js, by Lauren McCarthy, Casey Reas, and Ben Fry, O'Reilly / Make 2015. Copyright " book2: 2015 Lauren McCarthy, Casey Reas, and Ben Fry. All rights reserved. download: @@ -386,59 +386,59 @@ libraries: create-your-own4: "If you have created a library and would like to have it included on this page, submit this form!" community: - community-title: "Community" - community-statement-title: "p5.js Community Statement" - community-statement1: "p5.js is a community interested in exploring the creation of art and design with technology." - community-statement2: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners." - community-statement3: "We like these hashtags: #noCodeSnobs (because we value community over efficiency), #newKidLove (because we all started somewhere), #unassumeCore (because we don't assume knowledge), and #BlackLivesMatter (because of course)." - in-practice-title: "In practice:" - in-practice1: " We are not code snobs. We do not assume knowledge or imply there are things that somebody should know. " - in-practice2: "We insist on actively engaging with requests for feedback regardless of their complexity." - in-practice3: "We welcome newcomers and prioritize the education of others. We strive to approach all tasks with the enthusiasm of a newcomer. Because we believe that newcomers are just as valuable in this effort as experts." - in-practice4: "We consistently make the effort to actively recognize and validate multiple types of contributions." - in-practice5: "We are always willing to offer help or guidance." - in-times-conflict-title: "In times of conflict:" - in-times-conflict1: "We listen." - in-times-conflict2: "We clearly communicate while acknowledging other's feelings." - in-times-conflict3: "We admit when we're wrong, apologize, and accept responsibility for our actions." - in-times-conflict4: "We are continuously seeking to improve ourselves and our community." - in-times-conflict5: "We keep our community respectful and open." - in-times-conflict6: "We make everyone feel heard." - in-times-conflict7: "We are mindful and kind in our interactions." - in-the-future-title: "In the future:" - in-the-future1: "The future is now." - contribute-title: "Contribute" - contribute1: "Our community is always looking for enthusiasts to help in all different ways." - develop-title: "Develop." + community-title: "커뮤니티" + community-statement-title: "p5.js 커뮤니티 성명서" + community-statement1: "p5.js는 기술을 재료로 예술과 디자인을 창조하는데 관심이 있는 커뮤니티입니다." + community-statement2: "우리는 다양한 성 정체성(gender identity), 젠더 표현(gender expression), 성적 지향(sexual orientation), 인종, 민족성, 언어, 사회성, 크기, 능력, 계급, 종교, 문화, 하위문화, 정치적 성향, 나이, 기술적 숙련도, 직업, 배경을 가진 사람들의 공동체이자 연대입니다. 우리는 당신의 참여를 환영하며 독려합니다. 모든 사람이 우리 커뮤니티에 활발히 참여할만한 시간, 경제적 수단, 능력이 있는 것이 아니라는 점을 알고 있지만요. 우리는 모두 배우는 과정에 있습니다." + community-statement3: "우리가 좋아하는 해시태그는 #noCodeSnobs (우리는 효율성보다 커뮤니티를 우위에 두니까요), #newKidLove (누구나 언젠가는 초보니까요), #unassumeCore (상대가 어떠한 것을 알고 있다고 섣불리 가정하지 않습니다), and #BlackLivesMatter (말할 필요도 없이 중요한 사실이죠) 입니다." + in-practice-title: "행동지침:" + in-practice1: "우리는 잘난체하는 프로그래머들이 아닙니다. 우리는 상대가 이미 어떠한 것을 알고 있다고 섣불리 가정하거나 모든 사람이 반드시 알아야 할 지식이 있다고 생각하지 않습니다. " + in-practice2: "피드백이 필요한 경우가 있다면 언제든 적극적으로 응합니다." + in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또한, 우리는 모든 과업을 대할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에서, 초보자는 숙련자만큼이나 중요한 존재입니다. " + in-practice4: "우리는 모든 형태의 이바지를 적극적으로 알아차리고 인증합니다." + in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다." + in-times-conflict-title: "갈등이 있을때는 우리는:" + in-times-conflict1: "서로의 생각에 귀 기울입니다. " + in-times-conflict2: "명확하게 의사를 전달하되, 상대의 감정을 배려합니다. " + in-times-conflict3: "잘못한 경우에는 잘못을 인정하고, 용서를 구하며, 행동에 대한 책임을 집니다. " + in-times-conflict4: "우리 자신과 커뮤니티를 향상시키기 위해 지속적으로 노력합니다. " + in-times-conflict5: "서로 존중하며 개방된 자세를 유지합니다. " + in-times-conflict6: "모든 사람의 의견을 존중하고 경청합니다. " + in-times-conflict7: "사려깊고 친절한 태도로 대화합니다." + in-the-future-title: "미래에는:" + in-the-future1: "지금이 바로 미래입니다." + contribute-title: "기여하기" + contribute1: "우리는 언제나 열정있는 당신의 도움을 환영합니다." + develop-title: "개발. " develop1: "GitHub" - develop2: " is the main place where code is collected, issues are documented, and discussions about code are had. Check out the " - develop3: " development tutorial" - develop4: " to get started, or " - develop5: "create your own library." - document-title: "Document." - document1: " Everyone loves documentation. Help is needed " - document2: "porting examples" - document3: ", and" - document4: " adding documentation" - document5: ", and creating tutorials." - teach-title: "Teach." - teach1: " Teach a workshop, a class, a friend, a collaborator! Tag @p5xjs on Twitter and we will do our best to share what you're doing." - create-title: "Create." - create1: " p5.js is looking for designers, artists, coders, programmers to bring your creative and amazing work to show on the front page and inspire other people. Submit your work to " + develop2: "는 코드가 수집되고, 문제나 쟁점들이 문서화되며, 코드 관련 논의가 진행되는 곳입니다. p5.js 개발에 기여하려면 " + develop3: "개발 튜토리얼" + develop4: "을 참고하거나, " + develop5: "당신의 라이브러리를 만들어보세요." + document-title: "다큐멘테이션. " + document1: "다큐멘테이션만큼 유용한게 없죠! 현재 도움이 필요한 부분은 " + document2: "예제를 이전하는 작업" + document3: "," + document4: "다큐멘테이션을 추가하는 작업" + document5: ", 그리고 튜토리얼을 만드는 작업입니다." + teach-title: "가르치기. " + teach1: "워크샵, 수업, 친구, 협업자에게 p5.js를 가르치는 것도 좋은 기여 방법입니다. 트위터에서 @p5xjs를 소환하면 당신이 어떠한 수업을 하는지 공유할게요." + create-title: "만들기. " + create1: "p5.js는 사용자들에게 영감을 줄 수 있는 작업을 웹사이트 첫 페이지에 게재합니다. 디자이너, 예술가, 코더, 프로그래머- 누구든 좋습니다. 당신이 만든 창의적인 작업을 다음의 메일주소로 제출하세요: " create2: "hello@p5js.org" create3: "." - donate-title: "Donate." - donate1: " p5.js is free and open source and made by artists. Help support the development of p5.js through a donation to the " - donate2: "Processing Foundation" - donate3: "." - contributors-conference-title: "Contributors Conference" - contributors-conference1: "In 2015, p5.js held its first-ever " - contributors-conference2: "contributors conference" - contributors-conference3: ". Artists, designers, developers, educators, and more joined forces at " - contributors-conference4: "CMU's Studio for Creative Inquiry" - contributors-conference5: " to make p5.js awesome." - mailing-list-title: "Mailing list" - mailing-list-1: "Enter your email address to receive occasional updates from the Processing Foundation." + donate-title: "기부하기. " + donate1: "p5.js는 예술가들에 의해 만들어진 오픈소스 프로젝트로, 사용자들에게 무료로 제공됩니다. p5.js의 개발을 지원하려면, " + donate2: "프로세싱 파운데이션" + donate3: "에 기부해 주세요. " + contributors-conference-title: "기여자 컨퍼런스" + contributors-conference1: "2015년에, p5.js는 첫 " + contributors-conference2: "기여자 컨퍼런스" + contributors-conference3: "를 개최했습니다. 예술가, 디자이너, 개발자, 교육자를 포함한 다수의 사람들이 " + contributors-conference4: "카네기멜론대학의 Studio for Creative Inquiry" + contributors-conference5: "에서 만나 p5.js를 더 멋지게 만들기 위한 논의와 활동들을 하였습니다." + mailing-list-title: "이메일 Mailing list" + mailing-list-1: "프로세싱 재단으로부터 새소식을 받아보려면, 아래에 이메일 주소를 입력하세요." people-title: "People" people1: "blah" @@ -498,4 +498,4 @@ contributors-conference: contributors-conference-support6: "Thank you!" reference: - Reference: "Reference" \ No newline at end of file + Reference: "Reference" diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json index cdd17d07e3..034232cde2 100644 --- a/src/data/reference/ko.json +++ b/src/data/reference/ko.json @@ -1,8 +1,8 @@ { - "Home": "Inicio", - "Download": "Descargar", - "Start": "Empezar", - "Reference": "Referencia", + "Home": "홈", + "Download": "다운로드", + "Start": "시작하기", + "Reference": "레퍼런스", "reference-tagline": "la intuición de Processing x el poder de JavaScript", "reference-search": "Busca en la API", "reference-menu-home": "Inicio", @@ -19,31 +19,31 @@ "reference-description2": "o", "reference-description3": "Puedes descargar una versión de la referencia", "reference-description4": "aquí", - "reference-contribute1": "Si ves algún error o tienes alguna sugerencia", - "reference-contribute2": "por favor dinos", + "reference-contribute1": "잘못된 부분이나 제안사항이 있다면 ", + "reference-contribute2": "알려주세요.", "reference-error1": "¿Encontraste algún error?", "reference-error2": "está documentado y definido en", "reference-error3": "Por favor siéntete libre de ", "reference-error4": "editar el archivo", "reference-error5": "y de indicar un pull request.", "reference-example": "Ejemplo", - "reference-description": "Descripción", + "reference-description": "설명", "reference-extends": "Extiende", "reference-parameters": "Parámetros", "reference-syntax": "Sintaxis", "reference-returns": "Retorna", - "footer1": "p5.js fue creado por ", - "footer2": " y es desarrollado por una comunidad de colaboradores, con apoyo de ", - "footer3": " y ", - "footer4": "Identidad y diseño gráfico por ", - "Libraries": "Bibliotecas", - "Learn": "Aprender", - "Examples": "Ejemplos", - "Books": "Libros", - "Community": "Comunidad", - "Contribute": "Contribuir", - "Forum": "Foro", - "h1": "Referencia", + "footer1": "p5.js는 ", + "footer2": "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 ", + "footer3": " 과 ", + "footer4": "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 :", + "Libraries": "라이브러리", + "Learn": "학습", + "Examples": "예제", + "Books": "관련 책", + "Community": "커뮤니티", + "Contribute": "기여하기", + "Forum": "포럼", + "h1": "레퍼런스", "Color": "Color", "Shape": "Forma", "Creating & Reading": "Creación y lectura", @@ -77,22 +77,22 @@ "Input": "Entrada", "Output": "Salida", "Table": "Tabla", - "Time & Date": "Tiempo & Fecha", + "Time & Date": "날짜와 시간", "XML": "XML", - "Math": "Matemáticas", - "Calculation": "Cálculo", - "Noise": "Ruido", + "Math": "수학", + "Calculation": "계산", + "Noise": "노이즈", "Trigonometry": "Trigonometría", - "Typography": "Tipografía", - "Font": "Fuente", + "Typography": "타이포그래피", + "Font": "폰트", "Lights, Camera": "Luces, cámara", - "Camera": "Cámara", - "Lights": "Luces", + "Camera": "카메라", + "Lights": "빛", "Material": "Materiales", - "footer1": "p5.js fue creado por ", - "footer2": " y es desarrollado por una comunidad de colaboradores, con apoyo de ", - "footer3": " y ", - "footer4": "Identidad y diseño gráfico por ", + "footer1": "p5.js는 ", + "footer2": "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 ", + "footer3": " 과 ", + "footer4": "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 :", "p5": { "alpha": { "description": "Extrae el valor de alpha de un color o de un arreglo de pixeles.", @@ -151,71 +151,94 @@ "returns": "the p5 object" }, "background": { - "description": "La función background() define el color usado como fondo del lienzo p5.js. El fondo por defecto es gris claro. Esta función es típicamente usada dentro de draw() para despejar o borrar la ventana mostrada al inicio de cada cuadro, pero puede ser usada dentro de setup() para definir el fondo en el primer cuadro de la animación o si el fondo solo necesita ser definido una vez.", - "params": ["Color: cualquier valor creado con la función color()", - "Número: opacidad del fondo relativo al rango de color actual (por defecto es 0-100)", - "colorstring: string de color, formatos posibles: enteros rgb() o rgba(), porcentajes rgb() o rgba(), hex 3 dígitos, hex 6 dígitos", - "Número: especifica un valor entre blanco y negro", - "Número: valor de rojo o hue (dependiendo del modo de color actual)", - "Número: valor de verde o saturación (dependiendo del modo de color actual)", - "Número: valor de azul o brillo (dependiendo del modo de color actual)", - "p5.Image: imagen creada con loadImage() o createImage(), para ser definida como fondo (debe ser del mismo tamaño que la ventana del bosquejo)"], + "description": "background() 함수는 p5.js 캔버스 배경 색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 한번만 설정하면 되는 경우에 setup() 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.", + "params": ["p5.Color: color() 함수를 통해 만들어진 값", + "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex", + "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", + "숫자: 흑백 채도를 설정함", + "숫자: 선택한 컬러모드에 따라, red값 혹은 hue값", + "숫자: 선택한 컬러모드에 따라, green값 혹은 saturation값", + "숫자: 선택한 컬러모드에 따라, blue값 혹은 brightness값", + "숫자 배열[]: red, green blud와 투명도를 포함한 배열", + "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 창과 같은 사이즈여야 함)"], "returns": "the p5 object" }, "clear": { - "description": "Borra los pixeles del buffer. Esta función solo funciona en objetos p5.Canvas creados con la función createCanvas(); no funcionará con la ventana principal. A diferencia del contexto principal de gráficas, los pixeles en las áreas gráficas adicionales creadas con createGraphics() pueden ser entera o parcialmente transparentes. Esta función borra todo para hacer los pixeles 100% transparentes.", + "description": "버퍼 내의 픽셀을 클리어합니다. 본 함수는 createCanvas() 함수로 만들어진 p5.Canvas 오브젝트에만 적용되며, 메인 디스플레이 윈도우에 사용할 수는 없습니다. 메인 그래픽 영역에서와 다르게, createGraphics()를 이용해 생성한 추가 그래픽 영역 내에 있는 픽셀은 완전히 혹은 부분적으로 투명하게 만들 수 있습니다. clear() 함수는 모든 픽셀을 100% 투명하게 만듭니다.", "returns": "the p5 object" }, "colorMode": { - "description": "colorMode() cambia la manera en que p5.js interpreta los datos de color. Por defecto, los parámetros de fill(), stroke(), background() y color() son definidos por valores entre 0 y 255 en modo RGB. Esto es equivalente a definir el modo de color según colorMode(RGB, 255). Definir el modo de color en colorMode(HSB) permite usar el sistema HSB. Por defecto, este modo de color es colorMode(HSB, 360, 100, 100, 1). También se puede usar HSL. Nota: los objetos de color existentes recuerdan el modo en que fueron creados, por lo que puedes cambiar el modo como quieras, sin afectar su apariencia.", - "params": ["Constante: RGB o HSB, correspondiente a Rojo/Verde/Azul o tinte/saturación/brillo (o luminosidad)", - "Número: rango de rojo o tinte, dependiendo del modo de color actual, o rango para todos los valores", - "Número: rango de verde o saturación, dependiendo del modo de color actual.", - "Número: rango de azul o brillo/luminosidad, dependiendo del modo de color actual.", - "Número: rango de transparencia alpha"], + "description": "colorMode()는 p5.js가 색 데이터를 해석하는 방식을 결정합니다. fill(), stroke(), background(), color()의 매개변수의 초기값은 RGB 컬러모드이며, 범위는 0에서 255까지, 즉 colorMode(RGB, 255) 입니다. colorMode(HSB)로 설정하는 경우 HSB 컬러 시스템을 사용할 수 있는데, 초기값은 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 컬러모드를 HSL을 설정하는 것도 가능합니다. 참고: 이미 존재하는 컬러 오브젝트들은 자신이 생성되었을 당시의 모드를 기억합니다. 따라서, 이미 존재하는 컬러 오브젝트에 영향을 미치지 않으면서 컬러모드는 바꾸는 것이 가능합니다.", + "params": ["상수(Constante): RGB (Red/Green/Blue), HSB (Hue/Saturation/Brightness), HSL (Hue/Saturation/Lightness) 중 하나", + "숫자: 현재 컬러모드에 따라 red 혹은 hue 범위", + "숫자: 현재 컬러모드에 따라 green 혹은 saturation 범위.", + "숫자: 현재 컬러모드에 따라 blue 혹은 brightness/lightness 범위.", + "숫자: 투명도 범위"], "returns": "the p5 object" }, "fill": { - "description": "Define el color usado para el relleno de figuras geométricas. Por ejemplo, si ejecutas fill(204, 102, 0), todas las figuras a continuación tendrán relleno naranja. Este color es especificado en términos de color RGB o HSB, dependiendo del modo de color según colorMode() (el dominio de color por defecto es RGB, con cada valor en el rango entre 0 y 255). Si se provee un argumento tipo string, los tipos RGB, RGBA y CSS hexadecimal están soportados. Un objeto Color p5 puede ser provisto para definir el color del relleno.", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo, tinte (dependiendo del modo de color actual), o arreglo de color, o string de color CSS.", - "Número: valor de verde o saturación (dependiendo del modo de color actual)", - "Número: valor de azul o brillo (dependiendo del modo de color actual)", - "Número: opacidad del fondo"], + "description": "도형을 칠할 색을 선택합니다. 예를 들어 fill(204, 102, 0)을 실행하면 해당되는 모든 도형들의 색이 주황색으로 바뀝니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.", + "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값", + "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", + "문자열: 문자열로 된 색상값", + "숫자: 흑백 채도를 설정함", + "숫자 배열[]: red, green blud와 투명도를 포함한 배열", + "p5.Color" + ], "returns": "the p5 object" }, + + "p5.Color: color() 함수를 통해 만들어진 값", + "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex", + "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", + "숫자: 흑백 채도를 설정함", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값", + "숫자 배열[]: red, green blud와 투명도를 포함한 배열", + "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 창과 같은 사이즈여야 함)"], "noFill": { - "description": "Deshabilita el relleno de figuras geométricas. Si tanto noStroke() como noFill() son ejecutados, nada será dibujado en pantalla.", + "description": "도형에 색을 채우지 않도록 설정합니다. noStroke() 과 noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.", "returns": "the p5 object" }, "noStroke": { - "description": "Deshabilita el dibujo de los trazos (bordes). Si tanto noStroke() como noFill() son ejecutados, nada será dibujado en pantalla.", + "description": "선이나 윤곽선을 그리지 않도록 설정합니다. noStroke() 과 noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.", "returns": "the p5 object" }, "stroke": { - "description": "Define el color usado para dibujar líneas y bordes de figuras. Este color especificado en términos de color RGB o HSB, dependiendo del modo de color actual según colorMode() (el dominio de color por defecto es RGB, con cada valor en el rango entre 0 y 255). Si se provee un argumento tipo string, los tipos RGB, RGBA y CSS hexadecimal están soportados. Un objeto Color p5 puede ser provisto para definir el color del trazado.", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo, tinte (dependiendo del modo de color actual), o arreglo de color, o string de color CSS.", - "Número: valor de verde o saturación (dependiendo del modo de color actual)", - "Número: valor de azul o brillo (dependiendo del modo de color actual)", - "Número: opacidad del fondo"], + "description": "선을 그리거나 도형 윤곽선 색을 설정합니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.", + "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값", + "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값", + "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", + "문자열: 문자열로 된 색상값", + "숫자: 흑백 채도를 설정함", + "숫자 배열[]: red, green blud와 투명도를 포함한 배열", + "p5.Color"], "returns": "el objeto p5" }, "arc": { - "description": "Dibuja un arco en la pantalla. Si se llama con solo a, b, c, d, start y stop, el arco se dibuja como un pastel abierto. Si el modo se provee, el arco será dibujado abierto, o como acorde, o como pastel, según lo especificado. El origen puede ser cambiado con la función ellipseMode(). Nota que si dibujas un círculo completo (ej: 0 a TWO_PI) aparecerá en blanco, porque 0 y TWO_PI son la misma posición en el círculo unitario. La mejor manera de manejar esto es usar la función ellipse() para una elipse cerrada, y la función arc() para generar solo secciones de una elipse.", - "params": ["Número: coordenada x del arco de elipse.", - "Número: coordenada y del arco de elipse.", - "Número: ancho del arco de elipse.", - "Número: altura del arco de elipse.", - "Número: ángulo inicial del arco de elipse.", - "Número: ángulo final del arco de elipse.", - "Constante: parámetro opcional para determinar la manera de dibujar el arco."], + "description": "화면에 호를 그립니다. 모드 선택 없이 x, y, w, h, 시작, 끝만을 지정하면 호는 열린 파이조각 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫혀진 반원(CHORD), 닫혀진 파이조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 본 함수를 이용해 시작점을 0, 끝점을 TWO_PI로 설정해 원 전체를 그리려 시도하면, 시작점과 끝점이 같기 때문에 아무것도 그려지지 않습니다. 원 전체를 그릴때는 ellipse() 함수를, 원 일부를 그릴 때는 arc() 함수를 이용하세요.", + "params": ["숫자: 호를 포함하는 원의 x 좌표", + "숫자: 호를 포함하는 원의 y 좌표", + "숫자: 호를 포함하는 원의 너비", + "숫자: 호를 포함하는 원의 높이", + "숫자: 시작점의 각도로, 호도(radians)로 설정", + "숫자: 끝점의 각도로, 호도(radians)로 설정", + "상수: 호를 그리는 방식을 설정함. CHORD, PIEC, OPEN 중 선택. 필수 변수는 아니며 필요한 경우에만 사용하면 됨.", + "숫자: WEBGL 모드에서만 사용하며, 호의 윤곽선을 구성하는 점(vertices)의 숫자를 지정한다. 필수 변수는 아니며 필요한 경우에만 사용하면 됨. 초기값은 25이다.", + ], "returns": "the p5 object" }, "ellipse": { - "description": "Dibuja una elipse (óvalo) en la pantalla. Una elipse con igual ancho y altura es un círculo. Por defecto, los primeros dos parámetros definen la ubicación, y el tercero y cuarto definen el ancho y altura de la figura. Si no especifica una altura, el valor del ancho es usado como ancho y altura. El origen puede ser cambiado con la función ellipseMode().", - "params": ["Número: coordenada x de la elipse.", - "Número: coordenada y de la elipse.", - "Número: ancho de la elipse.", - "Número: altura de la elipse."], + "description": "스크린에 타원을 그립니다. 너비와 높이가 같은 경우에는 원이 그려집니다. 첫 두 변수는 위치를, 세번째 네번째 변수는 도형의 너비와 높이를 설정합니다. 높이를 설정하지 않으면 너비 값이 높이로도 사용됩니다. 너비나 높이를 음수로 입력하면, 자동적으로 절대값이 사용됩니다. 원 시작점을 원의 중심으로 둘지의 여부는 ellipseMode() 함수를 이용해 변경할 수 있습니다.", + "params": ["숫자: 원의 x 좌표", + "숫자: 원의 y 좌표", + "숫자: 원의 너비", + "숫자: 원의 높이", + "정수: 원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WEGBL 모드용)"], "returns": "the p5 object" }, "line": { From acae5166c690acd607994a771fa14c9a87902226 Mon Sep 17 00:00:00 2001 From: Yeseul Song Date: Mon, 15 Apr 2019 00:02:07 -0400 Subject: [PATCH 03/36] Adding Korean translations for the navigation --- src/data/ko.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/ko.yml b/src/data/ko.yml index b757af284c..f58f06fcd0 100644 --- a/src/data/ko.yml +++ b/src/data/ko.yml @@ -498,4 +498,4 @@ contributors-conference: contributors-conference-support6: "Thank you!" reference: - Reference: "Reference" + Reference: "레퍼런스" From a95d8a909b1b61b85cd837f770301cdd1cd611f9 Mon Sep 17 00:00:00 2001 From: Yeseul Song Date: Mon, 15 Apr 2019 00:05:33 -0400 Subject: [PATCH 04/36] Adding second push of korean translations Korean translations completed for: circle() line() point() quad() rect() square() triangle() preload() setup() draw() remove() noLoop() loop() push() pop() redraw() createCanvas() loadImage() image() --- src/data/reference/ko.json | 301 ++++++++++++++++--------------------- 1 file changed, 131 insertions(+), 170 deletions(-) diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json index 034232cde2..96d35c4668 100644 --- a/src/data/reference/ko.json +++ b/src/data/reference/ko.json @@ -4,34 +4,34 @@ "Start": "시작하기", "Reference": "레퍼런스", "reference-tagline": "la intuición de Processing x el poder de JavaScript", - "reference-search": "Busca en la API", - "reference-menu-home": "Inicio", - "reference-menu-download": "Descargar", - "reference-menu-get-started": "Empezar", - "reference-menu-reference": "Referencia", - "reference-menu-libraries": "Bibliotecas", - "reference-menu-learn": "Aprender", - "reference-menu-examples": "Ejemplos", - "reference-menu-books": "Libros", - "reference-menu-community": "Comunidad", - "reference-menu-forum": "Foro", - "reference-description1": "¿No encuentras lo que buscas? Quizás debas revisar en", - "reference-description2": "o", - "reference-description3": "Puedes descargar una versión de la referencia", - "reference-description4": "aquí", - "reference-contribute1": "잘못된 부분이나 제안사항이 있다면 ", - "reference-contribute2": "알려주세요.", - "reference-error1": "¿Encontraste algún error?", - "reference-error2": "está documentado y definido en", - "reference-error3": "Por favor siéntete libre de ", - "reference-error4": "editar el archivo", - "reference-error5": "y de indicar un pull request.", - "reference-example": "Ejemplo", + "reference-search": "API 검색", + "reference-menu-home": "홈", + "reference-menu-download": "다운로드", + "reference-menu-get-started": "시작하기", + "reference-menu-reference": "레퍼런스", + "reference-menu-libraries": "라이브러리", + "reference-menu-learn": "학습", + "reference-menu-examples": "예제", + "reference-menu-books": "관련 책", + "reference-menu-community": "커뮤니티", + "reference-menu-forum": "포럼", + "reference-description1": "찾는 항목이 이곳에 없다면, 다음의 페이지를 살펴보세요:", + "reference-description2": " 혹은 ", + "reference-description3": "오프라인 버전의 레퍼런스는 다음 링크에서 다운받을 수 있습니다: ", + "reference-description4": "레퍼런스 다운로드", + "reference-contribute1": "잘못된 부분이나 제안사항이 있다면", + "reference-contribute2": "알려주세요", + "reference-error1": "오타나 버그를 발견했다구요?", + "reference-error2": "관련 문서는 이곳에 있습니다: ", + "reference-error3": "p5.js에 기여하고 싶다면, ", + "reference-error4": "파일을 수정하고", + "reference-error5": "pull request 해주세요!", + "reference-example": "예제", "reference-description": "설명", - "reference-extends": "Extiende", - "reference-parameters": "Parámetros", - "reference-syntax": "Sintaxis", - "reference-returns": "Retorna", + "reference-extends": "확장", + "reference-parameters": "변수", + "reference-syntax": "문법", + "reference-returns": "리턴", "footer1": "p5.js는 ", "footer2": "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 ", "footer3": " 과 ", @@ -44,55 +44,6 @@ "Contribute": "기여하기", "Forum": "포럼", "h1": "레퍼런스", - "Color": "Color", - "Shape": "Forma", - "Creating & Reading": "Creación y lectura", - "Setting": "Configuración", - "2D Primitives": "Primitivas 2D", - "Attributes": "Atributos", - "Curves": "Curvas", - "Vertex": "Vértices", - "3D Models": "Modelos 3D", - "3D Primitives": "Primitivas 3D", - "Constants": "Constantes", - "Structure": "Estructura", - "Environment": "Ambiente", - "DOM": "DOM", - "Rendering": "Render", - "Transform": "Transformar", - "Data": "Datos", - "Dictionary": "Diccionario", - "Array Functions": "Funciones de arreglo", - "Conversion": "Conversión", - "String Functions": "Funciones de String", - "Events": "Eventos", - "Acceleration": "Aceleración", - "Keyboard": "Teclado", - "Mouse": "Ratón", - "Touch": "Tacto", - "Image": "Imagen", - "Loading & Displaying": "Cargar & Mostrar", - "Pixels": "Pixeles", - "IO": "Entrada y salida", - "Input": "Entrada", - "Output": "Salida", - "Table": "Tabla", - "Time & Date": "날짜와 시간", - "XML": "XML", - "Math": "수학", - "Calculation": "계산", - "Noise": "노이즈", - "Trigonometry": "Trigonometría", - "Typography": "타이포그래피", - "Font": "폰트", - "Lights, Camera": "Luces, cámara", - "Camera": "카메라", - "Lights": "빛", - "Material": "Materiales", - "footer1": "p5.js는 ", - "footer2": "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 ", - "footer3": " 과 ", - "footer4": "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 :", "p5": { "alpha": { "description": "Extrae el valor de alpha de un color o de un arreglo de pixeles.", @@ -184,21 +135,10 @@ "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", "문자열: 문자열로 된 색상값", "숫자: 흑백 채도를 설정함", - "숫자 배열[]: red, green blud와 투명도를 포함한 배열", - "p5.Color" - ], + "숫자 배열[]: red, green blue와 투명도를 포함한 배열", + "p5.Color" ], "returns": "the p5 object" }, - - "p5.Color: color() 함수를 통해 만들어진 값", - "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex", - "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)", - "숫자: 흑백 채도를 설정함", - "숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값", - "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값", - "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값", - "숫자 배열[]: red, green blud와 투명도를 포함한 배열", - "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 창과 같은 사이즈여야 함)"], "noFill": { "description": "도형에 색을 채우지 않도록 설정합니다. noStroke() 과 noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.", "returns": "the p5 object" @@ -217,7 +157,7 @@ "숫자: 흑백 채도를 설정함", "숫자 배열[]: red, green blud와 투명도를 포함한 배열", "p5.Color"], - "returns": "el objeto p5" + "returns": "the p5 object" }, "arc": { "description": "화면에 호를 그립니다. 모드 선택 없이 x, y, w, h, 시작, 끝만을 지정하면 호는 열린 파이조각 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫혀진 반원(CHORD), 닫혀진 파이조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 본 함수를 이용해 시작점을 0, 끝점을 TWO_PI로 설정해 원 전체를 그리려 시도하면, 시작점과 끝점이 같기 때문에 아무것도 그려지지 않습니다. 원 전체를 그릴때는 ellipse() 함수를, 원 일부를 그릴 때는 arc() 함수를 이용하세요.", @@ -228,8 +168,7 @@ "숫자: 시작점의 각도로, 호도(radians)로 설정", "숫자: 끝점의 각도로, 호도(radians)로 설정", "상수: 호를 그리는 방식을 설정함. CHORD, PIEC, OPEN 중 선택. 필수 변수는 아니며 필요한 경우에만 사용하면 됨.", - "숫자: WEBGL 모드에서만 사용하며, 호의 윤곽선을 구성하는 점(vertices)의 숫자를 지정한다. 필수 변수는 아니며 필요한 경우에만 사용하면 됨. 초기값은 25이다.", - ], + "숫자: WEBGL 모드에서만 사용하며, 호의 윤곽선을 구성하는 점(vertices)의 숫자를 지정한다. 필수 변수는 아니며 필요한 경우에만 사용하면 됨. 초기값은 25이다."], "returns": "the p5 object" }, "ellipse": { @@ -241,54 +180,79 @@ "정수: 원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WEGBL 모드용)"], "returns": "the p5 object" }, + "circle": { + "description": "화면에 원을 그립니다. 원은 단순한 단일폐곡선으로, 중심점으로부터 같은 좌표에 위치한 점들의 집합입니다. 원은 너비와 높이가 동일한 타원으로 ellipse() 함수를 이용해 그리는 것도 가능합니다. 이 경우 타원의 너비와 높이는 원의 지름과 동일합니다. 본 함수의 첫번째 두번째 변수는 원의 중심점을, 세번째 변수는 지름을 설정합니다.", + "params": ["숫자: 원 중심점의 x 좌표", + "숫자: 원 중심점의 y 좌표", + "숫자: 원의 지름"], + "returns": "the p5 object" + }, "line": { - "description": "Dibuja una línea (un camino directo entre dos puntos) en la pantalla. La versión de line() con cuatro parámetros dibuja la línea en 2D. Para darle color a una línea, usa la función stroke(). Una línea no puede ser rellenada, por lo que la función fill() no afectará el color de una línea. Las líneas 2D son dibujadas con una ancho de un pixel por defecto, pero esto puede ser cambiado con la función strokeWeight().", - "params": ["Número: coordenada x del primer punto.", - "Número: coordenada y del primer punto.", - "Número: coordenada x del segundo punto.", - "Número: coordenada y del segundo punto."], + "description": "화면에 선, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하는 경우 이차원 평면에 선을 그립니다. 선의 색을 지정하려면 stroke() 함수를 이용하세요. 선은 면은 가지고 있지 않기 때문에 면 색을 채우는 fill() 함수는 적용되지 않습니다. 선의 굵기 초기값은 1픽셀이며 이를 변경하기 위해서는 strokeWeight() 함수를 이용합니다.", + "params": ["숫자: 첫번째 점의 x 좌표", + "숫자: 첫번째 점의 y 좌표", + "숫자: 두번째 점의 x 좌표", + "숫자: 첫번째 점의 y 좌표", + "숫자: 첫번째 점의 z 좌표", + "숫자: 두번째 점의 z 좌표"], "returns": "the p5 object" }, "point": { "description": "Dibuja un punto, una coordenada en el espacio de un pixel de dimensión. El primer parámetro es la coordenada horizontal del punto, el segundo valor es la coordenada vertical del punto. El color del punto es determinado por el trazado actual con la función stroke().", - "params": ["Número: coordenada x.", - "Número: coordenada y ."], + "params": ["숫자: x 좌표", + "숫자: y 좌표", + "숫자: z 좌표 (WEBGL 모드 사용시)"], "returns": "the p5 object" }, "quad": { - "description": "Dibuja un cuadrilátero, un polígono de cuatro lados. Es similar a un rectángulo, pero los ángulos entre sus bordes no están limitados a noventa grados. El primer par de parámetros (x1, y1) corresponde a las coordenadas del primer vértice y los pares siguientes deben seguir en el mismo orden, según las manecillas del reloj o en contra, alrededor de la figura a definir.", - "params": ["Número: coordenada x del primer punto.", - "Número: coordenada y del primer punto.", - "Número: coordenada x del segundo punto.", - "Número: coordenada y del segundo punto.", - "Número: coordenada x del tercer punto.", - "Número: coordenada y del tercer punto.", - "Número: coordenada x del cuarto punto.", - "Número: coordenada y del cuarto punto."], + "description": "네모꼴을 그립니다. 네모꼴은 4개의 변을 가진 다각형으로, 직사각형과 유사해 보이지만 직사각형과 다르게 변 사이의 각도가 90도로 고정되어 있지 않습니다. 첫 한 쌍의 변수는 첫 꼭지점을 설정하며 뒤따르는 다른 쌍의 변수들은 시계방향이나 반시계방향으로 차례대로 꼭지점을 설정합니다. z 변수는 WEBGL모드에서 quad() 함수를 사용하는 경우에만 적용됩니다.", + "params": ["숫자: 첫번째 꼭지점의 x 좌표", + "숫자: 첫번째 꼭지점의 y 좌표", + "숫자: 두번째 꼭지점의 x 좌표", + "숫자: 두번째 꼭지점의 y 좌표", + "숫자: 세번째 꼭지점의 x 좌표", + "숫자: 세번째 꼭지점의 y 좌표", + "숫자: 네번째 꼭지점의 x 좌표", + "숫자: 네번째 꼭지점의 y 좌표", + "숫자: 첫번째 꼭지점의 z 좌표", + "숫자: 두번째 꼭지점의 z 좌표", + "숫자: 세번째 꼭지점의 z 좌표", + "숫자: 네번째 꼭지점의 z 좌표"], "returns": "the p5 object" }, "rect": { - "description": "Dibuja un rectángulo en la pantalla. Un rectángulo es una figura de cuatro lados con cada ángulo interior de noventa grados. Por defecto, los dos primeros parámetros definen la ubicación de la esquina superior izquierda, el tercero el ancho y el cuarto la altura. La manera en que estos parámetros son interpretados, sin embargo, puede ser cambiado con la función rectMode(). Los parámetros quinto, sexto, séptimo y octavo, si son especificados, determinan el radio de la esquina superior derecha, superior izquierda, inferior derecha e inferior izquierda, respectivamente. Si se omite un parámetro de radio de esquina, se usa el radio especificado por el valor anterior en la lista.", - "params": ["Número: coordenada x del rectángulo.", - "Número: coordenada y del rectángulo.", - "Número: ancho del rectángulo.", - "Número: altura del rectángulo.", - "Número: radio opcional de la esquina superior izquierda.", - "Número: radio opcional de la esquina superior derecha.", - "Número: radio opcional de la esquina inferior derecha.", - "Número: radio opcional de la esquina inferior izquierda.", - "Número:", - "Número:"], - "returns": "el objeto p5" + "description": "화면에 직사각형을 그립니다. 직사각형은 변이 네개이면서 모든 각도가 90도인 도형입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 사각형의 너비를, 네번째 변수는 높이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 다섯번째, 여섯번째, 일곱번째, 여덟번째 변수를 입력하는 경우 각각의 숫자는 차계로 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 지정합니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.", + "params": ["숫자: 직사각형의 x 좌표값", + "숫자: 직사각형의 y 좌표값", + "숫자: 직사각형의 너비", + "숫자: 직사각형의 높이", + "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "정수: x 방향의 segment 수 (WEBGL 모드에서 사용)", + "정수: y 방향의 segment 수 (WEBGL 모드에서 사용)"], + "returns": "the p5 object" + }, + "square": { + "description": "화면에 정사각형을 그립니다. 정사각형은 변이 네개이면서 모든 각도가 90도이며 네 변의 길이가 같은 도형입니다. 정사격형은 사실상 rect() 함수로도 그릴 수 있는 도형으로, 너비와 높이가 모두 s로 같은 직사각형인 셈입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 한 변의 길이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 네번째, 다섯번째, 여섯번째, 일곱번째 변수를 입력해 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 각각 지정할 수 있습니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.", + "params": ["숫자: 정사각형의 x 좌표값", + "숫자: 정사각형의 y 좌표값", + "숫자: 정사각형 한 변의 길이", + "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.", + "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력."], + "returns": "the p5 object" }, "triangle": { - "description": "Un triángulo es un plano creado por la conexión de tres puntos. Los primeros dos argumentos especifican el primer punto, los parámetros centrales especifican el segundo punto, y los dos últimos parámetros especifican el tercer punto.", - "params": ["Número: coordenada x del primer punto.", - "Número: coordenada y del primer punto.", - "Número: coordenada x del segundo punto.", - "Número: coordenada y del segundo punto.", - "Número: coordenada x del tercer punto.", - "Número: coordenada y del tercer punto."], + "description": "삼각형은 세 점을 이어 만든 평면입니다. 첫 두 변수는 첫번째 꼭지점을, 가운데 두 변수는 두번째 꼭지점을, 마지막 두 변수는 세번째 꼭지점을 지저합니다.", + "params": ["숫자: 첫번째 꼭지점의 x 좌표", + "숫자: 첫번째 꼭지점의 y 좌표", + "숫자: 두번째 꼭지점의 x 좌표", + "숫자: 두번째 꼭지점의 y 좌표", + "숫자: 세번째 꼭지점의 x 좌표", + "숫자: 세번째 꼭지점의 y 좌표"], "returns": "the p5 object" }, "ellipseMode": { @@ -537,40 +501,40 @@ "returns": "el objeto p5" }, "preload": { - "description": "La función preload() es ejecutada antes de setup(), es usada para manejar la carga asíncrona de archivos externos. Si se define una función preload(), setup() esperará hasta que las llamadas a funciones load hayan terminado. Solo se deben incluir instrucciones de carga dentro de preload() (loadImage, loadJSON, loadFont, loadStrings, etc).", - "returns": "el objeto p5" + "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일들의 비동기성 로딩을 blocking 방식으로 처리하기 위해 사용됩니다. preload() 함수를 사용하면 setup() 함수는 preload() 함수 내에 포함된 모든 로딩이 끝난 후에 실행됩니다. preload() 함수 내에는 loadImage, loadJSON, loadFont, LoadString과 같은 로딩 호출만 포함해야 합니다. 비동기적 로딩을 원하는 경우에는 setup() 함수 내 혹은 다른 적절한 위치에서 로딩하되, 콜백 매개변수와 함께 사용합니다. 로딩 페이지에는 'loading...' 문구가 표시됩니다. 로딩 페이지 문구나 디자인을 변경하려면 id가 'p5_loading'인 HTML 요소를 해당 페이지에 삽입하세요.", + "returns": "the p5 object" }, "setup": { - "description": "La función setup() es ejecutada una vez, cuando el programa empieza. Es usada para definir propiedades iniciales como amaño de la pantalla y color de fondo y para cargar medios como imágenes y tipografías cuando el programa empieza. Solo puede haber una función setup() en cada programa y no debe ser llamada después de su ejecución inicial. Nota: las variables declaradas dentro de setup() no son accesibles dentro de otras funciones, como draw().", - "returns": "el objeto p5" + "description": "setup()은 화면의 크기나 배경 색과 같은 환경적 속성, 이미지나 서체와 같은 미디어 로딩을 정의하는데 사용하는 함수로, 프로그램을 시작 시 단 한 번만 실행됩니다. setup()은 한 프로그램 내 하나만 존재하며, 한번 실행된 이후에 다시 호출되어서는 안됩니다. 주의: setup() 내에서 정의된 변수는 draw()를 포함한 다른 함수에서 접근이 불가함.", + "returns": "the p5 object" }, "draw": { - "description": "La función draw() es ejecutada después de setup(), y ejecuta contínuamente las líneas de código dentro de su bloque hasta que el programa es detenido o se ejecuta la función noLoop(). Notar que si noLoop() es ejecutada dentro de setup(), draw() igualmente será ejecutado una vez antes de parar. La función draw() es ejecutada automáticamente y nunca debiera ser ejecutada explícitamente. Siempre debería ser controlada con noLoop(), redraw() y loop(). Después de que noLoop() detiene la ejecución del código dentro de draw(), redraw() causa que el código dentro de draw() se ejecute una vez, y loop() causa que el código dentro de draw() siga ejecutándose de forma continua. El número de veces que draw() se ejecuta por segundo puede ser controlado con la función frameRate(). Solo puede haber una función draw() en cada bosquejo, y draw() solo debe existir si quieres que el código corra de forma continua, o para procesar eventos como mousePressed(). Algunas veces, podrías querer ejecutar una función draw() vacía, como se mostró en el ejemplo más arriba. Es importante notar que el sistema de coordenadas de dibujo será reiniciado al principio de cada ejecución de la función draw(). Si cualquier transformación es hecha dentro de draw() (por ejemplo: escalar, rotar, trasladar), sus efectos serán anulados al principio de cada ejecución de draw(), así que las transformaciones no se acumulan en el tiempo. Por el otro lado, el estilo aplicado (color de relleno, color de trazado) sí se mantendrá en efecto. ", - "returns": "el objeto p5" + "description": "setup()이 실행된 직후 호출되는 draw()는 프로그램이 종료되거나 noLoop() 함수가 호출될 때까지 계속해서 반복적으로 실행됩니다. 단, noLoop() 함수가 setup() 내에서 호출되는 경우에는 draw() 에 영향을 미치지 않아 실행을 종료시키지 않습니다. draw()는 자동적으로 호출되는 함수이며 절대로 임의로 호출해 사용할 수 없습니다. 대신, draw()는 noLoop(), redraw(), loop()로 조종이 가능합니다. noLoop()는 draw() 실행을 중단하고, redraw()는 draw() 내 코드를 한 번 실행시키며, loop()는 draw() 내 코드를 다시 반복적으로 실행시킵니다. frameRate() 함수를 이용하면 draw()를 일초에 몇 번 실행시킬 것인지 설정할 수 있습니다. draw()는 한 스케치에 꼭 하나만 존재합하며 mousePressed()와 같은 이벤트를 실행하기 위해서는 draw()가 반드시 필요합니다. 또하나 기억해야 할 점은 draw()를 시작할 때 좌표 시스템이 초기화된다는 점입니다. 즉, draw() 내에서 scale, rotate, translate와 같은 좌표 변형을 하는 경우 draw() 시작시 매번 이들이 초기화되기 때문에 변형 상태가 축적되지 않습니다. 한편, fill이나 stroke와 같은 스타일링은 draw() 시작시 초기화되지 않고 유지됩니다", + "returns": "the p5 object" }, "remove": { - "description": "Remueve el bosquejo de p5 completamente. Esto removerá el lienzo y cualquier otro elemento creado por p5.js. También detendrá el bucle de dibujo y desvinculará cualquier propiedad o método global de la ventana. Dejará una variable p5 en caso que quieras crear un nuevo bosquejo p5. Si quieres, puedes definir p5 = null para borrar esta variable.", - "returns": "el objeto p5" + "description": "전체 p5 스케치를 제거합니다. 캔버스를 포함해 p5.js에 의해 생성된 모든 요소를 제거하고, draw loop을 정지시키며 윈도우 전역의 속성과 메소드를 무효화 합니다. 단, 당신이 새로운 p5 스케치를 만들고 싶어할 경우를 대비해 변수 'p5'는 제거하지 않는데, 이마저 제거하고 싶다면 'p5 = null'을 입력하면 됩니다. 이 함수는 p5 라이브러리에 의해 생성된 함수, 변수, 오브젝트만 제거하며 프로그램 내의 다른 변수는 제거하지 않습니다.", + "returns": "the p5 object" }, "noLoop": { - "description": "Detiene la ejecución continua del código de draw() de p5.js. Si se llama a la función loop(), el código dentro de draw() empieza a correr de forma continua nuevamente. Si se usa noLoop() dentro de setup(), debe ser la última línea de código dentro del bloque. Cuando se usa noLoop(), no es posible manipular o acceder a la pantalla dentro de las funciones que manejan eventos como mousePressed() o keyPressed(). En vez de eso, usa estas funciones para llamar a redraw() o loop(), que permitirán la ejecución de draw(), lo que permite el refresco correcto de la pantalla. Esto significa que cuando noLoop() ha sido ejecutado, no se sigue dibujando, y funciones como saveFrame() o loadPixels() no se pueden usar. Notar que si el bosquejo es escalado, redraw() será llamado para actualizar el bosquejo, incluso si noLoop() ha sido ejecutada. Por otro lado, el bosquejo entrará a un estado singular, hasta que loop() sea ejecutado.", - "returns": "el objeto p5" + "description": "draw() 내 코드가 반복적으로 실행되는 것을 정지시킵니다. 정지 후에 다시 코드를 반복적으로 실행시키고 싶다면 loop()를 이용합니다. noLoop()이 setup() 내에서 사용하려면 가장 마지막 줄에 사용합니다. noLoop()이 호출되면 mousePressed()나 keyPressed()와 같은 이벤트 핸들러 함수를 접근하거나 조종할 수 없습니다. 대안으로는 draw()를 실행시킬 수 있는 redraw()나 loop()과 같은 함수를 이용해 화면을 적절히 업데이트하는 방법이 있습니다. noLoop()을 호출한 이후에는 스케치가 진행되지 않으며 saveFrame()이나 loadPixels과 같은 함수를 사용할 수도 없습니다. 주의: 스케치의 사이즈를 재설정(resize)하는 경우에는 noLoop()의 존재여부와 관계없이 redraw()가 자동적으로 호출됩니다. 사이즈 재설정 후 스케치를 업데이트하지 않으면 화면의 요소들이 제대로 보여지지 않기 때문입니다.", + "returns": "the p5 object" }, "loop": { - "description": "Por defecto, p5.js repite de forma continua la función draw(), ejecutado el código dentro de su bloque. Sin embargo, el bucle de dibujo puede ser detenido llamando a la función noLoop(). En ese caso, el bucle de draw() puede ser retomado con loop().", - "returns": "el objeto p5" + "description": "p5.js는 draw() 내 코드를 끊임없이 반복해서 실행합니다. 이를 멈추고싶을 때는 noLoop()를 사용하세요. draw() 반복 실행을 재개하고 싶은 경우에는 loop()을 사용합니다.", + "returns": "the p5 object" }, "push": { - "description": "La función push() graba la configuración actual de estilo de dibujo, y pop() restaura esta configuración. Notar que estas funciones siempre son usadas en conjunto. Permiten cambiar las configuraciones de estilo y transformaciones y luego volver a lo que tenías. Cuando un nuevo estado es iniciado con push(), construye encima de la información actual de estilo y transformación. Las funciones push() y pop() pueden ser embebidas para proveer más control (ver el segundo ejemplo para una demostración). push() almacena información relacionada a la configuración de estado de transformación y de estulo actual, controlada por las siguientes funciones: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading().", - "returns": "el objeto p5" + "description": "push()와 pop()은 항상 함께 사용되는 함수로, push() 함수는 함수 이전에 설정된 드로잉 스타일과 좌표 시스템을 저장하고 pop() 함수는 이 저장값을 복구합니다. 이 함수를 사용하면 스타일과 좌표 시스템을 일시적으로 변경하고 이후 필요한 시점에 본래의 설정값으로 편리하게 되돌아올 수 있습니다. push() 함수를 호출한 이후에 입력하는 설정은 새로운 상태를 정의하며 이 설정은 pop() 함수가 등장하기 전까지 유효합니다. 두번째 예제와 같이 push()와 pop() 함수 세트 내에 다른 push()와 pop() 함수 세트를 내장하는 것도 가능합니다. push() 함수는 다음의 함수가 설정하는 현재의 좌표 시스템과 스타일을 저장합니다: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), texgtAlign(), textFont(), textSize(), textLoading(). WEBGL 모드에서는 다음 함수를 이용해 설정하는 추가적인 스타일도 저장됩니다: setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shineness(), normalMaterial(), shader().", + "returns": "the p5 object" }, "pop": { - "description": "La función push() graba la configuración actual de estilo de dibujo, y pop() restaura esta configuración. Notar que estas funciones siempre son usadas en conjunto. Permiten cambiar las configuraciones de estilo y transformaciones y luego volver a lo que tenías. Cuando un nuevo estado es iniciado con push(), construye encima de la información actual de estilo y transformación. Las funciones push() y pop() pueden ser embebidas para proveer más control (ver el segundo ejemplo para una demostración). push() almacena información relacionada a la configuración de estado de transformación y de estulo actual, controlada por las siguientes funciones: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading()." + "description": "push()와 pop()은 항상 함께 사용되는 함수로, push() 함수는 함수 이전에 설정된 드로잉 스타일과 좌표 시스템을 저장하고 pop() 함수는 이 저장값을 복구합니다. 이 함수를 사용하면 스타일과 좌표 시스템을 일시적으로 변경하고 이후 필요한 시점에 본래의 설정값으로 편리하게 되돌아올 수 있습니다. push() 함수를 호출한 이후에 입력하는 설정은 새로운 상태를 정의하며 이 설정은 pop() 함수가 등장하기 전까지 유효합니다. 두번째 예제와 같이 push()와 pop() 함수 세트 내에 다른 push()와 pop() 함수 세트를 내장하는 것도 가능합니다. push() 함수는 다음의 함수가 설정하는 현재의 좌표 시스템과 스타일을 저장합니다: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), texgtAlign(), textFont(), textSize(), textLoading(). WEBGL 모드에서는 다음 함수를 이용해 설정하는 추가적인 스타일도 저장됩니다: setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shineness(), normalMaterial(), shader()." }, "redraw": { - "description": "Ejecuta una vez el código dentro de la función draw(). Esta función permite al programa actualizar la ventana mostrada solamente cuando es necesario, por ejemplo, cuando un evento registrado por mousePressed() o keyPressed() ocurre. En la estructura de un programa, solo hace sentido llamar a redraw() dentro de eventos como mousePressed(). Esto es porque redraw() no hace que draw() se ejecute de forma inmediata (solo define una indicación de que se necesita un refresco). La función redraw() no funciona de forma correcta cuando se llama dentro de la función draw(). Para habilitar y deshabilitar animaciones, usa las funcioens loop() y noLoop(). Adicionalmente, puedes definir el número de veces que se dibuja por cada llamada a este método. Para esto, añade un entero como parámetro único a la función, que señale cuántas veces se requiere dibujar.", - "params": ["Entero: redibuja n-veces. Por defecto el valor es 1"], - "returns": "el objeto p5" + "description": "draw() 내 코드를 한 번 실행합니다. 본 함수를 이용하면 필요한 경우에만 화면을 업데이트할 수 있습니다. redraw()는 mousePressed()나 keyPressed()에 의해 일어나는 이벤트와 같이 조건적으로 일어나는 이벤트에 사용하면 유용합니다. 이 함수를 어느 위치에 사용하냐구요? redraw()는 draw()를 바로 실행시키는 것이 아니라 단지 업데이트가 필요하다는 표시를 하는 셈이기 때문에, mousePressed()와 같은 이벤트 내에서 호출해야 합니다. redraw() 함수는 draw()함수 내에 사용할 수는 없습니다. 애니메이션의 실행 여부를 조종하고 싶다면 loop()과 noLoop()를 이용하세요. redraw 횟수를 정하는 것도 가능한데, 이를 위해서는 정수를 redraw() 함수의 변수로 입력합니다.", + "params": ["정수: redraw를 n번 실행합니다. n의 초기값은 1입니다."], + "returns": "the p5 object" }, "print": { "description": "La función print() escribe en la consola del navegador. Esta función es a menudo de ayuda para observar los datos que un programa está produciendo. Esta función crea una nueva línea de texto por cada ejecución de la función. Elementos individuales pueden ser separados por comillas ('') y unidos con el operador de adición (+). Aunque print() es similar a console.log(), no llama a console.log() directamente, para simular una manera más simple de entender el comportamiento del programa. Por esto mismo, es más lento. Para resultados más rápidos, usar directamente console.log().", @@ -657,11 +621,10 @@ "returns": "Objeto: parámetros de la URL" }, "createCanvas": { - "description": "Crea un elemento canvas en el documento, y define sus dimensiones medidas en pixeles. Este método debe ser llamado solo una vez al comienzo de la función setup(). Llamar a la función createCanvas() más de una vez en un bosquejo puede resultar en comportamientos impredecibles. Si quieres más de un lienzo donde dibujar, debes usar la función createGraphics() (escondido por defecto, pero puede ser mostrado), Las variables de sistema width (ancho) y height (altura) son definidas por los parámetros pasados a la función. Si createCanvas() no es usado, la ventana tendrá un tamaño por defecto de 100 x 100 pixeles. Para más maneras de posicionar el lienzo, ver la sección de posición del lienzo.", - "params": ["Número: ancho del lienzo", - "Número: altura del lienzo", - "Constante: P2D o WEBGL"], - "returns": "Objeto: lienzo generado" + "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를 참고하세요.", + "params": ["숫자: 캔버스의 너비", + "숫자: 캔버스의 높이", + "상수: P2D 또는 WEBGL"] }, "resizeCanvas": { "description": "Redimensiona el linezo al ancho y la altura dados. El lienzo será borrado y la función draw() será llamada inmediatamente, permitiendo que el bosquejo se ajuste al nuevo lienzo", @@ -987,28 +950,26 @@ "returns": "el objeto p5" }, "loadImage": { - "description": "Carga una imagen desde una ruta de archivo y crea un objeto p5.Image. La imagen puede no estar inmediatamente disponible para render. Si quieres asegurarte que esté lista antes de hacer algo con ella, ubica la función loadImage() dentro de preload(). También puedes proveer una función callback para manejar la imagen cuando esté lista. La ruta a la imagen debe ser relativa al archivo HTML de tu bosquejo. Cargar desde una URL u otra ubicación remota podría estar bloqueado por las opciones de seguridad del navegador.", - "params": ["String: ruta de la imagen a cargar", - "Función(p5.Image): función a ser llamada una vez que la imagen sea cargada. Le será pasado el objeto p5.Image", - "Función(evento): llamada con el evento error si es que la carga de la imagen falla."], - "returns": "el objeto p5" + "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.", + "params": ["문자열: 불러올 이미지 경로", + "함수(p5.Image): 이미지를 불러온 후 호출할 함수", + "함수(Event): 이미지 불러오기를 실패하는 경우에 호출할 함수"] }, "image": { - "description": "Dibuja una imagen en el lienzo principal del bosquejo p5.js.", - "params": ["p5.Image: la imagen a mostrar", - "Número: la coordenada x donde se ubicará la esquina superior de la imagen", - "Número: la coordenada y donde se ubicará la esquina superior de la imagen", - "Número: ancho de la imagen a dibujar", - "Número: altura de la imagen a dibujar", - "Número: la coordenada x en el lienzo de destino donde se ubicará la esquina superior izquierda de la imagen", - "Número: la coordenada y en el lienzo de destino donde se ubicará la esquina superior izquierda de la imagen", - "Número: ancho de la imagen a dibujar en el lienzo de destino", - "Número: altura de la imagen a dibujar en el lienzo de destino", - "Número: la coordenada x de la esquina superior izquierda del subrectángulo de la imagen original a dibujar en el lienzo de destino", - "Número: la coordenada y de la esquina superior izquierda del subrectángulo de la imagen original a dibujar en el lienzo de destino", - "Número: el ancho del subrectángulo de la imagen original a dibujar en el lienzo de destino", - "Número: la altura del subrectángulo de la imagen original a dibujar en el lienzo de destino"], - "returns": "el objeto p5" + "description": "p5.js 캔버스에 이미지를 배치합니다. 본 함수를 사용하는 몇가지 방법을 소개하자면 다음과 같습니다. (1) 가장 간단한 방법은 img, x, y 세 개의 변수를 사용하는 방법입니다. x, y는 이미지의 위치를 지정합니다. (2) 이미지의 크기를 설정하려면 img, x, y와 더불어 이미지의 너비와 높이를 설정하는 두개의 변수를 추가로 사용합니다. (3) 여덟개의 변수를 사용하는 방법입니다. 먼저, 각 변수들을 구별하기 위해 p5.js에서 사용하는 용어를 배워봅시다. 첫번째 용어는 '목적지 사각형(destination rectagle)로, dx, dy 등의 변수가 이에 해당합니다. 두번째 용어는 '원본 이미지(source image)'로, sx, sy등의 변수가 이에 해당합니다. '원본 이미지'의 크기를 설정하면 해당 이미지의 일부만을 디스플레이할 때 유용합니다. 자세한 사항은 아래 도식을 참고하세요.", + "params": ["p5.Image, p5.Element: 디스플레이할 이미지", + "숫자: 왼쪽 위 모서리의 x 좌표", + "숫자: 왼쪽 위 모서리의 y 좌표", + "숫자: 이미지 너비 설정", + "숫자: 이미지 높이 설정", + "숫자: 원본 이미지를 배치할 목적지 사각형의 x 좌표", + "숫자: 원본 이미지를 배치할 목적지 사각형의 y 좌표", + "숫자: 목적지 사각형의 너비", + "숫자: 목적지 사각형의 높이", + "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 x좌표", + "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표", + "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비", + "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"] }, "tint": { "description": "Define el valor de relleno para mostrar imágenes. Las imágenes pueden ser teñidas en colores específicos o hacerse transparentes al incluir un valor alpha. Para aplicar transparencia a una imagen sin afectar su color, usa blanco como color de teñido y especifica un valor alpha. Por ejemplo, tint(255, 128) hará una imagen 50% transparente (asumiendo el rango alpha por defecto entre 0 y 255, el que puede ser modificado con la función colorMode()). El valor del parámetro gris debe ser menor o igual al actual valor máximo según lo especificado por colorMode(). El valor máximo por defecto es 255.", From 084e3e337599b50e1d6f5a6f3f006ae4def5fa58 Mon Sep 17 00:00:00 2001 From: Yeseul Song Date: Mon, 15 Apr 2019 00:15:32 -0400 Subject: [PATCH 05/36] Adding Korean translations for page titles --- src/data/ko.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/ko.yml b/src/data/ko.yml index f58f06fcd0..cbe7ab91c1 100644 --- a/src/data/ko.yml +++ b/src/data/ko.yml @@ -32,7 +32,7 @@ home: p1x1: "안녕하세요! p5.js는 " p1x2: "의 목표를 지키고 이를 온라인 공간으로 확장하고자 시작된 자바스크립트 라이브러리로, 예술가, 디자이너, 교육자, 초보자를 위해 만들어졌습니다. " p2x1: "마치 다양한 미술 도구로 스케치북에 그림을 그리듯이, p5.js를 이용하면 인터넷 브라우저의 '캔버스(canvas)'를 스케치북 삼아 그림을 그릴 수 있습니다. 뿐만 아니라, p5.js의 추가 " - libraries: " 라이브러리" + libraries: "라이브러리" p2x2: "를 이용하면 텍스트, 입력값, 비디오, 웹캠, 소리와 같은 HTML5 오브젝트를 " interact: "쉽게 다루고 " p2x3: " , '캔버스'를 너머 인터넷 브라우저 자체를 당신의 스케치북으로 삼을 수 있습니다." @@ -116,7 +116,7 @@ get started: book2: 2015 Lauren McCarthy, Casey Reas, and Ben Fry. All rights reserved. download: - Download: "Download" + Download: "다운로드" complete-library-title: "Complete Library" p5.js-complete: "p5.js complete" includes-1: "Includes:" @@ -171,7 +171,7 @@ download: support-33: " was founded in 2012 after more than a decade of work with the original Processing software. The Foundation’s mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources." learn: - learn-title: "Learn" + learn-title: "학습" learn1: "These tutorials provide more in-depth or step-by-step overviews of particular topics. Check out the " learn2: "examples page" learn3: "to see short demonstrations of various p5.js topics." @@ -347,7 +347,7 @@ learn: test-tutorial: libraries: - Libraries: "Libraries" + Libraries: "라이브러리" p5.dom: "p5.dom lets you interact with HTML5 objects beyond the canvas, including video, audio, webcam, input, and text." p5.sound: "p5.sound extends p5 with Web Audio functionality including audio input, playback, analysis and synthesis." p5.accessibility: "p5.accessibility makes the p5 canvas more accessible to people who are blind and visually impaired." @@ -443,10 +443,10 @@ community: people1: "blah" books: - books-title: "Books" + books-title: "관련 책" examples: - Examples: "Examples" + Examples: "예제" back-examples: "Back to Examples" Structure: "Structure" Form: "Form" From 7dc8ca97721e2969fda4021ef019d58212bfa346 Mon Sep 17 00:00:00 2001 From: Lauren McCarthy Date: Wed, 17 Apr 2019 19:56:18 +0900 Subject: [PATCH 06/36] updating korean to remove spanish --- src/data/reference/ko.json | 1520 +---------------- .../pages/reference/assets/js/reference.js | 107 +- .../reference/assets/js/reference.js.map | 10 +- src/templates/pages/reference/index.hbs | 7 +- src/templates/partials/i18n.hbs | 3 +- 5 files changed, 123 insertions(+), 1524 deletions(-) diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json index 96d35c4668..90f89d6a8a 100644 --- a/src/data/reference/ko.json +++ b/src/data/reference/ko.json @@ -44,63 +44,52 @@ "Contribute": "기여하기", "Forum": "포럼", "h1": "레퍼런스", + "Color": "Color", + "Shape": "Shape", + "Creating & Reading": "Creating & Reading", + "Setting": "Setting", + "2D Primitives": "2D Primitives", + "Attributes": "Attributes", + "Curves": "Curves", + "Vertex": "Vertex", + "3D Models": "3D Models", + "3D Primitives": "3D Primitives", + "Constants": "Constants", + "Structure": "Structure", + "Environment": "Environment", + "DOM": "DOM", + "Rendering": "Rendering", + "Transform": "Transform", + "Data": "Data", + "Dictionary": "Dictionary", + "Array Functions": "Array Functions", + "Conversion": "Conversion", + "String Functions": "String Functions", + "Events": "Events", + "Acceleration": "Acceleration", + "Keyboard": "Keyboard", + "Mouse": "Mouse", + "Touch": "Touch", + "Image": "Image", + "Loading & Displaying": "Loading & Displaying", + "Pixels": "Pixels", + "IO": "IO", + "Input": "Input", + "Output": "Output", + "Table": "Table", + "Time & Date": "날짜와 시간", + "XML": "XML", + "Math": "수학", + "Calculation": "계산", + "Noise": "노이즈", + "Trigonometry": "Trigonometry", + "Typography": "타이포그래피", + "Font": "폰트", + "Lights, Camera": "Lights, Camera", + "Camera": "카메라", + "Lights": "빛", + "Material": "Material", "p5": { - "alpha": { - "description": "Extrae el valor de alpha de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "el objeto p5" - }, - "blue": { - "description": "Extrae el valor de azul de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "el objeto p5" - }, - "brightness": { - "description": "Extrae el valor de brillo HSB de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "el objeto p5" - }, - "color": { - "description": "Crea colores para ser almacenados en variables del tipo color. Los parámetros son interpretados como valores RGB o HSB, dependiendo del modo actual de color según colorMode)(). El modo por defecto es RGB con valores entre 0 y 255 y, por lo tanto, la función color(255, 204, 0) retorna un color amarillo brillante. Nota que si solo se provee un valor a la función color(), será interpretado como un valor en escala de grises. Añade un segundo valor, y será usado como transparencia alpha. Cuando se especifican tres valores, son interpretados como valores RGB o HSB. Al añadir un cuarto valor se aplica transparencia alpha. Si se provee solo un parámetro de tipo string, será interpretado como un string de color compatible con CSS.Los colores son almacenados como números o arreglos.", - "params": ["Número|String: número especificando el valor entre blanco y negro.", - "Número: valor de alpha relativo al rango de color actual (por defecto es 0-100)", - "Número|String: valor de rojo o tinte relativo al rango de color actual, o un string de color", - "Número: valor de verde o saturación relativo al rango de color actual", - "Número: valor de azul o brillo relativo al rango de color actual"], - "returns": "Arreglo: color resultante" - }, - "green": { - "description": "Extrae el valor de verde de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "the p5 object" - }, - "hue": { - "description": "Extrae el valor de tinte de un color o de un arreglo de pixeles. El tinte (hue) existe en HSB y HSL. Esta función retorna el tinte normalizado HSB que cuando se le provee un objeto de color HSB (o cuando se le provee un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará el tinte normalizado según HSB en otro caso. (Estos valores solo son diferentes si la configuración de valor de tinte máximo de cada sistema es diferente.)", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "the p5 object" - }, - "lerpColor": { - "description": "Mezcla dos colores para encontrar un tercer color según la combinación de ambos. El parámetro amt es la cantidad a interpolar entre los dos valores, donde 0.0 es igual al primer color, 0.1 es muy cercano al primer color, 0.5 está a medio camino entre ambos, etc. Un valor menor que 0 será tratado como 0. Del mismo modo, valores sobre 1 serán tratados como 1. Esto es distinto al comportamiento de lerp(), pero necesario porque de otra manera los números fuera de rango producirían colores no esperados y extraños. La manera en que los colores son interpolados depende del modo de color actual.", - "params": ["Arreglo/Número: interpola desde este color", - "Arreglo/Número: interpola hacia este color", - "Número: número entre 0 y 1"], - "returns": "Arreglo/Número: color interpolado" - }, - "lightness": { - "description": "Extrae el valor de luminosidad HSL de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "the p5 object" - }, - "red": { - "description": "Extrae el valor de rojo de un color o de un arreglo de pixeles.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "the p5 object" - }, - "saturation": { - "description": "Extrae el valor de saturación de un color o de un arreglo de pixeles. La saturación es escalada en HSB y HSL de forma distinta. Esta función retornará la saturación HSB cuando le sea provisto un objeto de color HSB (o cuando le sea provisto un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará saturación HSL.", - "params": ["Objeto: objeto p5.Color o arreglo de pixeles"], - "returns": "the p5 object" - }, "background": { "description": "background() 함수는 p5.js 캔버스 배경 색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 한번만 설정하면 되는 경우에 setup() 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.", "params": ["p5.Color: color() 함수를 통해 만들어진 값", @@ -245,710 +234,12 @@ "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력."], "returns": "the p5 object" }, - "triangle": { - "description": "삼각형은 세 점을 이어 만든 평면입니다. 첫 두 변수는 첫번째 꼭지점을, 가운데 두 변수는 두번째 꼭지점을, 마지막 두 변수는 세번째 꼭지점을 지저합니다.", - "params": ["숫자: 첫번째 꼭지점의 x 좌표", - "숫자: 첫번째 꼭지점의 y 좌표", - "숫자: 두번째 꼭지점의 x 좌표", - "숫자: 두번째 꼭지점의 y 좌표", - "숫자: 세번째 꼭지점의 x 좌표", - "숫자: 세번째 꼭지점의 y 좌표"], - "returns": "the p5 object" - }, - "ellipseMode": { - "description": "Modifica la ubicación de donde las elipses son dibujadas, cambiando la manera en que los parámetros dados a ellipse() son interpretados. El modo por defecto es ellipseMode(CENTER), que interpreta los dos primeros parámetros de ellipse() como el centro de la figura, mientras que los parámetros tercero y cuarto son el ancho y la altura. ellipseMode(RADIUS) también usa los dos primeros parámetros de ellipse() como el punto central de la figura, pero usa los parámetros tercero y cuarto para especificar la mitad del ancho y la altura de la figura. ellipseMode(CORNER) interpreta los dos primeros parámetros de ellipse() como la esquina superior izquierda de la figura, mientras que los parámetros tercero y cuarto son el ancho y la altura. ellipseMode(CORNERS) interpreta los dos primeros parámetros de ellipse() como la ubicación de una esquina del rectángulo contenedor de la elipse, y los parámetros tercero y cuarto como la ubicación de la esquina opuesta. El parámetro debe ser escrito en MAYÚSCULAS porque Javascript es una lenguaje de programación que distingue entre mayúsculas y minúsculas.", - "params": ["Constante: puede ser CENTER, RADIUS, CORNER, o CORNERS."], - "returns": "the p5 object" - }, - "noSmooth": { - "description": "Dibuja las figuras geométricas con bordes no suaves (aliasing). Notar que smooth() está activo por defecto, así que es necesario ejectuar noSmooth() para deshabilitar el suavizado de las figuras geométricas, imágenes y tipografías.", - "returns": "el objeto p5" - }, - "rectMode": { - "description": "Modifica la ubicación en que los rectángulos son dibujados, cambiando la manera en que los parámetros dados a rect() son interpretados. El modo por defecto es rectMode(CORNER), que interpreta los primeros dos parámetros de rect() como la esquina superior izquierda de la figura, mientras que los parámetros tercero y cuarto son su ancho y altura. rectMode(CORNERS) interpreta los dos primeros parámetros de rect() como la ubicación de una esquina, y los parámetros tercero y cuarto como la ubicación de la esquina opuesta. rectMode(CENTER) interpreta los dos primeros parámetros de rect() como el punto central de la figura, mientas que los parámetros tercero y cuarto son su ancho y altura. rectMode(RADIUS) también usa los dos primeros parámetros de rect()= como el punto central de la figura, pero usa los parámetros tercero y cuarto para especificar la mitad del ancho y la altura de la figura. Los parámetros deben ser escritos en MAYÚSCULAS porque Javascript es un lenguaje que distingue entre mayúsculas y minúsculas.", - "params": ["Constante: puede ser CORNER, CORNERS, CENTER, o RADIUS."], - "returns": "the p5 object" - }, - "smooth": { - "description": "Dibuja todas las figuras geométricas con bordes suaves (sin aliasing). smooth() también mejorará la calidad de las imágenes cuyo tamaño ha sido modificado. Notar que smooth() está activo por defecto; noSmooth() puede ser usado para deshabilitar el suavizado de las figuras geométricas, imágenes y tipografía.", - "returns": "the p5 object" - }, - "strokeCap": { - "description": "Define el estilo de rendering de los extremos de las líneas. Estos extremos pueden ser cuadrados, extendidos o redondeados, cada uno de estos especifados con los parámetros correspondientes: SQUARE, PROJECT, y ROUND. El extremo por defecto es redonedeado (ROUND).", - "params": ["Constante: puede ser SQUARE, PROJECT, o ROUND."], - "returns": "the p5 object" - }, - "strokeJoin": { - "description": "Define el estilo de las uniones que conectan segmentos de líneas. Estas uniones pueden ser tipo inglete, biseladas o redondeadas, y especificadas con los parámetros correspondientes: MITER, BEVEL, y ROUND. La unión por defecto es MITER.", - "params": ["Constante: puede ser MITER, BEVEL, o ROUND."], - "returns": "the p5 object" - }, - "strokeWeight": { - "description": "Define el ancho del trazo usado para dibujar líneas, puntos y los bordes de las figuras geométricas. Todos los anchos son medidos en pixeles.", - "params": ["Número: el peso (en pixeles) del trazado"], - "returns": "the p5 object" - }, - "bezier": { - "description": "Dibuja una curva Bezier cúbica en la pantalla. Estas curvas están definidas por una serie de puntos ancla y de control. Los primeros dos parámetros especifican el primer punto ancla y los dos últimos especifican el otro punto ancla, que se convierten en los puntos primero y último de la curva. Los parámetros en el medio especifican los dos puntos de control que definen la forma de la curva. De forma aproximada, los puntos de control atraen la curva hacia ellos. Las curvas Bezier fueron desarrolladas por el ingeniero automotriz Pierre Bezier, y son comúnmente usadas en gráficas computacionales para definir curvas de pendiente suave. Ver también curve().", - "params": ["Número: coordenada x del primer punto ancla", - "Número: coordenada y del primer punto ancla", - "Número: coordenada x del primer punto de control", - "Número: coordenada y del primer punto de control", - "Número: coordenada x del segundo punto de control", - "Número: coordenada y del segundo punto de control", - "Número: coordenada x del segundo punto ancla", - "Número: coordenada y del segundo punto ancla", - "Número: coordenada z del primer punto ancla", - "Número: coordenada z del primer punto de control", - "Número: coordenada z del segundo punto ancla", - "Número: coordenada z del segundo punto de control"], - "returns": "the p5 object" - }, - "bezierPoint": { - "description": "Evalua la curva Bezier en la posición t para los puntos a, b, c, d. Los parámetros a y d son los puntos primero y último de la curva, mientras que b y c son los puntos de control. El parámetro final t varía entre 0 y 1. Esto puede ser realizado una vez con las coordenadas x y una segunda vez con las coordenadas y para obtener la ubicación de la curva Bezier en t.", - "params": ["Número: coordenada del primer punto de la curva", - "Número: coordenada del primer punto de control de la curva", - "Número: coordenada del segundo punto de control de la curva", - "Número: coordenada del segundo punto de la curva", - "Número: valor entre 0 y 1"], - "returns": "el valor de la curva Bezier en la posición t" - }, - "bezierTangent": { - "description": "Evalua la tangente de la curva Bezier en la posición t para los puntos a, b, c, d. Los parámetros a y d son los puntos primero y último de la curva, mientras que b y c son los puntos de control. El parámetro final t varía entre 0 1.", - "params": ["Número: coordenada del primer punto de la curva", - "Número: coordenada del primer punto de control de la curva", - "Número: coordenada del segundo punto de control de la curva", - "Número: coordenada del segundo punto de la curva", - "Número: valor entre 0 y 1"], - "returns": "la tangente en la posición t" - }, - "curve": { - "description": "Dibuja una línea curva en la pantalla entre dos puntos, dados como los cuatro parámetros centrales. Los dos primeros puntos son un punto de control, como si la curva viniera desde este punto, aunque no sea dibujado. Los dos últimos parámetros de forma similar describen el otro punto de control. SE pueden cerar curvas más largas, por medio del posicionamiento de varias funciones curve() juntas o usando curveVertex(). Una función adicional llamada curveTightness() provee control de la calidad visual de la curva. La función curve() es una implementación de la Catmull-Rom spline.", - "params": ["Número: coordenada x del punto de control inicial", - "Número: coordenada y del punto de control inicial", - "Número: coordenada x del primer punto", - "Número: coordenada y del primer punto", - "Número: coordenada x del segundo punto", - "Número: coordenada y del segundo punto", - "Número: coordenada x del punto de control final", - "Número: coordenada y del punto de control final", - "Número: coordenada z del punto de control inicial", - "Número: coordenada z del primer punto", - "Número: coordenada z del segundo punto", - "Número: coordenada z del punto de control final"], - "returns": "Objeto: el objeto p5" - }, - "curveTightness": { - "description": "Modifica la calidad de las formas creadas con curve() y curveVertex(). El parámetro tightness (tirantez) determina cómo la curva calza con los vértices. El valor 0.0 es el valor por defecto (este valor define las curvas Spline Catmull-Rom) y el valor 1.0 conecta todos los puntos con líneas rectas. Valores en el rango entre -5.0 y 5.0 deformarán las curvas pero las dejarán reconocibles, y a medida que los valores crecen en magnitud, se continuarán deformando.", - "params": ["Número: deformación de los vértices originales"], - "returns": "the p5 object" - }, - "curvePoint": { - "description": "Evalua la curva en la posición t para los puntos a, b, c, d. El parámetro t varía entre 0 y 1, los puntos a y d son puntos en la cruva, y b y c son los puntos de control. Esto puede ser hecho una vez con las coordenadas x y una segunda vez con las coordenadas y para obtener la ubicación de la curva en t.", - "params": ["Número: coordenada del primer punto de la curva", - "Número: coordenada del primer punto de control de la curva", - "Número: coordenada del segundo punto de control de la curva", - "Número: coordenada del segundo punto de la curva", - "Número: valor entre 0 y 1"], - "returns": "the p5 object" - }, - "curveTangent": { - "description": "Evalua la tangente de la curva en la posición t para los puntos a, b, c, d. El parámetro t varía entre 0 y 1, a y d son los puntos de la curva, b y c son los puntos de control.", - "params": ["Número: coordenada del primer punto de la curva", - "Número: coordenada del primer punto de control de la curva", - "Número: coordenada del segundo punto de control de la curva", - "Número: coordenada del segundo punto de la curva", - "Número: valor entre 0 y 1"], - "returns": "la tangente en la posición t" - }, - "beginContour": { - "description": "Usa las funciones beginContour() y endContour() para crear figuras negativas dentro de figuras como el centro de la letra 'O'. beginContour() empieza la grabación de los vértices para la figura y endContour() finaliza la grabación. Los vértices que definen una figura negativa deben ser definidos en la dirección opuesta a la figura exterior. Primero dibuja los vértices de la figura exterior en el orden de las manecillas del reloj, y luego para figuras internas, dibuja vértices en el sentido contrario a las manecillas del reloj. Estas funciones solo pueden ser usadas dentro de un par beginShape()/endShape() y transformaciones como translate(), rotate(), y scale() no funcionan dentro de un par beginContour()/endContour(). Tampoco es posible usar otras figuras, como elupse() o rect() dentro.", - "returns": "el objeto p5" - }, - "beginShape": { - "description": "El uso de las funciones beginShape() y endShape() permiten la creación de figuras más complejas. beginShape() empieza la grabación de vértices para una figura, mientras que endShape() termina la grabación. El valor del parámetro kind (tipo) define qué tipo de figuras serán creadas a partir de los vértices. Si no se especifica un modo, la figura puede ser cualquier polígono irregular. Los parámetros disponibles para beginShape() son POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, y QUAD_STRIP. Después de llamar a la función beginShape(), debe ser seguida por una serie de comandos vertex(). Para detener el dibujo de la figura, ejecuta endShape(). Cada figura será dibujada con el color de trazo y el color de relleno actual. Transformaciones como translate(), rotate(), y scale() no funcionan dentro de beginShape(). Tampoco es posible usar otras figuras como ellipse() o rect() dentro de beginShape().", - "params": ["Constante: puede ser POINTS, LINES, TRIANGLES, TRIANGLE_FAN TRIANGLE_STRIP, QUADS, o QUAD_STRIP"], - "returns": "el objeto p5" - }, - "bezierVertex": { - "description": "Especifica las coordenadas de un vértice para una curva Bezier. Cada llamada a la función bezierVertex() define la posición de dos puntos de control y un punto ancla de una curva Bezier, añadiendo un nuevo segmento a la línea o figura. La primera vez que bezierVertex() es usada dentro de una llamada a beginShape(), debe ser antecedida por una llamada a la función vertex() para definir el primer punto ancla. Esta función debe ser usada entre beginShape() y endShape() y solo cuando no se ha especificado el parámetro MODE (modo) a beginShape().", - "params": ["Número: coordenada x del primer punto de control la curva", - "Número: coordenada y del primer punto de control la curva", - "Número: coordenada x del segundo punto de control la curva", - "Número: coordenada y del segundo punto de control la curva", - "Número: coordenada x del primer punto ancla", - "Número: coordenada y del primer punto ancla"], - "returns": "el objeto p5" - }, - "curveVertex": { - "description": "Especifica las coordenadas de un vértice para una curva. Esta función solo puede ser usada entre beginShape() y endShape() y cuando no se ha especificado el parámetro MODE en la función beginShape(). Los puntos primero y último en una serie de líneas curveVertex() serán usados para guiar el inicio y final de una curva. Un mínimo de cuatro puntos es requerido para dibujar una pequeña curva entre los puntos segundo y tercero, Añadir un quinto punto con curveVertex() dibujará la curva entre los puntos segundo, tercero y cuarto. La función curveVertex() es una implementación de las splines de Catmull-Rom.", - "params": ["Número: coordenada x del vértice", - "Número: coordenada y del vértice"], - "returns": "el objeto p5" - }, - "endContour": { - "description": "Usa las funciones beginContour() y endContour() para crear figuras negativas dentro de figuras como el centro de la letra 'O'. beginContour() empieza la grabación de los vértices para la figura y endContour() finaliza la grabación. Los vértices que definen una figura negativa deben ser definidos en la dirección opuesta a la figura exterior. Primero dibuja los vértices de la figura exterior en el orden de las manecillas del reloj, y luego para figuras internas, dibuja vértices en el sentido contrario a las manecillas del reloj. Estas funciones solo pueden ser usadas dentro de un par beginShape()/endShape() y transformaciones como translate(), rotate(), y scale() no funcionan dentro de un par beginContour()/endContour(). Tampoco es posible usar otras figuras, como elupse() o rect() dentro.", - "returns": "el objeto p5" - }, - "endShape": { - "description": "La función endShape() es compañera de la función beginShape() y solo puede ser ejecutada tras la ejecución de beginShape(). Cuando endshape() es ejecutada, todos los datos de imagen definidos desde la llamada anterior a beginShape() son escritos en el buffer de imagen. La constante CLOSE se usa como valor para el parámetro MODE para cerrar la figura (para conectar el comienzo con el final).", - "params": ["Constante: usa CLOSE para cerrar la figura."], - "returns": "el objeto p5" - }, - "quadraticVertex": { - "description": "Especifica las coordenadas de vértices par curvas Bezier cuadráticas. Cada llamada a quadraticVertex() define la posición de uno de los puntos de control y ancla de una curva Bezier, añadiendo un nuevo segmento a la línea o figura. La primera vez que quadraticVertex() es usada dentro de una llamada a beginShape(), debe ser precedida por una llamada a la función vertex() para definir el primer punto ancla. Esta función debe ser usada entre un par beginShape() y endShape() y solo cuando no se ha especificado el parámetro MODE de beginShape().", - "params": ["Número: coordenada x del punto de control", - "Número: coordenada y del punto de control", - "Número: coordenada x del punto ancla", - "Número: coordenada y del punto ancla"], - "returns": "el objeto p5" - }, - "vertex": { - "description": "Todas las figuras son construidas mediante la conexión de una serie de vértices. vertex() es usado para especificar las coordenadas de los vértices para puntos, líneas, triángulos, cuadriláteros y polígonos. Es usada exclusivamente dentro de un par de funciones beginShape() y endShape().", - "params": ["Número: coordenada x del vértice", - "Número: coordenada y del vértice"], - "returns": "el objeto p5" - }, - "loadModel": { - "description": "Carga un modelo 3d desde un archivo OBJ. Una de las limitaciones del formato OBJ es que no trae incorporado un sentido de escala. Esto significa que los modelos exportados por distintos programas pueden ser de tamaños radicalmente distintos. Si tu modelo no está siendo mostrado en pantalla, trata llamando a la función loadMode() con el parámetro de normalización configurado como verdadero. Esto escalará el tamaño del modelo a una escala apropiada para p5. También puedes hacer cambios adicionales al tamaño final de tu modelo con la función scale().", - "params": ["String: ubicación del modelo a cargar", - "Boolean: Si es verdadero (true), escala el modelo a un tamaño estandarizado al momento de cargarlo.", - "Función(p5.Geometry3D): función a ser llamada cuando el modelo se cargue. Será pasada al modelo del objeto 3D.", - "Función(evento): llamada con el error evento si la imagen no falla al cargar."], - "returns": "el objeto p5.Geometry3D" - }, - "model": { - "description": "Hace el render de un modelo 3D en la pantalla.", - "params": ["p5.Geometry: modelo 3D cargado para realizar render"], - "returns": "el objeto p5" - }, - "plane": { - "description": "Dibuja un plano con ancho y altura dados.", - "params": ["Número: ancho del plano", - "Número: altura del plano", - "Número: número opcional de subdivisiones triangulares en la dimensión x", - "Número: número opcional de subdivisiones triangulares en la dimensión y"], - "returns": "el objeto p5" - }, - "box": { - "description": "Dibuja una caja con ancho, altura y profundidad dados.", - "params": ["Número: ancho de la caja", - "Número: altura de la caja", - "Número: profundidad de la caja", - "Número: número opcional de subdivisiones triangulares en la dimensión x", - "Número: número opcional de subdivisiones triangulares en la dimensión y"], - "returns": "el objeto p5" - }, - "sphere": { - "description": "Dibuja una esfera de radio dado.", - "params": ["Número: radio del círculo", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], - "returns": "el objeto p5" - }, - "cylinder": { - "description": "Dibuja un cilindro de radio y altura dados.", - "params": ["Número: radio de la superficie", - "Número: altura del cilindro", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], - "returns": "el objeto p5" - }, - "cone": { - "description": "Dibuja un cono de radio y altura dados.", - "params": ["Número: radio de la superficie inferior", - "Número: altura del cono", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16"], - "returns": "el objeto p5" - }, - "ellipsoid": { - "description": "Dibuja un elipsoide de radio dado.", - "params": ["Número: radio x del círculo", - "Número: radio y del círculo", - "Número: radio z del círculo", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24. Evita números mayores a 150 que podrían colapsar el navegador.", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16. Evita números mayores a 150 que podrían colapsar el navegador."], - "returns": "el objeto p5" - }, - "torus": { - "description": "Dibuja un toroide con radio y tubo dado.", - "params": ["Número: radio del anillo completo", - "Número: radio del tubo", - "Número: radio z del círculo", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 24.", - "Número: opcional, número de segmentos, a mayor número de segmentos la geometría es más suave, por defecto es 16."], - "returns": "el objeto p5" - }, - "HALF_PI": { - "description": "HALF_PI es una constante matemática de valor 1.57079632679489661923. Es la mitad de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", - "returns": "el objeto p5" - }, - "PI": { - "description": "PI es una constante matemática de valor 3.14159265358979323846. Es la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", - "returns": "el objeto p5" - }, - "QUARTER_PI": { - "description": "QUARTER_PI es una constante matemática de valor 0.7853982. Es un cuarto de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", - "returns": "el objeto p5" - }, - "TAU": { - "description": "TAU es un alias de TWO_PI, una constante matemática de valor 6.28318530717958647693. Es el doble de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", - "returns": "el objeto p5" - }, - "TWO_PI": { - "description": "TWO_PI es una constante matemática de valor 6.28318530717958647693. Es el doble de la razón entre la circunferencia de un círculo y su diámetro. Es útil en combinación con las funciones trigonométricas sin() y cos().", - "returns": "el objeto p5" - }, - "preload": { - "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일들의 비동기성 로딩을 blocking 방식으로 처리하기 위해 사용됩니다. preload() 함수를 사용하면 setup() 함수는 preload() 함수 내에 포함된 모든 로딩이 끝난 후에 실행됩니다. preload() 함수 내에는 loadImage, loadJSON, loadFont, LoadString과 같은 로딩 호출만 포함해야 합니다. 비동기적 로딩을 원하는 경우에는 setup() 함수 내 혹은 다른 적절한 위치에서 로딩하되, 콜백 매개변수와 함께 사용합니다. 로딩 페이지에는 'loading...' 문구가 표시됩니다. 로딩 페이지 문구나 디자인을 변경하려면 id가 'p5_loading'인 HTML 요소를 해당 페이지에 삽입하세요.", - "returns": "the p5 object" - }, - "setup": { - "description": "setup()은 화면의 크기나 배경 색과 같은 환경적 속성, 이미지나 서체와 같은 미디어 로딩을 정의하는데 사용하는 함수로, 프로그램을 시작 시 단 한 번만 실행됩니다. setup()은 한 프로그램 내 하나만 존재하며, 한번 실행된 이후에 다시 호출되어서는 안됩니다. 주의: setup() 내에서 정의된 변수는 draw()를 포함한 다른 함수에서 접근이 불가함.", - "returns": "the p5 object" - }, - "draw": { - "description": "setup()이 실행된 직후 호출되는 draw()는 프로그램이 종료되거나 noLoop() 함수가 호출될 때까지 계속해서 반복적으로 실행됩니다. 단, noLoop() 함수가 setup() 내에서 호출되는 경우에는 draw() 에 영향을 미치지 않아 실행을 종료시키지 않습니다. draw()는 자동적으로 호출되는 함수이며 절대로 임의로 호출해 사용할 수 없습니다. 대신, draw()는 noLoop(), redraw(), loop()로 조종이 가능합니다. noLoop()는 draw() 실행을 중단하고, redraw()는 draw() 내 코드를 한 번 실행시키며, loop()는 draw() 내 코드를 다시 반복적으로 실행시킵니다. frameRate() 함수를 이용하면 draw()를 일초에 몇 번 실행시킬 것인지 설정할 수 있습니다. draw()는 한 스케치에 꼭 하나만 존재합하며 mousePressed()와 같은 이벤트를 실행하기 위해서는 draw()가 반드시 필요합니다. 또하나 기억해야 할 점은 draw()를 시작할 때 좌표 시스템이 초기화된다는 점입니다. 즉, draw() 내에서 scale, rotate, translate와 같은 좌표 변형을 하는 경우 draw() 시작시 매번 이들이 초기화되기 때문에 변형 상태가 축적되지 않습니다. 한편, fill이나 stroke와 같은 스타일링은 draw() 시작시 초기화되지 않고 유지됩니다", - "returns": "the p5 object" - }, - "remove": { - "description": "전체 p5 스케치를 제거합니다. 캔버스를 포함해 p5.js에 의해 생성된 모든 요소를 제거하고, draw loop을 정지시키며 윈도우 전역의 속성과 메소드를 무효화 합니다. 단, 당신이 새로운 p5 스케치를 만들고 싶어할 경우를 대비해 변수 'p5'는 제거하지 않는데, 이마저 제거하고 싶다면 'p5 = null'을 입력하면 됩니다. 이 함수는 p5 라이브러리에 의해 생성된 함수, 변수, 오브젝트만 제거하며 프로그램 내의 다른 변수는 제거하지 않습니다.", - "returns": "the p5 object" - }, - "noLoop": { - "description": "draw() 내 코드가 반복적으로 실행되는 것을 정지시킵니다. 정지 후에 다시 코드를 반복적으로 실행시키고 싶다면 loop()를 이용합니다. noLoop()이 setup() 내에서 사용하려면 가장 마지막 줄에 사용합니다. noLoop()이 호출되면 mousePressed()나 keyPressed()와 같은 이벤트 핸들러 함수를 접근하거나 조종할 수 없습니다. 대안으로는 draw()를 실행시킬 수 있는 redraw()나 loop()과 같은 함수를 이용해 화면을 적절히 업데이트하는 방법이 있습니다. noLoop()을 호출한 이후에는 스케치가 진행되지 않으며 saveFrame()이나 loadPixels과 같은 함수를 사용할 수도 없습니다. 주의: 스케치의 사이즈를 재설정(resize)하는 경우에는 noLoop()의 존재여부와 관계없이 redraw()가 자동적으로 호출됩니다. 사이즈 재설정 후 스케치를 업데이트하지 않으면 화면의 요소들이 제대로 보여지지 않기 때문입니다.", - "returns": "the p5 object" - }, - "loop": { - "description": "p5.js는 draw() 내 코드를 끊임없이 반복해서 실행합니다. 이를 멈추고싶을 때는 noLoop()를 사용하세요. draw() 반복 실행을 재개하고 싶은 경우에는 loop()을 사용합니다.", - "returns": "the p5 object" - }, - "push": { - "description": "push()와 pop()은 항상 함께 사용되는 함수로, push() 함수는 함수 이전에 설정된 드로잉 스타일과 좌표 시스템을 저장하고 pop() 함수는 이 저장값을 복구합니다. 이 함수를 사용하면 스타일과 좌표 시스템을 일시적으로 변경하고 이후 필요한 시점에 본래의 설정값으로 편리하게 되돌아올 수 있습니다. push() 함수를 호출한 이후에 입력하는 설정은 새로운 상태를 정의하며 이 설정은 pop() 함수가 등장하기 전까지 유효합니다. 두번째 예제와 같이 push()와 pop() 함수 세트 내에 다른 push()와 pop() 함수 세트를 내장하는 것도 가능합니다. push() 함수는 다음의 함수가 설정하는 현재의 좌표 시스템과 스타일을 저장합니다: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), texgtAlign(), textFont(), textSize(), textLoading(). WEBGL 모드에서는 다음 함수를 이용해 설정하는 추가적인 스타일도 저장됩니다: setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shineness(), normalMaterial(), shader().", - "returns": "the p5 object" - }, - "pop": { - "description": "push()와 pop()은 항상 함께 사용되는 함수로, push() 함수는 함수 이전에 설정된 드로잉 스타일과 좌표 시스템을 저장하고 pop() 함수는 이 저장값을 복구합니다. 이 함수를 사용하면 스타일과 좌표 시스템을 일시적으로 변경하고 이후 필요한 시점에 본래의 설정값으로 편리하게 되돌아올 수 있습니다. push() 함수를 호출한 이후에 입력하는 설정은 새로운 상태를 정의하며 이 설정은 pop() 함수가 등장하기 전까지 유효합니다. 두번째 예제와 같이 push()와 pop() 함수 세트 내에 다른 push()와 pop() 함수 세트를 내장하는 것도 가능합니다. push() 함수는 다음의 함수가 설정하는 현재의 좌표 시스템과 스타일을 저장합니다: fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), texgtAlign(), textFont(), textSize(), textLoading(). WEBGL 모드에서는 다음 함수를 이용해 설정하는 추가적인 스타일도 저장됩니다: setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shineness(), normalMaterial(), shader()." - }, - "redraw": { - "description": "draw() 내 코드를 한 번 실행합니다. 본 함수를 이용하면 필요한 경우에만 화면을 업데이트할 수 있습니다. redraw()는 mousePressed()나 keyPressed()에 의해 일어나는 이벤트와 같이 조건적으로 일어나는 이벤트에 사용하면 유용합니다. 이 함수를 어느 위치에 사용하냐구요? redraw()는 draw()를 바로 실행시키는 것이 아니라 단지 업데이트가 필요하다는 표시를 하는 셈이기 때문에, mousePressed()와 같은 이벤트 내에서 호출해야 합니다. redraw() 함수는 draw()함수 내에 사용할 수는 없습니다. 애니메이션의 실행 여부를 조종하고 싶다면 loop()과 noLoop()를 이용하세요. redraw 횟수를 정하는 것도 가능한데, 이를 위해서는 정수를 redraw() 함수의 변수로 입력합니다.", - "params": ["정수: redraw를 n번 실행합니다. n의 초기값은 1입니다."], - "returns": "the p5 object" - }, - "print": { - "description": "La función print() escribe en la consola del navegador. Esta función es a menudo de ayuda para observar los datos que un programa está produciendo. Esta función crea una nueva línea de texto por cada ejecución de la función. Elementos individuales pueden ser separados por comillas ('') y unidos con el operador de adición (+). Aunque print() es similar a console.log(), no llama a console.log() directamente, para simular una manera más simple de entender el comportamiento del programa. Por esto mismo, es más lento. Para resultados más rápidos, usar directamente console.log().", - "params": ["Cualquiera: cualquier combinación de número, string, objeto, boolean o arreglo a imprimir"], - "returns": "el objeto p5" - }, - "frameCount": { - "description": "La variable de sistema frameCount contiene el número de cuadros (frames) que se han mostrado desde que el programa empezó a ejecutarse. Dentro de setup() el valor es 0, después de la primera iteración de draw() es 1, etc.", - "returns": "el objeto p5" - }, - "focused": { - "description": "Confirma si la ventana de un programa de p5.js está en foco, lo que significa que el bosquejo aceptará entradas desde el ratón o teclado. Esta variable es verdadera (true) si la ventana está en foco y falsa (false) si no.", - "returns": "el objeto p5" - }, - "cursor": { - "description" : "Define el cursor como un símbolo predeterminado o una imagen, o hace el cursor visible si es que estaba escondido. Si estás tratando de asignar una imagen al cursor, el tamaño recomendado es 16x16 o 32x32 pixeles. No es posible cargar una imagen al cursor si estás exportando tu programa a la Web, y no todos los modos funcionan con todos los navegadores. Los valores de los parámetros x e y deben ser menores a la dimensión de la imagen.", - "params": ["Número|Constante: puede ser ARROW, CROSS, HAND, MOVE, TEXT, o WAIT, o la dirección de una imagen", - "Número: el punto activo horizontal del cursor", - "Número: el punto activo vertical del cursor"], - "returns": "el objeto p5" - }, - "frameRate": { - "description": "Especifica el número de cuadros mostrados por segundo. Por ejemplo, la llamada a la función frameRate(30), tratará de refrescar 30 veces por segundo. Si el procesador no es lo suficientemente rápido para mantener la tasa especificada, la tasa de cuadros por segundo no será lograda. Definir la tasa de cuadros por segundo dentro de setup() es lo recomendable. La tasa por defecto es de 60 veces por segundo. Esto es lo mismo que setFrameRate(val). Llamar a la función frameRate() sin argumentos retorna la tasa actual. Esto es lo mismo que getFrameRate(). Llamar a la función frameRate() con arugmentos que no son de tipo número o no son positivos también retornarán la tasa actual.", - "params": ["Número: número de cuadros a ser mostrados cada segundo."], - "returns": "la tasa de cuadros por segundo (frameRate) actual" - }, - "noCursor": { - "description": "Esconde el cursor.", - "returns": "el objeto p5" - }, - - "displayWidth": { - "description": "Variable de sistema que almacena el ancho de la pantalla mostrada. Esto es usado para correr un programa a pantalla completa en cualquier dimensión de pantalla.", - "returns": "el objeto p5" - }, - "displayHeight": { - "description": "Variable de sistema que almacena la altura de la pantalla mostrada. Esto es usado para correr un programa a pantalla completa en cualquier dimensión de pantalla.", - "returns": "el objeto p5" - }, - "windowWidth": { - "description": "Variable de sistema que almacena el ancho interior de la ventana del navegador, equivale a window.innerWidth.", - "returns": "el objeto p5" - }, - "windowHeight": { - "description": "Variable de sistema que almacena la altura interior de la ventana del navegador, equivale a window.innerHeight.", - "returns": "el objeto p5" - }, - "windowResized": { - "description": "La función windowResized() es llamada cada vez que la ventana del navegador cambia de tamaño. Es un buen lugar para cambiar las dimensiones del lienzo o hacer cualquier otro ajuste necesario para acomodar las nuevas dimensiones de la ventana.", - "returns": "el objeto p5" - }, - "width": { - "description": "Variable de sistema que almacena el ancho del lienzo dibujado. Este valor es definido por el primer parámetro de la función createCanvas(). Por ejemplo, la llamada a la función (320, 240) define la variable width al valor 320. El valor por defecto de ancho es de 100 si es que createCanvas() no ha sido usado en el programa.", - "returns": "el objeto p5" - }, - "height": { - "description": "ariable de sistema que almacena la altura del lienzo dibujado. Este valor es definido por el primer parámetro de la función createCanvas(). Por ejemplo, la llamada a la función (320, 240) define la variable width al valor 240. El valor por defecto de ancho es de 100 si es que createCanvas() no ha sido usado en el programa.", - "returns": "el objeto p5" - }, - "fullscreen": { - "description": "Si se da un argumento, define que el bosquejo esté a pantalla completa basado en el valor del argumento. Si no se da un argumento, retorna el estado actual de pantalla completa. Notar que debido a restricciones del navegador esto solo puede ser llamado con una entrada de parte del usuario, por ejemplo, cuando se presiona el ratón como en el ejemplo.", - "params": ["Boolean: define si el bosquejo debe estar a pantalla completa o no."], - "returns": "Boolean: estado de pantalla completa actual" - }, - "pixelDensity": { - "description": "Define el escalamiento de pixeles para monitores de alta densidad de pixeles. Por defecto, la densidad de pixeles es definida para calzar con la densidad del monitor, ejecuta pixelDensity() para que no sea así. Llamar a pixelDensity() sin argumentos retorna la densidad de pixeles actual del bosquejo.", - "params": ["Número: si es que el bosquejo debe ser escalado y cuánto."], - "returns": "Número: densidad de pixeles actual del bosquejo" - }, - "displayDensity": { - "description": "Retorna la densidad de pixeles del monitor actual en que el bosquejo está corriendo.", - "returns": "Número: la densidad de pixeles actual del monitor" - }, - "getURL": { - "description": "Retorna la URL actual.", - "returns": "String: URL" - }, - "getURLPath": { - "description": "Retorna la dirección URL como un arreglo", - "returns": "Arreglo: los componentes de la dirección" - }, - "getURLParams": { - "description": "Retorna los parámetros de la URL actual como un objeto.", - "returns": "Objeto: parámetros de la URL" - }, "createCanvas": { "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를 참고하세요.", "params": ["숫자: 캔버스의 너비", "숫자: 캔버스의 높이", "상수: P2D 또는 WEBGL"] }, - "resizeCanvas": { - "description": "Redimensiona el linezo al ancho y la altura dados. El lienzo será borrado y la función draw() será llamada inmediatamente, permitiendo que el bosquejo se ajuste al nuevo lienzo", - "returns": "el objeto p5" - }, - "noCanvas": { - "description": "Remueve el lienzo por defecto para un bosquejo de p5 que no requiere un lienzo.", - "returns": "el objeto p5" - }, - "createGraphics": { - "description": "Crea y retorna un nuevo objeto p5.Renderer. Usa esta clase si necesitas dibujar fuera de pantalla en un buffer gráfico. Los dos parámetros definen el ancho y la altura en pixeles.", - "params": ["Número: ancho del buffer gráfico fuera de pantalla", - "Número: altura del buffer gráfico fuera de pantalla", - "Constante: P2D o WEBGL, si no se define es P2D por defecto"], - "returns": "buffer gráfico fuera de pantalla" - }, - "blendMode": { - "description": "Combina los pixeles en la ventana según el modo definido. Existen distintas maneras de combinar los pixeles de la fuente (A) con los ya existentes en la pantalla mostrada (B). TODO", - "params": ["Constante: modo de combinar del lienzo"], - "returns": "el objeto p5" - }, - "applyMatrix": { - "description": "Multiplica la matriz actual por la especificada según los parámetros. Esto es muy lento porque tratará de calcular el inverso de la transformada, así que evítalo cuando sea posible", - "params": ["Número: números que definen la matriz 3x2 a multiplicar", - "Número: números que definen la matriz 3x2 a multiplicar", - "Número: números que definen la matriz 3x2 a multiplicar", - "Número: números que definen la matriz 3x2 a multiplicar", - "Número: números que definen la matriz 3x2 a multiplicar", - "Número: números que definen la matriz 3x2 a multiplicar"], - "returns": "el objeto p5" - }, - "resetMatrix": { - "description": "Reemplaza la matriz actual con la matriz identidad", - "returns": "el objeto p5" - }, - "rotate": { - "description": "Rota una figura según el monto especificado por el parámetro ángulo. Esta función toma en cuenta el modo de ángulo definido por angleMode(), así que los ángulos pueden ser ingresados en radianes o grados. Los objetos son siempre rotados según su posición relativa al origen y los números positivos rotan en la dirección de las manecillas del reloj. Las transformaciones se aplican a todo lo que ocurre de forma posterior y las subsecuentes llamadas a la función acumulan el efecto. Por ejemplo, llamar a la función rotate(HALF_PI) y luego rotate(HALF_PI) equivale a una llamada a rotate(PI). Todas las transformaciones son anuladas cuando la función draw() comienza nuevamente. Técnicamente, rotate() multiplica la matriz de transformación actual por una matriz de rotación. Esta función puede ser controlada además con las funciones push() y pop().", - "params": ["Ángulo: el ángulo de rotación, especificado en radianes o grados, dependiendo de angleMode()", - "Número: ángulo en radianes", - "p5.Vector|Arreglo: eje sobre el que se rota"], - "returns": "el objeto p5" - }, - "rotateX": { - "description": "Rota en torno al eje X", - "params": ["Número: ángulo en radianes"], - "returns": "el objeto p5" - }, - "rotateY": { - "description": "Rota en torno al eje Y", - "params": ["Número: ángulo en radianes"], - "returns": "el objeto p5" - }, - "rotateZ": { - "description": "Rota en torno al eje Z,. Sólo disponible en el modo WEBGL.", - "params": ["Número: ángulo en radianes"], - "returns": "el objeto p5" - }, - "scale": { - "description": "Aumenta o decrementa el tamaño de una figura por medio de expandir o contraer sus vértices. Los objetos siempre escalan desde su origen relativo al sistema de coordenadas. Los valores de escalamiento son porcentajes decimales. Por ejemplo, la llamada a la función scale(2.0) aumenta la dimensión de una figura en un 200%. Las transformaciones se aplican a todo lo que ocurre después y llamadas subsecuentes a la función multiplican el efecto. Por ejemplo, llamar a scale(2.0) y luego a scale(1.5) equivale a llamar a scale(3.0). Si la función scale() es llamad dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. El uso de esta función con el parámetro z está solo disponible en el modo WEBGL. Esta función puede también ser controlada con las funciones push() y pop().", - "params": ["Número | p5.Vector| Arreglo: porcentaje a escalar del objeto, o porcentaje a esacalar del objeto en el eje x si se dan múltiples argumentos", - "Número: porcentaje a escalar el objeto en el eje y", - "Número: porcentaje a escalar el objeto en el eje z (sólo en modo WEBGL)"], - "returns": "el objeto p5" - }, - "shearX": { - "description": "Corta la figura en torno al eje x según el monto especificado por el parámetro ángulo. Los ángulos deben ser especificados según el modo actual de ángulo angleMode(). Los objetos son siempre cortados según su posición relativa al origen y los números positivos cortan los objetos en la dirección de las manecillas del reloj. Las transformaciones aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a shearX(PI/2) y luego a shearX(PI/2) equivale a llamar a shearX(PI). Si shearX() es llamado dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. Técnicamente, shearX() multiplica la matriz de transformación actual por una matriz de rotación. La función puede ser controlada con las funciones push() y pop().", - "params": ["Número: ángulo de corte especificado en radianes o grados, dependiendo del modo de ángulo actual angleMode()"], - "returns": "el objeto p5" - }, - "shearY": { - - "description": "Corta la figura en torno al eje y según el monto especificado por el parámetro ángulo. Los ángulos deben ser especificados según el modo actual de ángulo angleMode(). Los objetos son siempre cortados según su posición relativa al origen y los números positivos cortan los objetos en la dirección de las manecillas del reloj. Las transformaciones aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a shearY(PI/2) y luego a shearY(PI/2) equivale a llamar a shearY(PI). Si shearY() es llamado dentro de draw(), la transformación es anulada cuando el bucle empieza nuevamente. Técnicamente, shearY() multiplica la matriz de transformación actual por una matriz de rotación. La función puede ser controlada con las funciones push() y pop().", - "params": ["Número: ángulo de corte especificado en radianes o grados, dependiendo del modo de ángulo actual angleMode()"], - "returns": "el objeto p5" - }, - "translate": { - "description": "Especifica una cantidad a desplazar los objetos dentro de la ventana mostrada. El parámetro x especifica la traslación de izquierda a derecha, el parámetro y especifica la traslación de arriba a abajo. Las transformaciones son acumulativas y aplican a todo lo que ocurre después y llamadas posteriores a la misma función acumulan el efecto. Por ejemplo, llamar a translate(50, 0) y luego a translate(20, 0) equivale a llamar a translate(70, 0). Si translate() es llamado dentro de draw(), la transformación es anulada cada vez que el bucle empieza nuevamente. Esta función peude ser controlada con las funciones push() y pop().", - "params": ["Número: traslación izquierda-derecha", - "Número: traslación arriba-abajo", - "Número: traslación adelante-atrás (solo en modo WEBGL)"], - "returns": "el objeto p5" - }, - "deviceOrientation": { - "description": "La variable de sistema deviceOrientation siempre contiene la orientación del dispositivo. El valor de esta variable será o landscape (paisaje) o portrait (retrato). Si la información no está disponible, su valor será undefined.", - "returns": "el objeto p5" - }, - "accelerationX": { - "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje X. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "accelerationY": { - "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje Y. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "accelerationZ": { - "description": "La variable de sistema accelerationX siempré contiene la aceleración del dispositivo en el eje Z. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "pAccelerationX": { - "description": "La variable de sistema pAccelerationX siempré contiene la aceleración del dispositivo en el eje X, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "pAccelerationY": { - "description": "La variable de sistema pAccelerationY siempré contiene la aceleración del dispositivo en el eje Y, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "pAccelerationZ": { - "description": "La variable de sistema pAccelerationZ siempré contiene la aceleración del dispositivo en el eje Z, del cuadro anterior al cuadro actual. El valor es representado en unidades de metros por segundo al cuadrado.", - "returns": "el objeto p5" - }, - "rotationX": { - "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje x. El valor está representado entre 0 y +/-180 grados. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", - "returns": "el objeto p5" - }, - "rotationY": { - "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje x. El valor está representado entre 0 y +/-180 grados. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", - "returns": "el objeto p5" - }, - "rotationZ": { - "description": "La variable de sistema rotationX siempre contiene la rotación del dispositivo en el eje y. El valor está representado entre 0 y 360 grados. A diferencia de rotationX y rotationY, esta variable está solo disponible en dispositivos equipados con una brújula interna. Nota: el orden en que las rotaciones son llamadas es importante, por ejemplo, si se usan juntas, deben ser llamadas en el orden Z-X-Y, en caso contrario podría haber un comportamiento errado.", - "returns": "el objeto p5" - }, - "pRotationX": { - "description": "La variable de sistema pRotationX siempre contiene la rotación del dispositivo en el eje x, en el cuadro anterior al actual. El valor está representado entre 0 y +/-180 grados. pRotationX puede ser usado en conjunto con rotationX para determinar la dirección de rotación del dispositivo a lo largo del eje x.", - "returns": "el objeto p5" - }, - "pRotationY": { - "description": "La variable de sistema pRotationY siempre contiene la rotación del dispositivo en el eje x, en el cuadro anterior al actual. El valor está representado entre 0 y +/-90 grados. pRotationY puede ser usado en conjunto con rotationY para determinar la dirección de rotación del dispositivo a lo largo del eje y.", - "returns": "el objeto p5" - }, - "pRotationZ": { - "description": "La variable de sistema pRotationZ siempre contiene la rotación del dispositivo en el eje z, en el cuadro anterior al actual. El valor está representado entre 0 y 359 grados. pRotationZ puede ser usado en conjunto con rotationZ para determinar la dirección de rotación del dispositivo a lo largo del eje z.", - "returns": "el objeto p5" - }, - "setMoveThreshold": { - "description": "La función setMoveThreshold() es usada para definir el umbral para detectar movimiento de la función deviceMoved(). El valor umbral por defecto es 0.5", - "params": ["Número: el valor umbral"], - "returns": "el objeto p5" - }, - "setShakeThreshold": { - "description": "La función setShakeThreshold() es usada para definir el umbral para detectar agitamiento de la función deviceShaken(). El valor umbral por defecto es 30.", - "params": ["Número: el valor umbral"], - "returns": "el objeto p5" - }, - "deviceMoved": { - "description": "La función deviceMoved() es llamada cuando el dispositivo es movido en una cantidad mayor al valor umbral en el eje X, Y o Z. El valor umbral por defecto es 0.5", - "returns": "el objeto p5" - }, - "deviceTurned": { - "description": "La función deviceTurned() es llamada cuando el dispositivo es girado en más de 90 grados de modo continuo. El eje que gatilla la función deviceTurned() es almacenado en la variable turnAxis. El método deviceTurned() puede ser restringido para gatillar en cualquier eje: X, Y o Z, comparando la variable turnAxis con X, Y o Z.", - "returns": "el objeto p5" - }, - "deviceShaken": { - "description": "La función deviceShaken() es llamada cuando la aceleración total de los cambios de accelerationX y accelerationY son mayores al valor umbral. El valor umbral por defecto es 30", - "returns": "el objeto p5" - }, - "keyIsPressed": { - "description": "La variable boolean de sistema keyIsPressed es verdadera (true) cuando cualquier tecla es presionada y falsa (false) si no hay ninguna tecla presionada", - "returns": "el objeto p5" - }, - "key": { - "description": "La variable de sistema key siempre contiene el valor más reciente de la tecla del teclado presionada. Para tener los mejores resultados, es mejor usarla dentro de la función keyTyped(). Para teclas sin valor ASCII, usa la variable keyCode ", - "returns": "el objeto p5" - }, - "keyCode": { - "description": "La variable keyCode es usada para detectar teclas especiales, como BACKSPACE, DELETE, ENTER, RETURN, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. También puedes revisar las teclas especiales buscando el código keyCode de cualquier tecla en internet.", - "returns": "el objeto p5" - }, - "keyPressed": { - "description": "La función keyPressed() es llamada una vez cada vez que una tecla es presionada. El código keyCode de la tecla presionada es almacenado en la variable keyCode. Para las teclas sin valor ASCII, usa la variable keyCode. Puedes comprobar si la variable keyCode es igual a BACKSPACE, DELETE, ENTER, RETURN, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. Para las teclas con valor ASCII que son presionadas, el valor es almacenado en la variable key. Sin embargo, no distingue entre letras mayúsculas y minúsculas. Por esta razón, es recomendable usar la función keyTyped() para leer la variable key, que sí distingue entre mayúsculas y minúsculas. Por la forma en que los sistemas operativos manejan la repetición de teclas, mantener presionada una tecla puede causar múltiples llamadas a keyTyped() (y también keyReleased()). La tasa de repetición es definida por el sistema operativo y según cómo cada computador está configurado. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "returns": "el objeto p5" - }, - "keyReleased": { - "description": "La función keyReleased() es llamada una vez cada vez que una tecla es soltada. Ver key y keyCode para más información. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "returns": "el objeto p5" - }, - "keyTyped": { - "description": "la función keyTyped es llamada cava vez que una tecla es presionada, excepto cuando son presionadas la steclas de acción como Ctrl, Shift y Alt, que son ignoradas. La tecla presionada más reciente será almacenada en la variable key. Por la forma en que los sistemas operativos manejan la repetición de teclas, mantener presionada una tecla puede causar múltiples llamadas a keyTyped() (y también keyReleased()). La tasa de repetición es definida por el sistema operativo y según cómo cada computador está configurado. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por teclas. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "params": ["Número: el valor umbral"], - "returns": "el objeto p5" - }, - "keyIsDown": { - "description": "La función keyIsDown() comprueba si la tecla está presionada. Puede ser usada si tienes un objeto que se mueve, y quieres que varias teclas sean capaces de afectar este comportamiento de manera simultánea, como cuando mueves una imagen de forma diagonal. Puedes ingresar cualquier número representando el código de tecla keyCode de la tecla, o usar cualquier de los nombres de la variable keyCode.", - "params": ["Número: la tecla a buscar"], - "returns": "el objeto p5" - }, - "mouseX": { - "description": "La variable de sistema mouseX siempre contiene la posición horizontal actual del ratón, relativa al origen (0, 0) del lienzo.", - "returns": "el objeto p5" - }, - "mouseY": { - "description": "La variable de sistema mouseY siempre contiene la posición vertical actual del ratón, relativa al origen (0, 0) del lienzo.", - "returns": "el objeto p5" - }, - "pmouseX": { - "description": "La variable de sistema pmouseX siempre contiene la posición horizontal actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) del lienzo.", - "returns": "el objeto p5" - }, - "pmouseY": { - "description": "La variable de sistema pmouseY siempre contiene la posición vertical actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) del lienzo.", - "returns": "el objeto p5" - }, - "winMouseX": { - "description": "La variable de sistema winMouseX siempre contiene la posición horizontal actual del ratón, relativa al origen (0, 0) de la ventana del navegador.", - "returns": "el objeto p5" - }, - "winMouseY": { - "description": "La variable de sistema winMouseY siempre contiene la posición vertical actual del ratón, relativa al origen (0, 0) de la ventana del navegador.", - "returns": "el objeto p5" - }, - "pwinMouseX": { - "description": "La variable de sistema pwinMouseX siempre contiene la posición horizontal actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) de la ventana del navegador.", - "returns": "el objeto p5" - }, - "pwinMouseY": { - "description": "La variable de sistema pwinMouseY siempre contiene la posición vertical actual del ratón, en el cuadro anterior al actual, relativa al origen (0, 0) de la ventana del navegador.", - "returns": "el objeto p5" - }, - "mouseButton": { - "description": "P5.js automáticamente rastrea si el botón del ratón está presionado y cuál botón está presionado. El valor de la variable de sistema mouseButton es o LEFT, RIGHT o CENTER dependiendo de cual fue el último botón presionado. Advertencia: diferentes navegadores pueden diferir.", - "returns": "el objeto p5" - }, - "mouseIsPressed": { - "description": "La variable boolean de sistema mouseIsPressed es verdadera (true) si el ratón está siendo presionado, y falsa (false) en caso contrario.", - "returns": "el objeto p5" - }, - "mouseMoved": { - "description": "La función mouseMoved() es llamada cada vez que el ratón se mueve y un botón del ratón no está siendo presionado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", - "returns": "el objeto p5" - }, - "mouseDragged": { - "description": "La función mouseDragged() es llamada cada vez que el ratón se mueve y un botón del ratón está siendo presionado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", - "returns": "el objeto p5" - }, - "mousePressed": { - "description": "La función mousePressed() es llamada cada vez que un botón del ratón está siendo presionado. La variable mouseButton (ver la referencia) puede ser usada para determinar cual botón está siendo presionado. Si no se define una función mousePressed(), la función touchStarted() será llamada en su reemplazo, si es que está definida. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", - "returns": "el objeto p5" - }, - "mouseReleased": { - "description": "La función mouseReleased() es llamada cada vez que un botón del ratón es soltado. Si no se define una función mouseReleased(), la función touchEnded() será llamada en su reemplazo, si es que está definida. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", - "returns": "el objeto p5" - }, - "mouseClicked": { - "description": "La función mouseClicked() es llamada cada vez que un botón del ratón es presionado y luego soltado. Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método.", - "returns": "el objeto p5" - }, - "mouseWheel": { - "description": "La función mouseWheel() es llamada cada vez que se detecta un evento de rueda de ratón vertical, ya sea gatillado por un ratón o por un touchpad. La propiedad event.delta retorna el monto que el ratón ha avanzado. Estos valores pueden ser positivos o negativos, dependiendo de la dirección de navegación (en OS X con natural scrolling, los signos son invertidos). Los navegadores pueden tener comportamientos por defecto asociados a distintos eventos del ratón. Para prevenir cualquier comportamiento por defecto, añade return false como última línea de este método. Debido al soporte actual del evento wheel en Safari, la función podría solo funcionar si return false es incluido cuando se usa Safari.", - "returns": "el objeto p5" - }, - "touchX": { - "description": "La variable de sistema touchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) del lienzo. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", - "returns": "el objeto p5" - }, - "touchY": { - "description": "La variable de sistema touchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) del lienzo. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", - "returns": "el objeto p5" - }, - "ptouchX": { - "description": "La variable de sistema ptouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) del lienzo, en el cuadro anterior al actual. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", - "returns": "el objeto p5" - }, - "ptouchY": { - "description": "La variable de sistema ptouchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) del lienzo, en el cuadro anterior al actual. Esto funciona mejor con interacciones de un dedo a la vez. Para interacciones multi-dedo, usar el arreglo touches[]", - "returns": "el objeto p5" - }, - "winTouchX": { - "description": "La variable de sistema winTouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) de la ventana.", - "returns": "el objeto p5" - }, - "winTouchY": { - "description": "La variable de sistema winTouchY siempre contiene la posición vertical de un dedo, relativo al origen (0, 0) de la ventana.", - "returns": "el objeto p5" - }, - "pwinTouchX": { - "description": "La variable de sistema pwinTouchX siempre contiene la posición horizontal de un dedo, relativo al origen (0, 0) de la ventana, en el cuadro anterior al actual.", - "returns": "el objeto p5" - }, - "pwinTouchY": { - "description": "La variable de sistema pwinTouchY siempre contiene la posición verticañ de un dedo, relativo al origen (0, 0) de la ventana, en el cuadro anterior al actual.", - "returns": "el objeto p5" - }, - "touches[]": { - "description": "La variable de sistema touches[] contiene un arreglo de las posiciones de todos los puntos de toque actuales, relativos al origen (0, 0) del lienzo, y también identificadores para cada toque mientras se mueve. Cada elemento en el arreglo es un objeto con las propiedas x, y e identidad.", - "returns": "el objeto p5" - }, - "touchIsDown": { - "description": "La variable boolean de sistema touchIsDown es verdadera (true) si en la pantalla hay un toque y falsa (false) si no.", - "returns": "el objeto p5" - }, - "touchStarted": { - "description": "La función touchStarted() es llamada una vez, cada vez que un toque nuevo es registrado. Si la función touchStarted() no ha sido definida, la función mouseIsPressed() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "returns": "el objeto p5" - }, - "touchMoved": { - "description": "La función touchStarted() es llamada una vez, cada vez que es registrado el movimiento de un toque. Si la función touchMoved() no ha sido definida, la función mouseDragged() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "returns": "el objeto p5" - }, - "touchEnded": { - "description": "La función touchEnded() es llamada una vez, cada vez que un toque finaliza. Si la función touchEnded() no ha sido definida, la función mouseReleased() será llamada en su lugar, si es que está definida. Los navegadores tienen distintos comportamientos por defecto asociados a distintos eventos gatillados por toque. Para prevenir cualquier comportamiento por defecto para este evento, añade return false al final de este método.", - "returns": "el objeto p5" - }, - "createImage": { - "description": "Crea una nueva p5.Image (el tipo de datos para almacenar imágenes). Esto provee un nuevo buffer de pixeles para jugar. Define el tamaño del buffer con los parámetros de ancho y altuar. .pixels da acceso a un arreglo conteniendo los valores de todos los pixeles en la ventana mostrada. Estos valores son números. Este arreglo es del tamaño (incluyendo un factor apropiado de pixelDensity) de la ventana mostrada x4, representando los valroes R, G, B, A en orden para cada pixel., moviendo de izquierda a derecha en cada fila, y luego bajando de columna. Ver .pixels para mayor información. Podría ser más simple usar set() y get(). Antes de acceder a los pixeles de una imagen, los datos deben ser cargados con la función loadPixels(). Después de que el arreglo de datos ha sido modificado, la función updatePixels() debe ejecutarse para actualizar los cambios.", - "params": ["Entero: ancho en pixeles", - "Entero: altura en pixeles"], - "returns": "el objeto p5" - }, - "saveCanvas": { - "description": "Graba el lienzo actual como una imagen. En Safari, esto abrirá la imagen en la ventana y el usuario deberá proveer su propio nombre de archivo. Otros navegadores o grabarán el archivo de inmediato, o abrirán una ventana de diálogo.", - "params": ["Canvas seleccionado: una variable representando un canvas HTML5 específico (opcional)", - "String", - "String: jpg o png"], - "returns": "el objeto p5" - }, - "saveFrames": { - "description": "Captura una secuencia de cuadros que pueden ser usados para crear una película. Acepta una función callback. Por ejemplo, puedes querer mandar los cuadros a un servidor donde pueden ser almacenados o convertidos en una película. Si no se provee una función callback, el navegador abrirá varios diálogos tratando de descargar todas las imágenes que han sido creadas. Con una función callback provista, los datos de imagen no son grabados por defecto, sino que son pasados como argumento a la función callback como un arreglo de objetos, con el tamaño del arreglo siendo igual al número total de cuadros.", - "params": ["String: ", - "String: jpg o png", - "Número: duración en segundos para grabar los cuadros", - "Número: tasa de cuadros por segundo a grabar", - "Función: una función callback que será ejecutada para manejar los datos de imagen. Esta función deberá aceptar un arreglo como argumento. El arreglo contendrá el número especificado de cuadros como objetos. Cada objeto tiene tres propiedades: datos de imagen imageData, nombre del archivo y extensión"], - "returns": "el objeto p5" - }, "loadImage": { "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.", "params": ["문자열: 불러올 이미지 경로", @@ -970,727 +261,6 @@ "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표", "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비", "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"] - }, - "tint": { - "description": "Define el valor de relleno para mostrar imágenes. Las imágenes pueden ser teñidas en colores específicos o hacerse transparentes al incluir un valor alpha. Para aplicar transparencia a una imagen sin afectar su color, usa blanco como color de teñido y especifica un valor alpha. Por ejemplo, tint(255, 128) hará una imagen 50% transparente (asumiendo el rango alpha por defecto entre 0 y 255, el que puede ser modificado con la función colorMode()). El valor del parámetro gris debe ser menor o igual al actual valor máximo según lo especificado por colorMode(). El valor máximo por defecto es 255.", - "params": ["Número|Arreglo: valor de gris, rojo o tinte (dependiendo del modo de color actual), o un arreglo de colores", - "Número|Arreglo: valor de verde o saturación (dependiendo del modo de color actual)", - "Número|Arreglo: valor de azul o brillo (dependiendo del modo de color actual)", - "Número|Arreglo: opacidad del fondo"], - "returns": "el objeto p5" - }, - "noTint": { - "description": "Remueve el valor actual de relleno para mostrar imágenes y revierte a mostrar las imágenes con sus colores originales.", - "returns": "el objeto p5" - }, - "imageMode": { - "description": "Define el modo de imagen. Modifica la ubicación desde la que las imágenes son dibujadas, por medio de cambiar la manera en que los parámetros dados a image() son interpretados. El modo por defecto es imageMode(CORNER), que interpreta los paráemtros segundo y tercero de image() como la posición de la esquina superior izquierda de la imagen. Si se dan dos parámetros adicionales, son usados para definir el ancho y la altura la imagen. imageMode(CORNERS) interpreta los paráemtros segundo y tercero de image() como la ubicación de una esquina, y los parámetros cuarto y quinto como la ubicación de la esquina opuesta. imageMode(CENTER) interpreta los parámetros segundo y tercero de image() como el punto central de la imagen. Si dos parámetros adicionales son especificados, son usados para definir el ancho y la altura de la imagen.", - "params": ["Constante: puede ser CORNER, CORNERS, o CENTER"], - "returns": "el objeto p5" - }, - "pixels[]": { - "description": "Arreglo tipo Uint8ClampedArray conteniendo los valores de todos los pixeles en la ventana mostrada. Estos valores son números. Este arreglo es del tamaño (incluyendo el factor apropiado de pixelDensity) de la ventana desplegada x4, representando los valores R, G, B, A por cada pixel, moviéndose de izquierda a derecha en cada fila, bajando una columna a la vez. Los monitores Retina y otros de alta densidad tendrán más pixeles en el arreglo (por un factor de pixelDensity al cuadrado). Por ejemplo, si la imagen es de 100 x 100 pixeles, habrán 40.000 valores. En un monitor retina, habrán 160.000. Los primeros cuatro valores (índices 0 a 4) en el arreglo serán los valores R, G, B, A del pixel en la posición (0, 0). Los siguientes cuatro valores (índices 4 a 7) serán los valores R, G, B, A del pixel en la posición (1, 0). De forma más general, para definir los valores de un pixel en (x, y): TODO. Aunque el método descrito es complejo, es lo suficientemente flexible como para trabajar con cualquier densidad de pixeles. Notar que set() inmediatamente se hace cargo de definir los valores apropiados en el arreglo pixels[] para un (x, y) dado a cualquier densidad de pixeles, pero el desempeño puede ser no tan rápido cuando muchas modificaciones son hechas en el arreglo de pixeles. Antes de acceder a este arreglo, los datos deben ser cargados con la función loadPixels(). Después de que el arreglo de datos ha sido modificado, la función updatePixels() debe ser ejecutada para refrescar los cambios. Notar que este no es un arreglo standard de Javascript. Esto significa que las funciones Javascript como slice() o arrayCopy() no funcionan.", - "returns": "el objeto p5" - }, - "blend": { - "description": "Copia una región de pixeles de una imagen a otra, usando un modo específico de mezcla para hacer la operación. Los modos disponibles de mezcla son: BLEND | DARKEST | LIGHTEST | DIFFERENCE | MULTIPLY| EXCLUSION | SCREEN | REPLACE | OVERLAY | HARD_LIGHT | SOFT_LIGHT | DODGE | BURN | ADD | NORMAL", - "params": ["p5.Image: imagen fuente", - "Entero: coordenada x de la esquina superior izquierda de la fuente", - "Entero: coordenada y de la esquina superior izquierda de la fuente", - "Entero: ancho de la imagen fuente", - "Entero: altura de la imagen fuente", - "Entero: coordenada x de la esquina superior izquierda del destino", - "Entero: coordenada y de la esquina superior izquierda del destino", - "Entero: ancho de la imagen destino", - "Entero: altura de la imagen destino", - "Constante: el modo de mezcla"], - "returns": "el objeto p5" - }, - "copy": { - "description": "Copia una región del lienzo a otra región del lienzo desde una imagen usada como el parámetro srcImage en el lienzo. Si la fuente y el destino no son del mismo tamaño, automáticamente redimensionará los pixeles de la fuente para calzar con la región especificada como destino.", - "params": ["p5.Image: imagen fuente", - "Entero: coordenada x de la esquina superior izquierda de la fuente", - "Entero: coordenada y de la esquina superior izquierda de la fuente", - "Entero: ancho de la imagen fuente", - "Entero: altura de la imagen fuente", - "Entero: coordenada x de la esquina superior izquierda de destino", - "Entero: coordenada y de la esquina superior izquierda de destino", - "Entero: ancho de la imagen de destino", - "Entero: altura de la imagen de destino"], - "returns": "el objeto p5" - }, - "filter": { - "description": "Aplica un filtro al lienzo. Las opciones posibles son: THRESHOLD, que convierte la imagen a pixeles blancos y negros dependiendo de si están arriba o abajo del umbral definido por el parámetro. El parámetro debe estar entre 0.0 (negro) y 1.0 (blanco). Si no se especifica ningún valor, el valor por defecto es 0.5. GRAY, convierte cualquier color en la imagen a un equivalente en la escala de grises, no tiene parámetros. OPAQUE, hace que el canal alpha sea totalmente opaco, no tiene parámetros. INVERT, hace que cada pixel tenga su valor inverso, no tiene parámetros. POSTERIZE, limita cada canal de la imagen a un número de colores especificado como parámetro. El parámetro puede definir entre 2 y 255 valores, pero los resultados más notorios se dan con valores bajos. BLUR, hace que la imagen sea borrosa con un proceso Gaussiano, siendo el parámetro el nivel de cuán borroso es el resultado, si no se usa ningún parámetro, el parámetro por defecto es 1, a mayores valores es más borroso el resultado. ERODE, reduce las áreas claras, no tiene parámetros. DILATE, aumenta las áreas claras, no tiene parámetros.", - "params": ["Constante: ", - "Número: un parámetro opcional único a cada filtro, ver más arriba"], - "returns": "el objeto p5" - }, - "get": { - "description": "Retorna un arreglo de valores RGBA por cada pixel o toma una sección de una imagen. Si no especifican parámetros, se retorna la imagen entera. Usa los parámetros x e y para obtener el valor de un pixel. Toma una sección de la ventana mostrada si especificas los parámetros adicionales w y h. Cuando se obtiene una imagen, los parámetros x e y definen las coordenadas de la esquina superior izquierda de la imagen, sin importar el actual mode imagen definido por imageMode(). Si el pixel solicitado está fuera de la imagen, se retorna el valor [0, 0, 0, 255]. Para obtener los números escalados según los rangoes de color actuales y tomar en cuenta el modo de color según colorMode(), usa getColor() en vez de get(). Tomar el valor de un pixel con get(x, y) es fácil, pero no tan rápido como tomar los datos directamente desde pixels[]. La instrucción equivalente a get(x, y) usando pixels[] con densidad de pixeles d es var off = (y width + x) d * 4; [pixels[off], pixels[off+1], pixels[off+2], pixels[off+3]]. Ver la referencia de pixels[] para mayor información.", - "params": ["Número: coordenada x del pixel", - "Número: coordenada y del pixel", - "Número: ancho", - "Número: altura"], - "returns": "Arreglo|p5.Image: valores de pixel en la posición (x, y) en formato arreglo RGBAs o p5.Image" - }, - "loadPixels": { - "description": "Carga los datos de los pixeles en pantalla al arreglo pixels[]. Esta función siempre debe ser llamada antes de leer o escribir en el arreglo pixels[]", - "returns": "el objeto p5" - }, - "set": { - "description": "Cambia el color de cualquier pixel, o pone una imagen directamente en la ventana. Los parámetros x e y especifican el pixel a cambiar y c especifica el valor del color. Puede ser un objeto p5.Color o un arreglo de pixeles RGBA. También puede ser un valor único en escala de grises. Cuando se define una imagen, los parámetros x e y definen las coordenadas de la esquina superior izquierda de la imagen, sin importar el modo actual de imagen según imageMode(). Después de usar set(), debes llamar a updatePixels()' para que tus cambios aparezcan. Esta función debería ser llamada una vez que todos los pixeles han sido definidos. Definir el color de un solo pixel con set(x, y) es fácil, pero es tan rápido como poner los datos directamente en el arreglo pixels[]. Definir los valores de pixels[] directamente puede ser complicado cuando se trabaja con un monitor retina, pero tendrá un mejor desempeño cuando muchos pixeles necesiten ser definidos directamente en cada iteración. Ver la referencia de pixels[] para mayor información.", - "params": ["Número: coordenada x del pixel", - "Número: coordenada x del pixel", - "Número: coordenada y del pixel", - "Número|Arreglo|Objeto: inserta un valor en escala de grises | un arreglo de pixeles | un objeto p5.Color | un objeto p5.Image a copiar"], - "returns": "el objeto p5" - }, - "updatePixels": { - "example": "", - - "description": "Actualiza la ventana mostrada con los datos del arreglo pixels[]. Se usa en conjunto con loadPixels(). Si solo estás leyendo pixeles desde el arreglo, no hay necesidad de llamar a updatePixels() - actualizar es solo necesario para aplicar cambios. updatePixels() debe ser llamada cada vez que el arreglo de pixeles es manipulado o si se llama a la función set().", - "params": ["Número: coordenada x de la esquina superior izquierda de la región a actualizar", - "Número: coordenada y de la esquina superior izquierda de la región a actualizar", - "Número: ancho de la región a actualizar", - "Número: altura de la región a actualizar"], - "returns": "el objeto p5" - }, - "loadFont": { - "description": "Carga un archivo de fuente de letra (.otf, .ttf) desde un archivo o URL, y retorna un objeto PFont. Este método es asíncrono, lo que significa que puede que no finalice antes de que la siguiente línea en tu bosquejo sea ejecutada. La ubicación del archivo debe ser relativo al archivo HTML que lo vincula con tu bosquejo. Cargar desde una URL u otra ubicación remota puede ser bloqueado por las opciones de seguridad del navegador.", - "params": ["String: número del archivo o URL a cargar", - "Función: función a ser ejecutada después de que loadFont() es completada"], - "returns": "Objeto: objeto p5.Font" - }, - "loadJSON": { - "description": "Carga un archivo JSON desde un archivo o una URL, y retorna un objeto o un arreglo. Este método es asíncrono, lo que significa que puede que no termine antes que se ejecute la siguiente línea en tu bosquejo.", - "params": ["String: nombre de archivo o URL a cargar", - "Función: función a ser ejecutada después de que loadJSON() finalice, los datos son pasados como primer argumento", - "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento", - "String: json o jsonp"], - "returns": "Objeto|Arreglo: datos JSON" - }, - "loadStrings": { - "description": "Lee los contenidos de un archivo y crea un arreglo de Strings de sus líneas individuales. Si el nombre del archivo es usado como parámetro, como en el ejemplo anterior, el archivo debe estar ubicado en el directorio del bosquejo. Alternativamente, el archivo puede ser cargado desde cualquier lugar del computador local usando una dirección absoluta (empieza con / en Unix y Linux, o una letra representando el disco en Windows), o el parámetro de nombre de archivo puede ser una URL donde esté el archivo dentro de una red. Este método es asíncrono, lo que significa que puede ser que su ejecución no termine antes de que se ejecute la siguiente línea del bosquejo.", - "params": ["String: nombre de archivo o URL a cargar", - "Función: función a ser ejecutada después de que loadStrings() finalice, el arreglo es pasado como primer argumento", - "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], - "returns": "Arreglo: un arreglo de Strings" - }, - "loadTable": { - "description": "Lee los contenidos de un archivo o URL y crea un objeto p5.Table con sus valores. Si un archivo es especificado, debe ser ubicado en el directorio data del bosquejo. El parámetro de nombre de archivo puede también ser una URL de un archivo en línea. Por defecto, se asume que el archivo está separado por comas (formato CSV), La tabla sólo busca una fila de encabezado si es que se incluye la opción header. Las opciones posibles incluyen: csv: se procesan los datos como valores separados por comas, tsv: se procesan los datos como separados por tabulación, header: la tabla tiene una fila de encabezados (títulos). Si se incluyenn múltiples opciones, se deben ingresar como parámetros separados por comas. Todos los archivos son cargados y grabados usando codificación UTF-8. Este método es asíncrono, lo que significa que su ejecución puede no haber terminado antes de que se ejecute la siguiente línea del bosquejo. Si se llama a loadTable() dentro de preload() se garantiza que se complete la operación antes de que setup() y draw() sean llamadas. Fuera de preload(), puedes suplir una función callback para manejar el objeto.", - "params": ["String: nombre de archivo o URL a cargar", - "String|Strings: header, csv, tsv", - "Función: función a ser ejecutada después de que loadTable() finalice, el arreglo es pasado como primer argumento. Si es exitosa, el objeto Table es pasado como primer argumento, en caso contrario se pasa el valor boolean false."], - "returns": "Objeto Table conteniendo los datos" - }, - "loadXML": { - "description": "Lee los contenidos de un archivo y crea un objeto XML con sus valores. Si el nombre del archivo es usado como parámetro, el archivo debe estar ubicado en el directorio del bosquejo. Alternativamente, el archivo puede ser cargado desde cualquier lugar del computador local usando una dirección absoluta (que empieza con / en Unix y Linux, o con una letra que simbolice el disco duro en Windows). También se puede usar como parámetro de nombre de archivo una URL para un archivo en una red. Este método es asíncrono, lo que significa que su ejecución puede no estar completa antes de que se ejecute la siguiente línea de código en el bosquejo. Llamar a loadXML() dentro de preload() garantiza que la operación se complete antes de que setup() y draw() sean llamados. Fuera de preload(), puedes suplir una función callBack para manejar el objeto.", - "params": ["String: nombre de archivo o URL a cargar", - "Función: función a ser ejecutada después de que loadXML() finalice, el objeto XML es pasado como primer argumento", - "Función: la función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], - "returns": "objeto XML que contiene los datos" - }, - "httpGet": { - "description": "Método para ejecutar una solicitud HTTP GET. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto.", - "params": ["String: nombre del archivo o URL a cargar", - "Objeto: parámetro de datos pasados con la solicitud enviada", - "String: json, jsonp, xml o text", - "Función: función a ser ejecutada después de que httpGet() finalice, los datos son pasados como primer argumento", - "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], - "returns": "el objeto p5" - }, - "httpPost": { - "description": "Método para ejecutar una solicitud HTTP POST. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto.", - "params": ["String: nombre del archivo o URL a cargar", - "Objeto: parámetro de datos pasados con la solicitud enviada", - "String: json, jsonp, xml o text", - "Función: función a ser ejecutada después de que httpPost() finalice, los datos son pasados como primer argumento", - "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], - "returns": "el objeto p5" - }, - "httpDo": { - "description": "Método para ejecutar una solicitud HTTP. Si no se especifica el tipo de datos, p5 tratará de adivinar basándose en la URL, usando texto por defecto. También puedes pasar un objeto especificando todos los parámetros de la solicitud siguiendo los ejemplos dentro de las llamadas de reqwest()", - "params": ["String: nombre del archivo o URL a cargar", - "Objeto: parámetro de datos pasados con la solicitud enviada", - "String: json, jsonp, xml o text", - "Función: función a ser ejecutada después de que httpDo() finalice, los datos son pasados como primer argumento", - "Función: función a ser ejecutada si es que hay un error, la respuesta es pasada como primer argumento"], - "returns": "el objeto p5" - }, - "save": { - "description": "Graba una imagen, text, json, csv, wav o html. Hace que la descarga ocurra en el computador cliente. Notar que no es recomendado llamar a save() dentro de draw() si está en bucle, porque la función save() abrirá una ventana de diálogo en cada cuadro. El comportamiento por defecto es grabar el lienzo como una imagen. Puedes opcionalmente especificar un nombre de archivo. Por ejemplo: TODO. Alternativamente, el primer parámetro puede ser un puntero a un lienzo p5.Element, un arreglo de Strings, un arreglo de JSON, un objeto JSON, un p5.Table, un p5.Image, o un p5.SoundFile (requiere p5.sound). El segundo parámetro es el nombre del archivo (incluyendo la extensión). El tercer parámetro es para opciones específicas a este tipo de objeto. Este método grabará un archivo que se austa a los parámetros dados. Por ejemplo: TODO. ", - "params": ["Objeto|String: si se provee un nombre de archivo, se grabará el lienzo como una imagen con la extensión png o jpg, dependiendo del nombre del archivo. Si se provee un objeto, se grabará dependiendo del objeto y el nombre del archivo (ver los ejemplos anteriores)", - "String: Si se provee un objeto como el primer parámetro, entonces el segundo parámetro indica el nombre del archivo, y debe incluir la extensión apropiada (ver los ejemplos anteriores).", - "Boolean|String: opciones adicionales depndiendo del tipo de archivo. Por ejemplo, cuando se graba un archivo JSON, true indica que la salida será optimizada según el tamaño del archivo, en vez de por legibilidad."], - "returns": "el objeto p5" - }, - "saveJSON": { - "description": "Escribe los contenidos de un arreglo o un objeto JSON a un archivo .json. El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", - "params": ["Arreglo|Objeto:", - "String: ", - "Boolean: si es verdadero (true), remueve los saltos de línea del archivo de salida para optimizar el tamaño del archivo, en desmedro de la legibilidad."], - "returns": "el objeto p5" - }, - "saveStrings": { - "description": "Escribe un arreglo de Strings a un archivo de texto, una línea por String. El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", - "params": ["Arreglo: arreglo de Strings a ser escrito", - "String: nombre del archivo de salida"], - "returns": "el objeto p5" - }, - "saveTable": { - "description": "Escribe los contenidos de un objeto Table a un archivo. Por defecto es un archivo de texto con valores separados por coma (csv), pero también puede usar separación por tabulación (tsv), o generar una tabla HTML (html). El proceso de grabación del archivo y su ubicación pueden variar entre navegadores web.", - "params": ["Table: el objeto Table a ser grabado en un archivo", - "String: el nombre del archivo en el que Table será grabado", - "String: puede ser tsv, csv o html."], - "returns": "el objeto p5" - }, - "p5.Table": { - "description": "Los objetos Table almacenan datos con múltiples filas y columnas, tal como una hoja de cálculo tradicional. Los objetos Table pueden ser generados desde cero, dinámicamente, o usando datos desde un archivo existente.", - "params": ["Arreglo: un arreglo de objetos p5.TableRow"], - "returns": "p5.Table: el objeto p5.Table generado" - }, - "p5.TableRow": { - "description": "Un objeto TableRow representa una única fila de datos, grabados en columnas, de una tabla. Un objeto TableRow contiene tanto un arreglo ordenado, como un objeto JSON desordenado.", - "params": ["String: opcional, puebla la fila con una serie de valores, separados por el separador", - "String: por defecto, valores separados por coma (csv)"], - "returns": "el objeto p5" - }, - "day": { - "description": "p5.js se comunica con el reloj de tu computador. La función day() retorna el día actual como un valor entre 1 y 31.", - "returns": "Número: el día actual" - }, - "hour": { - "description": "p5.js se comunica con el reloj de tu computador. La función hour() retorna la hora actual como un valor entre 0 y 23.", - "returns": "Número: la hora actual" - }, - "minute": { - "description": "p5.js se comunica con el reloj de tu computador. La función minute() retorna el minuto actual como un valor entre 0 y 59.", - "returns": "Número: el minuto actual" - }, - "millis": { - "description": "Retorna el número de milisegundos (milésimas de segundo) desde que el programa empezó a correr. La información es usada a menudo para temporizar eventos y animar secuencias", - "returns": "Número: el número de milisegundos desde que empezó el programa" - }, - "month": { - "description": "p5.js se comunica con el reloj de tu computador. La función month() retorna el mes actual como un valor entre 1 y 12.", - "returns": "Número: el mes actual" - }, - "second": { - "description": "p5.js se comunica con el reloj de tu computador. La función second() retorna el mes actual como un valor entre 0 y 59.", - "returns": "Número: el segundo actual" - }, - "year": { - "description": "p5.js se comunica con el reloj de tu computador. La función year() retorna el año actual como un entero (2014, 2015, 2015, etc).", - "returns": "Número: el año actual" - }, - "p5.XML": { - "description": "XML es una representación de un objeto XML, capaz de procesar código XML. Usa loadXML() para cargar archivos externos XML y crear objetos XML", - "params": ["String:"], - "returns": "p5.XML: el objeto p5.XML generado" - }, - "createVector": { - "description": "Crea un nuevo objeto p5.Vector (el tipo de datos para almacenar vectores). Esto provee un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección.", - "params": ["Número: componente x del vector", - "Número: componente y del vector", - "Número: componente z del vector"], - "returns": "el objeto p5" - }, - "p5.Vector": { - "description": "Una clase para describir un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección. El tipo de datos, sin embargo, graba los componentes del vector (x, y para 2D y x,y,z para 3D). La magnitud y la dirección pueden ser calculados con los métodos mag() y heading(). En muchos de los ejemplos de p5.js, verás que p5.Vector es usado para describir una posición, velocidad o aceleración. Por ejemplo, si consideras un rectángulo moviéndose a lo largo de la pantalla, en cada instante tiene una posición (un vector que apunta desde el origen hasta su ubicación), una velocidad(la tasa a la que la posición del objeto cambia por unidad de tiempo, expresada como vector), y aceleración (la tasa a la que la velocidad del objeto cambia por unidad de tiempo, expresada como vector). Como los vectores representan grupos de valores, no podemos simplemente usar las operaciones tradicionales de adición, multiplicación, etc. En vez de eso, necesitaremos hacer matemática de vectores, lo que es simplificado con los métodos dentro de la clase p5.Vector.", - "params": ["Número: componente x del vector", - "Número: componente y del vector", - "Número: componente z del vector"], - "returns": "el objeto p5" - }, - "abs": { - "description": "Calcula el valor absoluto (magnitud) de un número. Usa Math.abs(). El valor absoluto de un número es siempre positivo.", - "params": ["Número: número a computar"], - "returns": "Número: valor absoluto del número dado" - }, - "ceil": { - "description": "Calcula el entero más cercano que es mayor o igual que el valor del paráemtro. Usa Math.ceil(). Por ejemplo, ceil(9.03) retorna el valor 10.", - "params": ["Número: número a redondear"], - "returns": "Número: número redondeado hacia arriba" - }, - "constrain": { - "description": "Restringe un valor a estar entre un valor mínimo y uno máximo.", - "params": ["Número: número a restringir", - "Número: límite mínimo", - "Número: límite máximo"], - "returns": "Número: número restringido" - }, - "dist": { - "description": "Calcula la distancia entre dos puntos", - "params": ["Número: la coordenada x del primer punto", - "Número: la coordenada y del primer punto", - "Número: la coordenada z del primer punto", - "Número: la coordenada x del segundo punto", - "Número: la coordenada y del segundo punto", - "Número: la coordenada z del segundo punto"], - "returns": "Número: distancia entre los dos puntos" - }, - "exp": { - "description": "Retorna el número de Euler (2.71828...) elevado al parámetro n. Usa Math.exp().", - "params": ["Número: exponente a elevar"], - "returns": "e^n" - }, - "floor": { - "description": "Calcula el valor entero más cercano que es menor o igual al parámetro. Usa Math.floor().", - "params": ["Número: número a ser redondeado hacia abajo"], - "returns": "Número: número redondeado hacia abajo" - }, - "lerp": { - "description": "Calcula un número entre dos números a un incremento específico. El parámetro amt es la cantidad a interpolar entre los dos valores donde 0.0 es igual al primer punto, 0.1 está muy cerca del primer punto, 0.5 está a medio camino entre ambos números, etc. La función lerp es conveniente para crear movimiento a lo largo de un camino recto y para dibujar líneas punteadas.", - "params": ["Número: primer valor", - "Número: segundo valor", - "Número: número entre 0.0 y 1.0"], - "returns": "Número: valor interpolado" - }, - "log": { - "description": "Calcula el logaritmo natural (logaritmo con base e) de un número. Esta función espera que el parámetro n sea de un valor más grande que 0.0. Usa Math.log().", - "params": ["Número: número más grande que 0"], - "returns": "Número: logaritmo naturla de n" - }, - "mag": { - "description": "Calcula la magnitud (o tamaño) de un vector. Un vector es una dirección en el espacio comúnmente usada en gráfica computacional y álgebra lineal. Como no tiene posición de inicio, la magnitud del vector puede ser pensada como la distancia entre la coordenada 0,0 a su valor x,y. Por lo tanto, mag() es un atajo a escribir dist(0, 0, x, y).", - "params": ["Número: primer valor", - "Número: segundo valor"], - "returns": "Número: magnitud del vector entre (0, 0) y (a, b)" - }, - "map": { - "description": "Escala un nombre de un rango a otro rango. En el primer ejemplo anterior, el número 25 es convertido de un valor en el rango entre 0 y 100 a un valor cuyo rango está entre el borde izquierdo de la ventana (0) y el borde derecho (ancho).", - "params": ["Número: el valor a ser convertido", - "Número: límite inferior del rango actual", - "Número: límite superior del rango actual", - "Número: límite inferior del rango deseado", - "Número: límite superior del rango deseado"], - "returns": "Número: número escalado" - }, - "max": { - "description": "Determina el valor más grande en una secuencia de números, y luego retorna ese valor. max() acepta cualquier número de parámetros tipo número, o un arreglo de cualquier largo.", - "params": ["Número|Arreglo: números a comparar"], - "returns": "Número: número máximo" - }, - "min": { - "description": "Determina el valor más pequeño en una secuencia de números, y luego retorna ese valor. max() acepta cualquier número de parámetros tipo número, o un arreglo de cualquier largo.", - "params": ["Número|Arreglo: números a comparar"], - "returns": "Número: número mínimo" - }, - "norm": { - "description": "Normaliza un número de un rango a otro rango entre 0 y 1. Es idéntico a map(value, low, high, 0, 1). Los números fuera del rango no son saturados a 0 o 1, porque los números fuera de rango son muchas veces intencionales y útiles (ver el segundo ejemplo más arriba)", - "params": ["Número: valor entrante a ser normalizado", - "Número: límite inferior del rango actual", - "Número: límite superior del rango actual"], - "returns": "Número: número normalizado" - }, - "pow": { - "description": "Facilita las expresiones exponenciales. La función pow() es una manera eficiente de multiplicar números po sí mismos (o sus recíprocos) en grandes cantidades. Por ejemplo, pow(3, 5) es equivalente a la expresión 3*3*3*3*3 y pow (3, -5) es equivalente a 1/3*3*3*3*3. Usa Math.pow().", - "params": ["Número: base de la expresión exponencial", - "Número: potencia a la que se eleva la base"], - "returns": "n^e" - }, - "round": { - "description": "Calcula el entero más cercano al parámetro n. Por ejemplo, round(133.8) retorna el valor 134. Usa la función Math.round().", - "params": ["Número: número a redondear"], - "returns": "Número: número redondeado" - }, - "sq": { - "description": "Eleva al cuadrado un número (lo multiplica por sí mismo), El resultado es siempre un número positivo, porque multiplicar dos números negativos siempre resulta en un número positivo.", - "params": ["Número: número a elevar al cuadrado"], - "returns": "Número: número elevado al cuadrado" - }, - "sqrt": { - "description": "Calcula la raíz cuadrada de un número. La raíz cuadrada de un número es siempre positiva, aunque puede haber una raíz cuadrada válida que sea negativa. La raíz cuadrada s de un número a es tal que s*s = a. Es lo opuesto a elevar al cuadrado. Usa Math.sqrt().", - "params": ["Número: número no negativo al que se le calcula la raíz cuadrada"], - "returns": "Número: raíz cuadrada del número" - }, - "noise": { - "description": "Retorna el valor del ruido Perlin en las coordenadas específicas. El ruido Perlin es un generador de secuencias aleatorias produciendo una sucesión de números más naturalmente ordenada y armónica, en comparación con la función estándar random(). Fue inventada por Ken Perlin en los 1980s y ha sido usada desde entonces en aplicaciones gráficas para producir texturas procedurales, movimiento natural, figuras, terrenos, etc. La principal diferencia con la función random() es definida en una espacio infinito n-dimensional donde cada par de coordenadas corresponde a un valor fijo semi-aleatorio (fijado solo durante el tiempo de vida del programa; ver la función noiseSeed()). p5.js puede calcular ruido 1D, 2D y 3D, dependiendo del número de coordenadas dado. El valor resultante siempre estará entre 0.0 y 1.0. El valor de ruido puede ser animado moviéndose a través del espacio del ruido como fue demostrado en el ejemplo superior. Las dimensiones segunda y tercera también pueden ser interpretadas como tiempo. El ruido está estructurado de forma similar a una señal de audio, con respecto al uso de la función de las frecuencias. De forma similar al conecpto de armónicas en física, el ruido Perlin es calculado a lo largo de varias octavas que se han sumado para dar forma al resultado final. Otra manera de ajustar el caracter de la secuencia resultante es la escala de las coordenadas de entrada. Como la función trabaja en un espacio infinito, el valor de las coordenadas no importa como tal, solo la distancia entre las coordenadas sucesivas importa (por ejemplo: cuando se usa noise() dentro de un bucle). Como regla general, a menor la diferencia entre coordenadas, más suave es el ruido resultante. Pasos entre 0.005 y 0.03 funcionan mejor para la mayor parte de las aplicaciones, pero esto diferirá dependiendo del uso.", - "params": ["Número: coordenada x en el espacio del ruido", - "Número: coordenada y en el espacio del ruido", - "Número: coordenada z en el espacio del ruido"], - "returns": "valor de ruido Perlin (entre 0 y 1) en las coordenadas especificadas" - }, - "noiseDetail": { - "description": "Ajusta el caracter y nivel de detalle producido por la función de ruido Perlin. Similar al concepto de armónicas en física, el ruido es calculado a lo largo de varias octavas. Las octavas más graves contribuyen de forma más significativa a la señal de salida y como define la intensidad general del ruido, mientras que las octavas más altas crean detalles más finos en la secuencia de ruido. Por defecto, el ruido es calculado a lo largo de 4 octavas, con cada octava contribuyendo exactamente la mitad que su predecesora, partiendo con una intensidad de 50% para la primera octava. Este tamaño de caída puede ser cambiado al añadir un parámetro adicional a la función. Por ejemplo, un factor de caída de 75% significa que cada octava tendrá un 75% de impacto (25% menos) que la octava anterior. Cualquier valor entre 0.0 y 1.0 es válido, sin embargo nota que valores superiores a 0.5 pueden resultar en que noise() retorne valores mayores a 1.0. Al cambiar estos parámetros, la señal creada por noise() puede ser adaptada para calzar con necesidades y características específicas.", - "params": ["Número: número de octavas a ser usadas por el ruido", - "Número: factor de caída para cada octava"], - "returns": "el objeto p5" - }, - "noiseSeed": { - "description": "Define el valor semilla para la función noise(). Por defecto, noise() produce diferentes resultados cada vez que el programa es ejecutado. Defines el parámetro value a una constante para que retorne la misma secuencia de números pseudo-aleatorios cada vez que el programa es ejecutado", - "params": ["Número: el valor semilla"], - "returns": "el objeto p5" - }, - "acos": { - "description": "El inverso de la función cos(), retorna el arcocoseno de un valor. Esta función espera valores entre -1 y 1 y los valores retornados están en el rango entre 0 y PI (3.1415927).", - "params": ["Número: el valor al que se aplica arcocoseno"], - "returns": "Número: el arcocoseno del valor" - }, - "asin": { - "description": "El inverso de la función sin(), retorna el arcoseno de un valor. Esta función espera valores entre -1 y 1 y los valores retornados están en el rango entre -PI/2 y PI/2 .", - "params": ["Número: el valor al que se aplica arcoseno"], - "returns": "Número: el arcoseno del valor" - }, - "atan": { - "description": "El inverso de la función tan(), retorna el arcotangente de un valor. Esta función espera valores entre -Infinito e Infinito (exclusivo) y los valores retornados están en el rango entre -PI/2 y PI/2 .", - "params": ["Número: el valor al que se aplica arcotangente"], - "returns": "Número: el arcotangente del valor" - }, - "atan2": { - "description": "Calcula el ángulo (en radianes) desde un punto específico al origen, medido desde el eje x positivo. Los valores retornados son de tipo float entre -PI/2 y PI/2. La función atan2() es más frecuentemente usada para orientar figuras figuras geométricas según la posición del cursor. Nota: la coordenada y del punto es el primer parámetro, y la coordenada x es el segundo parámetro, debido a la estructura para calcular la tangente.", - "params": ["Número: coordenada y del punto", - "Número: coordenada x del punto"], - "returns": "Número: el arcotangente del punto dado" - }, - "cos": { - "description": "calcula el coseno de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", - "params": ["Número: el ángulo"], - "returns": "Número: el coseno del ángulo" - }, - "sin": { - "description": "calcula el seno de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", - "params": ["Número: el ángulo"], - "returns": "Número: el seno del ángulo" - }, - "tan": { - "description": "calcula la tangente de un ángulo. Esta función toma en cuenta el modo actual de ángulo según angleMode(). Los valores son retornados en el rango entre -1 y 1.", - "params": ["Número: el ángulo"], - "returns": "Número: la tangente del ángulo" - }, - "degrees": { - "description": "Convierte una medida en radianes a su correspondiente valor en grados. Radianes y grados son dos maneras de calcular lo mismo. Hay 360 grados en un círculo y 2*PI radianes en un círculo. Por ejemplo, 90 grados equivalen a PI/2 radianes.", - "params": ["Número: valor en radianes a ser convertido a grados."], - "returns": "el ángulo convertido" - }, - "radians": { - "description": "Convierte una medida en grados a su correspondiente valor en radianes. Radianes y grados son dos maneras de calcular lo mismo. Hay 360 grados en un círculo y 2*PI radianes en un círculo. Por ejemplo, 90 grados equivalen a PI/2 radianes.", - "params": ["Número: valor en grados a ser convertido a radianes."], - "returns": "el ángulo convertido" - }, - "angleMode": { - "description": "Define el modo actual de p5 para interpretar ángulos. El modo por defecto es en RADIANS (radianes).", - "params": ["CONSTANTE: puede ser RADIANS (radianes) o DEGREES (grados)"], - "returns": "el objeto p5" - }, - "randomSeed": { - "description": "Define la semilla para la función random(). Por defecto, la función random() produce diferentes resultados cada vez que el programa es ejecutado. Definir el parámetro semilla como una constante hace que retorne la misma secuencia de números pseudo-aleatorios cada vez que el programa es ejecutado.", - "params": ["Número: el valor semilla"], - "returns": "el objeto p5" - }, - "random": { - "description": "Retorna un número aleaotorio de tipo float (punto flotante). Acepta 0, 1 o 2 argumentos. Si no se le da un argumento, retorna un número aleatorio entre 0 y 1 (sin incluir 1). Si se da un argumento y es un número, retorna un número aleatorio entre 0 y hasta (pero sin incluir) el parámetro. Si se da un argumento y es un arreglo, retorna una elemento al azar del arreglo. Si se dan dos argumentos, retorna un número aleatorio entre el primer argumento y hasta (pero sin incluir) el segundo argumento.", - "params": ["Número: el límite inferior (inclusivo)", - "Número: el límite superio (exclusivo)", - "Arreglo: el arreglo del cual se elige"], - "returns": "Número: el número aleatorio o un elemento aleatorio de un conjunto de opciones" - }, - "randomGaussian": { - "description": "Retorna un número aleatorio ajjustado a una distribución Gaussiana o normal. No existe teóricamente un valor mínimo o máximo que la función randomGaussian() pueda retornar. En vez de eso, existe solo una muy baja probabilidad de retornar valores lejos de la media, y una alta probabilidad de retornar números cercanos a la media. Acepta 0, 1 o 2 argumentos. Si no tiene argumentos, retorna una media de 0 y una desviación estándar de 1. Si tiene un argumento, el argumento es la media (y la desviación estándar es 1). Si tiene dos argumentos, el primero es la media y el segundo es la desviación estándar.", - "params": ["Número: la media", - "Número: la desviación estándar"], - "returns": "el número aleatorio" - }, - "textAlign": { - "description": "Define el alineamiento actual para dibujar texto. Acepta dos argumentos: horizAlign(LEFT, CENTER o RIGHT) y vertAlign(TOP, BOTTOM, CENTER, o BASELINE). El parámetro horizAlign se refiere al valor x de la función text(), mientras que vel parámetro vertAlign al valor y. Así que si escribes textAlign(LEFT), estás alineando el borde izquierdo de tu texto al valor x dado en la función text(). Si escribes textAlign(RIGHT, TOP), estás alineando el borde derecho de tu texto con el valor x y el borde superior con el valor y del texto.", - "params": ["Constante: alineamiento horizontal, puede ser LEFT, CENTER o RIGHT", - "Constante: alineamiento vertical, puede ser TOP, BOTTOM, CENTER o BASELINE"], - "returns": "el objeto p5" - }, - "textLeading": { - "description": "Define o retorna el espaciado, en pixeles, entre líneas de texto. Esta configuración será usada en todas las llamadas posteriores a la función text().", - "params": ["Número: el tamaño en pixeles de espaciamiento entre líneas"], - "returns": "el objeto p5" - }, - "textSize": { - "description": "Define o retorna el tamaño actual de la tipografía. Este tamaño será usado en todas las llamadas posteriores a la función text(). El tamaño de la tipografía es medido en pixeles.", - "params": ["Número: el tamaño en pixeles de las letras en pixeles"], - "returns": "el objeto p5" - }, - "textStyle": { - "description": "Define o retorna el estilo actual de la tipografía. Puede ser NORMAL (normal), ITALIC (cursivo) o BOLD (destacado). Notar que puede ser anulado por estilo CSS. Para tipografías que no sean de sistema (opentype, truetype, etc.), usa loadFont().", - "params": ["Número|Constante: estilo del texto, puede ser NORMAL, ITALIC o BOLD"], - "returns": "el objeto p5" - }, - "textWidth": { - "description": "Calcula y retorna el ancho de cualquier caracter o string.", - "params": ["String: el String de caracteres a medir"], - "returns": "Número" - }, - "text": { - "description": "Dibuja texto en la pantalla. Muestra la información especificada en el primer parámetro en la pantalla, en la posición especificada por los parámetros adicionales. Una fuente por defecto será usada a menos que una fuente sea definida por la función textFont() y un tamaño por defecto será usado a menos que se use la función textSize(). Cambia el color del texto con la función fill(). Cambia la apariencia del texto con las funciones stroke() y strokeWeight(). El texto se muestra en relación a la función textAlign(), que da la opción de dibujar a la izuiqerda, derecha y centro de las coordenadas. Los parámetros x2 e y2 definen un área rectangular donde mostrar el texto y solo puede ser usado por los datos tipo String. Cuando estos parámetros son especificados, son interpretados según la configuración de rectMode(). El texto que no cabe completamente dentro del rectángulo especificado no será dibujado en pantalla.", - "params": ["String: símbolos alfanuméricos a ser mostrados", - "Número: coordenada x del texto", - "Número: coordenada y del texto", - "Número: por defecto, el ancho de la caja contenedora del texto, ver rectMode() para más información", - "Número: por defecto, la altura de la caja contenedora del texto, ver rectMode() para más información"], - "returns": "Objeto" - }, - "textFont": { - "description": "Define la función actual con la que se dibujará el contenido de la función text()", - "params": ["Objeto|String: una fuente cargada con loadFont(), o un String representando una tipografía segura de la web (una fuente ampliamente disponible a lo largo de todos los sistemas)."], - "returns": "Objeto" - }, - "p5.Font": { - "description": "Clase base para manipulación de tipografía", - "params": ["Objeto: puntero a la instancia p5"], - "returns": "el objeto p5" - }, - "append": { - "description": "Añade un valor al final de un arreglo. Extiende el largo de un arreglo en una unidad. Usa la función Array.push()", - "params": ["Arreglo: Arreglo al que se agregará el dato", - "Cualquiera: a ser añadido al arreglo"], - "returns": "el objeto p5" - }, - "arrayCopy": { - "description": "Copia el arreglo (o una parte del arreglo) a otro arreglo. El arreglo fuente es copiado al arreglo de destino, empezando por la posición especificada por srcPosition y a la posición especificada por dstPosition. El número de elementos a copiar es determinado por el largo. Notar que al copiar valores se sobreescriben los valores existentes en el arreglo de destino. Para anexar valores en vez de sobreescribirlos, usa la función concat(). La versión simplificada con dos argumentos, arrayCopy(src, dest), copia un arreglo entero a otro del mismo tamaño. Es equivaletne a arrayCopy(src, 0, dst, 0, src.length). Usar esta función es mucho más eficiente para copiar datos de un arreglo que iterar con un bucle for() y copiar cada elemento individualmente. ", - "params": ["Arreglo: el arreglo fuente", - "Número: posición inicial en el arreglo fuente", - "Arreglo: el arreglo de destino", - "Número: posición inicial del arreglo de destino", - "Número: númeor de elementos del arreglo a ser copiados"], - "returns": "el objeto p5" - }, - "concat": { - "description": "Concatena dos arreglos, usa la función Array.concat(). No modifica los arreglos de entrada.", - "params": ["Arreglo: primer arreglo a concatenar", - "Arreglo: segundo arreglo a concatenar"], - "returns": "Arreglo: el arreglo concatenado" - }, - "reverse": { - "description": "Invierte el orden un arreglo, usa Array.reverse().", - "params": ["Arreglo: arreglo a ser invertido"], - "returns": "el objeto p5" - }, - "shorten": { - "description": "Disminuye un arreglo en un elemento y retorna el arreglo más corto, usa Array.pop().", - "params": ["Lista: arreglo a acortar"], - "returns": "Arreglo: el arreglo acortado" - }, - "shuffle": { - "description": "Ordena aleatoriamente los elementos de un arreglo. Implementa el algoritmo Fisher Yates.", - "params": ["Arreglo: Arreglo a ordenar", - "Boolean: modifica el arreglo"], - "returns": "Arreglo: retorna el arreglo ordenado" - }, - "sort": { - "description": "Ordena un arreglo de números, desde el más pequeño al más grande, o pone un arreglo de palabras en orden alfabético. El arreglo original no es modificado, un nuevo arreglo ordenado es retornado. El parámetro count define el número de elementos a ordenar. Por ejemplo, si hay 12 elementos en un arreglo y count es 5, los primeros 5 elementos del arreglo serán ordenados.", - "params": ["Arreglo: arreglo a ordenar", - "Número: número de elementos a ordenar, empezando desde 0"], - "returns": "el objeto p5" - }, - "splice": { - "description": "Inserta un valor o un arreglo de valores en un arreglo existente El primer parámetro especifica el arreglo inicial a ser modificado, y el segundo parámetro define los datos a insertarse. El tercer parámetro es un índice que especifica la posición del arreglo a partir de la que se insertarán los datos. Recuerda que el índice del arreglo empieza en 0, así que la primera posición es 0, la segunda es 1, etc.", - "params": ["Arreglo: arreglo a ser modificado", - "Cualquiera: valor a ser introducido", - "Número: posición del arreglo donde se inserta el dato"], - "returns": "el objeto p5" - }, - "subset": { - "description": "Extrae un arreglo de elementos de un arreglo existente. El parámetro list define el arreglo desde el cual los elementos serán copiados, y los parámetros start y count especifican cuáles elementos extraer. Si no especifica count, los elementos serán extraidos desde el principio. Esta función no modifica el arreglo original", - "params": ["Arreglo: arreglo del cual se extrae", - "Número: posición de donde empezar a extraer", - "Número: número de valores a extraer"], - "returns": "Arreglo: arreglo de elementos extraidos" - }, - "float": { - "description": "Convierte un String a su representación de punto flotante. Los contenidos de un String deben parecerse a un número, en otro caso NaN es retornado. Por ejemplo, float('1234.56') evalua a 1234.56, pero float('giraffe') retorna NaN. Cuando un arreglo de valores es pasado, un arreglo de floats del mismo largo es retornado.", - "params": ["String: string a ser procesado"], - "returns": "Número: representación en punto flotante de un string" - }, - "int": { - "description": "Convierte un boolean, string o float a su representación en número entero. Cuando un arreglo de valores es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", - "params": ["String|Boolean|Número|Arreglo: valor a procesar"], - "returns": "Número: valor representado como entero" - }, - "str": { - "description": "Convierte un boolean, string, o número a su representación en string. Cuando un arreglo de valores es introducido, entonces un arreglo de strings de la misma longitud es retornado.", - "params": ["String|Boolean|Número|Arreglo: valor a procesar"], - "returns": "String: valor representado como string" - }, - "boolean": { - "description": "Convierte un número o string a su representación en boolean. Para números, cualquier valor distinto de cero (positivo o ne gativo), evalua a true, mientras que cero evalua a falso. Para un string, el valor true evalua a true, mientras que cualquier otro valor evalua a falso. Cuando un arreglo de números o strings es introducido, entonces un arreglo de booleans de la misma longitud es retornado.", - "params": ["String|Boolean|Número|Arreglo: valor a procesar"], - "returns": "Boolean: representación en formato boolean del valor" - }, - "byte": { - "description": "Convierte un número, string o boolean a su representación en byte. Un byte puede solo ser un número entero entre -128 y 127, así que cuando un valor fuera de este rango es convertido, se hace wrap a la representación correspondiente en byte. Cuando un arreglo de números, string, o booleans es introducido, entonces un arreglo de bytes de la misma longitud es retornado.", - "params": ["String|Boolean|Número|Arreglo: valor a procesar"], - "returns": "Número: representación en formato byte del valor" - }, - "char": { - "description": "Convierte un número o string a su representaciómo como un string de un único caracter. Si se provee un parámetro, es primero pasado como entero y luego evaluado como un string de un único caracter. Cuando un arreglo de números o strings es introducido, entonces un arreglo de strings de un único caracter de la misma longitud es retornado.", - "params": ["String|Número|Arreglo: valor a procesar"], - "returns": "String: representación en formato string del valor" - }, - "unchar": { - "description": "Convierte un string de un único caracter a su correspondiente representación como valor entero. Cuando un arreglo de strings de un caracter es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", - "params": ["String|Arreglo: valor a procesar"], - "returns": "Número: representación en formato entero del valor" - }, - "hex": { - "description": "Convierte un número a su correspondiente representación como hexadecimal. Si se ingersa un segundo parámetro, es usado para definir el número de caracteres a generar en la notación hexadecimal. Cuando un arreglo es introducido, entonces un arreglo de strings en notación hexadecimal de la misma longitud es retornado.", - "params": ["Número|Arreglo: valor a procesar"], - "returns": "String: representación en formato string hexadecimal del valor" - }, - "unhex": { - "description": "Convierte una representación en string de un número hexadecimal a su correspondiente representación como valor entero. Cuando un arreglo de strings en notación hexadecimal es introducido, entonces un arreglo de enteros de la misma longitud es retornado.", - "params": ["String|Arreglo: valor a procesar"], - "returns": "Número: representación en formato entero del valor hexadecimal" - }, - "join": { - "description": "Combina una arreglo de Strings en un String, cada uno separado por los caracteres usados como parámetro separator. Para unir arreglos de enteros o floats, es necesario primero convertirlos a Strings usando las funciones nf() o nfs().", - "params": ["Arreglo: arreglo de Strings a ser unidos", - "String: String a ser posicionado entre cada item"], - "returns": "String: String unificado" - }, - "match": { - "description": "Esta función es usada para aplicar una expresión regular a una porción de texto, y retorna grupos coincidentes (elementos encontrados entre paréntesis) como un arreglo de Strings. Si no existen coincidencias, se retorna el valor null. Si no se especifican grupos en la expresión regular, pero la secuencia coincide, un arreglo de largo 1 (con el texto coincidente como primer elemento del arreglo) será retornado. Para usar la función, primero comprueba si el resultado es null. Si el resultado es null, entonces la secuencia no tuvo coincidencias. Si la secuencia tuvo coincidencias, retorna un arreglo. Si exsiten grupos (especificados como conjuntos de paréntesis) en la expresión regular, entonces los contenidos de cada uno serán retornados en el arreglo. El elemento[0] de una coincidencia de expresión regular retorna el string coincidente, y el grupo de coincidencia empieza en el elemento[1] (el primer grupo es [1], el segundo es [2], etc).", - "params": ["String: el String a ser buscado", - "String: la expresión regular a ser usada para buscar coincidencias"], - "returns": "Arreglo: arreglo de Strings encontrados" - }, - "matchAll": { - "description": "Esta función es usada para aplicar una expresión regular a una porción de texto, y retorna una lista de grupos coincidentes (elementos encontrados entre paréntesis) como un arreglo de Strings bidimensional. Si no existen coincidencias, se retorna el valor null. Si no se especifican grupos en la expresión regular, pero la secuencia coincide, un arreglo de dos dimensiones es retornado, pero es de largo 1. Para usar la función, primero comprueba si el resultado es null. Si el resultado es null, entonces la secuencia no tuvo coincidencias. Si la secuencia tuvo coincidencias, retorna un arreglo 2D. Si exsiten grupos (especificados como conjuntos de paréntesis) en la expresión regular, entonces los contenidos de cada uno serán retornados en el arreglo. El elemento[i][0] de una coincidencia de expresión regular retorna el string coincidente completo, y el grupo de coincidencia empieza en el elemento[i][1] (el primer grupo es [i][1], el segundo es [i][2], etc).", - "params": ["String: el String a ser buscado", - "String: la expresión regular a ser usada para buscar coincidencias"], - "returns": "Arreglo: arreglo 2D de Strings encontrados" - }, - "nf": { - "description": "Función de utilidad para formatear números a strings. Existen dos veriones: una para formatear floats, y una para formatear enteros. Los valores de los dígitos y los parámetros left y right siempre deben ser enteros positivos", - "params": ["Número|Arreglo: el número a formatear", - "Número: número de dígitos a la izquierda del punto decimal", - "Número: número de dígitos a la derecha del punto decimal"], - "returns": "String|Arreglo: String formateada" - }, - "nfc": { - "description": "Función de utilidad para formatear números en strings y poner las comas apropiadas para señalar múltiplos de mil. Hay dos versiones: una para números enteros y otra para arreglos de enteros. El valor del parámetro right debe siempre ser un entero positivo.", - "params": ["Número|Arreglo: el número a formatear", - "Número: número de dígitos a la derecha del punto decimal"], - "returns": "String|Arreglo: String formateada" - }, - "nfp": { - "description": "Función de utilidad para formatear números en strings. Similar a nf() pero pone un signo + en frente de los números positivos y un signo - en frente de números negativos. Hay dos versiones, una para formatear floats y otra para formatear enteros. Los valores de los parámetros left y right deben siempre ser enteros positivos.", - "params": ["Número|Arreglo: el número a formatear", - "Número: número de dígitos a la izquierda del punto decimal", - "Número: número de dígitos a la derecha del punto decimal"], - "returns": "String|Arreglo: String formateada" - }, - "nfs": { - "description": "Función de utilidad para formatear números en strings. Similar a nf() pero pone un espacio en frente de los números positivos y un signo - en frente de números negativos. Hay dos versiones, una para formatear floats y otra para formatear enteros. Los valores de los parámetros left y right deben siempre ser enteros positivos.", - "params": ["Número|Arreglo: el número a formatear", - "Número: número de dígitos a la izquierda del punto decimal", - "Número: número de dígitos a la derecha del punto decimal"], - "returns": "String|Arreglo: String formateada" - }, - "split": { - "description": "La función split usa String.split(), corta un String en pedazos usando un caracter o String como delimitador. El parámetro delim especifica el caracter o caracteres que marcan los bordes entre cada pieza. Un arreglo String[] es retornado, que contiene cada una de las piezas. La función splitTokens() funciona de forma similar, excepto que divide usango un rango de caracteres en vez de usar un caracter o una secuencia de caracteres específicos.", - "params": ["String: el String a ser dividido", - "String: el String usado para separar los datos"], - "returns": "Arreglo: arreglo de Strings" - }, - "splitTokens": { - "description": "La función splitTokens() divide un String en uno o varios caracteres delimitadores o tokens. El parámetro delim especifica el o los caracteres a ser usados como borde. Si no se especifican caracteres delim, cualquier caracter tipo whitespace será usado para dividir. Los caracteres whitespace incluyen tabulación (\t), nueva línea (\n), retorno de carro (\r), entrada de formulario (\f), y espacio.", - "params": ["String: el String a ser dividido", - "String: lista de Strings individuales que serán usados como separadores"], - "returns": "Arreglo: arreglo de Strings" - }, - "trim": { - "description": "Remueve caracteres tipo whitespace (espacio en blanco) del comienzo y el final de un String. En adición a los caracteres estámdar de whitespace como espacio, retorno de carro y tabulación, esta función también remueve el caracter Unicode nbsp.", - "params": ["String|Arreglo: un String o arreglo de Strings a ser recortados."], - "returns": "String|Arreglo: un String o arreglo de Strings recortados." - }, - "camera": { - "description": "Define la posición de la cámara", - "params": ["Número: valor de la posición de la cámara en el eje x", - "Número: valor de la posición de la cámara en el eje y", - "Número: valor de la posición de la cámara en el eje z"], - "returns": "p5: el objeto p5" - }, - "perspective": { - "description": "Define la perspectiva de la cámara", - "params": ["Número: frustum del campo de visión vertical de la cámara, de abajo hacia arriba, en grados", - "Número: frustum de la relación de aspecto de la cámara", - "Número: frustum del largo del plano cercano", - "Número: frustum del largo del plano lejano"], - "returns": "p5: el objeto p5" - }, - "ortho": { - "description": "Define la cámara ortogonal", - "params": ["Número: define el frustum del plano izquierdo de la cámara", - "Número: define el frustum del plano derecho de la cámara", - "Número: define el frustum del plano inferior de la cámara", - "Número: define el frustum del plano superior de la cámara", - "Número: define el frustum del plano cercano de la cámara", - "Número: define el frustum del plano lejano de la cámara"], - "returns": "p5: el objeto p5" - }, - "ambientLight": { - "description": "Crea una luz ambiente con color", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", - "Número: opcional, valor de verde o saturación", - "Número: opcional, valor de azul o brillo", - "Número: opcional, valor de opacidad"], - "returns": "el objeto p5" - }, - - "directionalLight": { - "description": "Crea una luz direccional con color y dirección", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", - "Número: opcional, valor de verde o saturación", - "Número: opcional, valor de azul o brillo", - "Número: opcional, valor de opacidad", - "Número|p5.Vector: dirección del eje x o un p5.Vector", - "Número: opcional, dirección del eje y", - "Número: opcional, dirección del eje z"], - "returns": "el objeto p5" - }, - "pointLight": { - "description": "Crea una luz puntual con color y posición", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color actual), o arreglo de color o String de color CSS", - "Número: opcional, valor de verde o saturación", - "Número: opcional, valor de azul o brillo", - "Número: opcional, valor de opacidad", - "Número|p5.Vector: dirección del eje x o un p5.Vector", - "Número: opcional, dirección del eje y", - "Número: opcional, dirección del eje z"], - "returns": "p5: el objeto p5" - }, - "normalMaterial": { - "description": "Material normal para geometría. Puedes ver todos los posibles materiales en este ejemplo (TODO).", - "returns": "p5: el objeto p5" - }, - "texture": { - "description": "Textura para geometría. Puedes ver todos los posibles materiales en este ejemplo (TODO).", - "params": ["p5.Image|p5.MediaElement|p5.Graphics: gráfica bidimensional para hacer render como textura."], - "returns": "p5: el objeto p5" - }, - "ambientMaterial": { - "description": "Material ambiente para geometría con un color dado. Puedes ver todos los posibles materiales en este ejemplo (TODO).", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color), o arreglo de color, o String de color CSS", - "Número: opcional, valor de verde o saturación", - "Número: opcional, valor de azul o brillo", - "Número: opcional, valor de opacidad"], - "returns": "p5: el objeto p5" - }, - "specularMaterial": { - "description": "Material espejo para geometría con un color dado. Puedes ver todos los posibles materiales en este ejemplo (TODO).", - "params": ["Número|Arreglo|String|p5.Color: valor de gris, rojo o tinte (dependiendo del modo de color), o arreglo de color, o String de color CSS", - "Número: opcional, valor de verde o saturación", - "Número: opcional, valor de azul o brillo", - "Número: opcional, valor de opacidad"], - "returns": "p5: el objeto p5" - }, - "p5.RendererGL": { - "description": "TODO", - "returns": "p5: el objeto p5" - }, - "p5.Shader": { - "description": "Clase Shader para el modo WEBGL", - "params": ["p5.RendererGL: una instancia de p5.RendererGL que servirá de contexto GL para este nuevo p5.Shader", - "String: código fuente para el vertex shader (en forma de string)", - "String: código fuente para el fragment shader (en forma de string)"], - "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."] } }, "p5.Image": { diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js index a538b1e161..a875c4ae60 100644 --- a/src/templates/pages/reference/assets/js/reference.js +++ b/src/templates/pages/reference/assets/js/reference.js @@ -2442,13 +2442,13 @@ define('listView',[ }); -define('text!tpl/item.html',[],function () { return '

<%=item.name%><% if (item.isMethod) { %>()<% } %>

\n\n<% if (item.example) { %>\n
\n

Example

\n Examples for <%=item.name%>\n\n\t
\n <%= item.example %>\n
\n
\n<% } %>\n\n\n
\n \n

Description

\n\n <% if (item.deprecated) { %>\n

\n Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n

\n <% } %>\n \n\n <%= item.description %>\n\n <% if (item.extends) { %>\n

Extends <%=item.extends%>

\n <% } %>\n\n <% if (item.module === \'p5.dom\') { %>\n

This function requires you include the p5.dom library. Add the following into the head of your index.html file:\n

<script language="javascript" type="text/javascript" src="path/to/p5.dom.js"></script>
\n

\n <% } %>\n <% if (item.module === \'p5.sound\') { %>\n

This function requires you include the p5.sound library. Add the following into the head of your index.html file:\n

<script language="javascript" type="text/javascript" src="path/to/p5.sound.js"></script>
\n

\n <% } %>\n\n <% if (item.constRefs) { %>\n

Used by:\n <%\n var refs = item.constRefs;\n for (var i = 0; i < refs.length; i ++) {\n var ref = refs[i];\n var name = ref;\n if (name.substr(0, 3) === \'p5.\') {\n name = name.substr(3);\n }\n\tif (i !== 0) {\n if (i == refs.length - 1) {\n %> and <%\n } else {\n %>, <%\n }\n }\n %><%= name %>()<%\n }\n %>\n

\n <% } %>\n\n
\n\n<% if (isConstructor || !isClass) { %>\n\n
\n

Syntax

\n

\n <% syntaxes.forEach(function(syntax) { %>\n

<%= syntax %>
\n <% }) %>\n

\n
\n\n\n<% if (item.return) { %>\n\n \n\n<% } %>\n\n<% if (item.access) { %>\n<%= item.access %>\n<% } %>\n\n<% if (item.final) { %>\nconstant\n<% } %>\n\n<% if (item.chainable) { %>\n

chainable

\n<% } %>\n\n<% if (item.async) { %>\nasync\n<% } %>\n\n\n\n<% if (item.params) { %>\n
\n

Parameters

\n \n <% for (var i=0; i\n \n \n \n \n <% } %>\n
\n <% var p = item.params[i] %>\n <% if (p.optional) { %>\n <%=p.name%>\n <% } else { %>\n <%=p.name%>\n <% } %>\n <%if (p.optdefault) { %>=<%=p.optdefault%><% } %>\n \n <% if (p.type) {\n var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'$1\');\n %>\n <%=type%>: <%=p.description%>\n <% } %>\n <% if (p.multiple) {%>\n multiple\n <% } %>\n
\n
\n<% } %>\n\n<% if (item.return) { %>\n
\n\t

Returns

\n <% if (item.return.type) { %>\n

<%=item.return.type%>: <%= item.return.description %>

\n <% } %>\n
\n<% } %>\n\n<% } %>\n';}); +define('text!tpl/item.html',[],function () { return '

<%=item.name%><% if (item.isMethod) { %>()<% } %>

\n\n<% if (item.example) { %>\n
\n

Example

\n Examples for <%=item.name%>\n\n\t
\n <% _.each(item.example, function(example){ %>\n <%= example %>\n <% }); %>\n
\n
\n<% } %>\n\n\n
\n \n

Description

\n\n <% if (item.deprecated) { %>\n

\n Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n

\n <% } %>\n \n\n <%= item.description %>\n\n <% if (item.extends) { %>\n

Extends <%=item.extends%>

\n <% } %>\n\n <% if (item.module === \'p5.dom\') { %>\n

This function requires you include the p5.dom library. Add the following into the head of your index.html file:\n

<script language="javascript" type="text/javascript" src="path/to/p5.dom.js"></script>
\n

\n <% } %>\n <% if (item.module === \'p5.sound\') { %>\n

This function requires you include the p5.sound library. Add the following into the head of your index.html file:\n

<script language="javascript" type="text/javascript" src="path/to/p5.sound.js"></script>
\n

\n <% } %>\n\n <% if (item.constRefs) { %>\n

Used by:\n <%\n var refs = item.constRefs;\n for (var i = 0; i < refs.length; i ++) {\n var ref = refs[i];\n var name = ref;\n if (name.substr(0, 3) === \'p5.\') {\n name = name.substr(3);\n }\n\tif (i !== 0) {\n if (i == refs.length - 1) {\n %> and <%\n } else {\n %>, <%\n }\n }\n %><%= name %>()<%\n }\n %>\n

\n <% } %>\n\n
\n\n<% if (isConstructor || !isClass) { %>\n\n
\n

Syntax

\n

\n <% syntaxes.forEach(function(syntax) { %>\n

<%= syntax %>
\n <% }) %>\n

\n
\n\n\n<% if (item.return) { %>\n\n \n\n<% } %>\n\n<% if (item.access) { %>\n<%= item.access %>\n<% } %>\n\n<% if (item.final) { %>\nconstant\n<% } %>\n\n<% if (item.chainable) { %>\n

chainable

\n<% } %>\n\n<% if (item.async) { %>\nasync\n<% } %>\n\n\n\n<% if (item.params) { %>\n
\n

Parameters

\n \n <% for (var i=0; i\n \n \n \n \n <% } %>\n
\n <% var p = item.params[i] %>\n <% if (p.optional) { %>\n <%=p.name%>\n <% } else { %>\n <%=p.name%>\n <% } %>\n <%if (p.optdefault) { %>=<%=p.optdefault%><% } %>\n \n <% if (p.type) {\n var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'$1\');\n %>\n <%=type%>: <%=p.description%>\n <% } %>\n <% if (p.multiple) {%>\n multiple\n <% } %>\n
\n
\n<% } %>\n\n<% if (item.return) { %>\n
\n\t

Returns

\n <% if (item.return.type) { %>\n

<%=item.return.type%>: <%= item.return.description %>

\n <% } %>\n
\n<% } %>\n\n<% } %>\n';}); -define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n
\n \n <%=constructor%>\n
\n<% } %>\n\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n

Fields

\n

\n <% _.each(fields, function(item) { %>\n class="addon"<% } %> ><%=item.name%>: <%= item.description %>\n
\n <% }); %>\n

\n<% } %>\n\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n

Methods

\n

\n \n <% _.each(methods, function(item) { %>\n \n \n \n <% }); %>\n
class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%><%= item.description %>
\n

\n<% } %>\n';}); +define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n
\n \n <%=constructor%>\n
\n<% } %>\n\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n

Fields

\n

\n <% _.each(fields, function(item) { %>\n class="addon"<% } %> ><%=item.name%>: <%= item.description %>\n
\n <% }); %>\n

\n<% } %>\n\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n

Methods

\n

\n \n <% _.each(methods, function(item) { %>\n \n \n \n <% }); %>\n
class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%>
<%= item.description %>
\n

\n<% } %>\n';}); -define('text!tpl/itemEnd.html',[],function () { return '

\n\n\n\n\n

If you see any errors or have suggestions, please let us know.

\n\n \n\n <% if (item.file && item.line) { %>\n

Find any typos or bugs? <%=item.name%><% if (item.isMethod) { %>()<% } %> is documented and defined in <%= item.file %>. Please feel free to edit the file and issue a pull request!

\n <% } %>\n\n

\n';}); +define('text!tpl/itemEnd.html',[],function () { return '

\n\n\n\n\n

If you see any errors or have suggestions, please let us know.

\n\n \n\n <% if (item.file && item.line) { %>\n

Find any typos or bugs? <%=item.name%><% if (item.isMethod) { %>()<% } %> is documented and defined in <%= item.file %>. Please feel free to edit the file and issue a pull request!

\n <% } %>\n\n

\n';}); // Copyright (C) 2006 Google Inc. // @@ -4116,13 +4116,14 @@ define('itemView',[ 'text!tpl/itemEnd.html', // Tools 'prettify' -], function (App, itemTpl, classTpl, endTpl) { - +], function(App, itemTpl, classTpl, endTpl) { 'use strict'; + var appVersion = App.project.version || 'master'; + var itemView = Backbone.View.extend({ el: '#item', - init: function () { + init: function() { this.$html = $('html'); this.$body = $('body'); this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll @@ -4136,20 +4137,29 @@ define('itemView',[ getSyntax: function(isMethod, cleanItem) { var isConstructor = cleanItem.is_constructor; var syntax = ''; - if (isConstructor) syntax += 'new '; - else if (cleanItem.static && cleanItem.class) syntax += cleanItem.class + '.'; + if (isConstructor) { + syntax += 'new '; + } else if (cleanItem.static && cleanItem.class) { + syntax += cleanItem.class + '.'; + } syntax += cleanItem.name; if (isMethod || isConstructor) { syntax += '('; if (cleanItem.params) { - for (var i=0; i'+cleanItem.name+' example '+(i+1)+''); + for (var i = 0; i < examples.length; i++) { + $(examples[i]).prepend( + '' + + cleanItem.name + + ' example ' + + (i + 1) + + '' + ); } var canvases = $('.cnv_div'); - for (var i=0; i'+alts[i]+''); + for (var j = 0; j < alts.length; j++) { + if (j < canvases.length) { + $(canvases[j]).append( + '' + alts[j] + '' + ); } } } @@ -4258,7 +4280,7 @@ define('itemView',[ * @param {object} item The item object. * @returns {object} Returns the same item object with urlencoded paths. */ - clean: function (item) { + clean: function(item) { var cleanItem = item; if (cleanItem.hasOwnProperty('file')) { @@ -4271,7 +4293,7 @@ define('itemView',[ * @param {object} item Item object. * @returns {object} This view. */ - show: function (item) { + show: function(item) { if (item) { this.render(item); } @@ -4289,8 +4311,10 @@ define('itemView',[ * Show a message if no item is found. * @returns {object} This view. */ - nothingFound: function () { - this.$el.html("



Ouch. I am unable to find any item that match the current query.

"); + nothingFound: function() { + this.$el.html( + '



Ouch. I am unable to find any item that match the current query.

' + ); App.pageView.hideContentViews(); this.$el.show(); @@ -4304,7 +4328,7 @@ define('itemView',[ // Chrome scrolls 'body', Firefox scrolls 'html' var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0; if (scroll) { - this.$scrollBody.animate({'scrollTop': 0}, 600); + this.$scrollBody.animate({ scrollTop: 0 }, 600); } }, /** @@ -4312,13 +4336,12 @@ define('itemView',[ * @param {string} str * @returns {string} Returns the string. */ - capitalizeFirst: function (str) { + capitalizeFirst: function(str) { return str.substr(0, 1).toUpperCase() + str.substr(1); } }); return itemView; - }); diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map index f0e601f10d..5591bbc091 100644 --- a/src/templates/pages/reference/assets/js/reference.js.map +++ b/src/templates/pages/reference/assets/js/reference.js.map @@ -25,7 +25,7 @@ "../../../config-wrap-end-default.js" ], "names": [], - "mappings": "AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnYA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9rDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3HA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxIA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1nDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACrNA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClEA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjGA", + "mappings": "AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnYA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9rDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3HA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxIA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1nDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5OA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClEA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjGA", "file": "reference.js", "sourcesContent": [ "(function () {\n", @@ -37,11 +37,11 @@ "define('searchView',[\n 'App',\n // Templates\n 'text!tpl/search.html',\n 'text!tpl/search_suggestion.html',\n // Tools\n 'typeahead'\n], function(App, searchTpl, suggestionTpl) {\n\n var searchView = Backbone.View.extend({\n el: '#search',\n /**\n * Init.\n */\n init: function() {\n var tpl = _.template(searchTpl);\n var className = 'form-control input-lg';\n var placeholder = 'Search the API';\n this.searchHtml = tpl({\n 'placeholder': placeholder,\n 'className': className\n });\n this.items = App.classes.concat(App.allItems);\n\n return this;\n },\n /**\n * Render input field with Typehead activated.\n */\n render: function() {\n // Append the view to the dom\n this.$el.append(this.searchHtml);\n\n // Render Typeahead\n var $searchInput = this.$el.find('input[type=text]');\n this.typeaheadRender($searchInput);\n this.typeaheadEvents($searchInput);\n\n return this;\n },\n /**\n * Apply Twitter Typeahead to the search input field.\n * @param {jquery} $input\n */\n typeaheadRender: function($input) {\n var self = this;\n $input.typeahead(null, {\n 'displayKey': 'name',\n 'minLength': 2,\n //'highlight': true,\n 'source': self.substringMatcher(this.items),\n 'templates': {\n 'empty': '

Unable to find any item that match the current query

',\n 'suggestion': _.template(suggestionTpl)\n }\n });\n },\n /**\n * Setup typeahead custom events (item selected).\n */\n typeaheadEvents: function($input) {\n var self = this;\n $input.on('typeahead:selected', function(e, item, datasetName) {\n var selectedItem = self.items[item.idx];\n select(selectedItem);\n });\n $input.on('keydown', function(e) {\n if (e.which === 13) { // enter\n var txt = $input.val();\n var f = _.find(self.items, function(it) { return it.name == txt; });\n if (f) {\n select(f);\n }\n } else if (e.which === 27) {\n $input.blur();\n }\n });\n\n function select(selectedItem) {\n var hash = App.router.getHash(selectedItem);//\n App.router.navigate(hash, {'trigger': true});\n $input.blur();\n }\n },\n /**\n * substringMatcher function for Typehead (search for strings in an array).\n * @param {array} array\n * @returns {Function}\n */\n substringMatcher: function(array) {\n return function findMatches(query, callback) {\n var matches = [], substrRegex, arrayLength = array.length;\n\n // regex used to determine if a string contains the substring `query`\n substrRegex = new RegExp(query, 'i');\n\n // iterate through the pool of strings and for any string that\n // contains the substring `query`, add it to the `matches` array\n for (var i=0; i < arrayLength; i++) {\n var item = array[i];\n if (substrRegex.test(item.name)) {\n // typeahead expects suggestions to be a js object\n matches.push({\n 'itemtype': item.itemtype,\n 'name': item.name,\n 'className': item.class,\n 'is_constructor': !!item.is_constructor,\n 'final': item.final,\n 'idx': i\n });\n }\n }\n\n callback(matches);\n };\n }\n\n });\n\n return searchView;\n\n});\n\n", "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\n

\"><%=group.name%>

\\n
\\n <% _.each(group.subgroups, function(subgroup, ind) { %>\\n
\\n <% if (subgroup.name !== \\'0\\') { %>\\n
\"><%=subgroup.name%>
\\n <% } %>\\n <% _.each(subgroup.items, function(item) { %>\\n
\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%>
\\n <% }); %>\\n
\\n <% }); %>\\n
\\n<% }); %>\\n';});\n\n", "define('listView',[\n 'App',\n // Templates\n 'text!tpl/list.html'\n], function (App, listTpl) {\n var striptags = function(html) {\n var div = document.createElement('div');\n div.innerHTML = html;\n return div.textContent;\n };\n\n var listView = Backbone.View.extend({\n el: '#list',\n events: {},\n /**\n * Init.\n */\n init: function () {\n this.listTpl = _.template(listTpl);\n\n return this;\n },\n /**\n * Render the list.\n */\n render: function (items, listCollection) {\n if (items && listCollection) {\n var self = this;\n\n // Render items and group them by module\n // module === group\n this.groups = {};\n _.each(items, function (item, i) {\n\n if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n\n var group = item.module || '_';\n var subgroup = item.submodule || '_';\n if (group === subgroup) {\n subgroup = '0';\n }\n var hash = App.router.getHash(item);\n\n // Create a group list\n if (!self.groups[group]) {\n self.groups[group] = {\n name: group.replace('_', ' '),\n subgroups: {}\n };\n }\n\n // Create a subgroup list\n if (!self.groups[group].subgroups[subgroup]) {\n self.groups[group].subgroups[subgroup] = {\n name: subgroup.replace('_', ' '),\n items: []\n };\n }\n\n // hide the un-interesting constants\n if (group === 'Constants' && !item.example)\n return;\n\n if (item.class === 'p5') {\n\n self.groups[group].subgroups[subgroup].items.push(item);\n\n } else {\n\n var found = _.find(self.groups[group].subgroups[subgroup].items,\n function(i){ return i.name == item.class; });\n\n if (!found) {\n\n // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\n var ind = hash.lastIndexOf('/');\n hash = item.hash.substring(0, ind).replace('p5/','p5.');\n self.groups[group].subgroups[subgroup].items.push({\n name: item.class,\n hash: hash\n });\n }\n\n }\n }\n });\n\n // Put the
  • items html into the list
      \n var listHtml = self.listTpl({\n 'striptags': striptags,\n 'title': self.capitalizeFirst(listCollection),\n 'groups': self.groups,\n 'listCollection': listCollection\n });\n\n // Render the view\n this.$el.html(listHtml);\n }\n\n var renderEvent = new Event('reference-rendered');\n window.dispatchEvent(renderEvent);\n\n return this;\n },\n /**\n * Show a list of items.\n * @param {array} items Array of item objects.\n * @returns {object} This view.\n */\n show: function (listGroup) {\n if (App[listGroup]) {\n this.render(App[listGroup], listGroup);\n }\n App.pageView.hideContentViews();\n\n this.$el.show();\n\n return this;\n },\n /**\n * Helper method to capitalize the first letter of a string\n * @param {string} str\n * @returns {string} Returns the string.\n */\n capitalizeFirst: function (str) {\n return str.substr(0, 1).toUpperCase() + str.substr(1);\n }\n\n\n\n });\n\n return listView;\n\n});\n\n", - "\ndefine('text!tpl/item.html',[],function () { return '

      <%=item.name%><% if (item.isMethod) { %>()<% } %>

      \\n\\n<% if (item.example) { %>\\n
      \\n

      Example

      \\n Examples for <%=item.name%>\\n\\n\\t
      \">\\n <%= item.example %>\\n
      \\n
      \\n<% } %>\\n\\n\\n
      \\n \\n

      Description

      \\n\\n <% if (item.deprecated) { %>\\n

      \\n Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n

      \\n <% } %>\\n \\n\\n <%= item.description %>\\n\\n <% if (item.extends) { %>\\n

      Extends \" title=\"<%=item.extends%> reference\"><%=item.extends%>

      \\n <% } %>\\n\\n <% if (item.module === \\'p5.dom\\') { %>\\n

      This function requires you include the p5.dom library. Add the following into the head of your index.html file:\\n

      <script language=\"javascript\" type=\"text/javascript\" src=\"path/to/p5.dom.js\"></script>
      \\n

      \\n <% } %>\\n <% if (item.module === \\'p5.sound\\') { %>\\n

      This function requires you include the p5.sound library. Add the following into the head of your index.html file:\\n

      <script language=\"javascript\" type=\"text/javascript\" src=\"path/to/p5.sound.js\"></script>
      \\n

      \\n <% } %>\\n\\n <% if (item.constRefs) { %>\\n

      Used by:\\n <%\\n var refs = item.constRefs;\\n for (var i = 0; i < refs.length; i ++) {\\n var ref = refs[i];\\n var name = ref;\\n if (name.substr(0, 3) === \\'p5.\\') {\\n name = name.substr(3);\\n }\\n\\tif (i !== 0) {\\n if (i == refs.length - 1) {\\n %> and <%\\n } else {\\n %>, <%\\n }\\n }\\n %>\"><%= name %>()<%\\n }\\n %>\\n

      \\n <% } %>\\n\\n
      \\n\\n<% if (isConstructor || !isClass) { %>\\n\\n
      \\n

      Syntax

      \\n

      \\n <% syntaxes.forEach(function(syntax) { %>\\n

      <%= syntax %>
      \\n <% }) %>\\n

      \\n
      \\n\\n\\n<% if (item.return) { %>\\n\\n \\n\\n<% } %>\\n\\n<% if (item.access) { %>\\n\"><%= item.access %>\\n<% } %>\\n\\n<% if (item.final) { %>\\nconstant\\n<% } %>\\n\\n<% if (item.chainable) { %>\\n

      chainable

      \\n<% } %>\\n\\n<% if (item.async) { %>\\nasync\\n<% } %>\\n\\n\\n\\n<% if (item.params) { %>\\n
      \\n

      Parameters

      \\n \\n <% for (var i=0; i\\n \\n \\n \\n \\n <% } %>\\n
      \\n <% var p = item.params[i] %>\\n <% if (p.optional) { %>\\n <%=p.name%>\\n <% } else { %>\\n <%=p.name%>\\n <% } %>\\n <%if (p.optdefault) { %>=<%=p.optdefault%><% } %>\\n \\n <% if (p.type) {\\n var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'$1\\');\\n %>\\n <%=type%>: <%=p.description%>\\n <% } %>\\n <% if (p.multiple) {%>\\n multiple\\n <% } %>\\n
      \\n
      \\n<% } %>\\n\\n<% if (item.return) { %>\\n
      \\n\\t

      Returns

      \\n <% if (item.return.type) { %>\\n

      <%=item.return.type%>: <%= item.return.description %>

      \\n <% } %>\\n
      \\n<% } %>\\n\\n<% } %>\\n';});\n\n", - "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n
      \\n \\n <%=constructor%>\\n
      \\n<% } %>\\n\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n

      Fields

      \\n

      \\n <% _.each(fields, function(item) { %>\\n \" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%>: <%= item.description %>\\n
      \\n <% }); %>\\n

      \\n<% } %>\\n\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n

      Methods

      \\n

      \\n \\n <% _.each(methods, function(item) { %>\\n \\n \\n \\n <% }); %>\\n
      \" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%><%= item.description %>
      \\n

      \\n<% } %>\\n';});\n\n", - "\ndefine('text!tpl/itemEnd.html',[],function () { return '

      \\n\\n\\n\\n\\n

      If you see any errors or have suggestions, please let us know.

      \\n\\n \\n\\n <% if (item.file && item.line) { %>\\n

      Find any typos or bugs? <%=item.name%><% if (item.isMethod) { %>()<% } %> is documented and defined in #L<%= item.line %>\" target=\"_blank\" ><%= item.file %>. Please feel free to #L<%= item.line %>\" target=\"_blank\" style=\"font-family: inherit\">edit the file and issue a pull request!

      \\n <% } %>\\n\\n

      \\n';});\n\n", + "\ndefine('text!tpl/item.html',[],function () { return '

      <%=item.name%><% if (item.isMethod) { %>()<% } %>

      \\n\\n<% if (item.example) { %>\\n
      \\n

      Example

      \\n Examples for <%=item.name%>\\n\\n\\t
      \">\\n <% _.each(item.example, function(example){ %>\\n <%= example %>\\n <% }); %>\\n
      \\n
      \\n<% } %>\\n\\n\\n
      \\n \\n

      Description

      \\n\\n <% if (item.deprecated) { %>\\n

      \\n Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n

      \\n <% } %>\\n \\n\\n <%= item.description %>\\n\\n <% if (item.extends) { %>\\n

      Extends \" title=\"<%=item.extends%> reference\"><%=item.extends%>

      \\n <% } %>\\n\\n <% if (item.module === \\'p5.dom\\') { %>\\n

      This function requires you include the p5.dom library. Add the following into the head of your index.html file:\\n

      <script language=\"javascript\" type=\"text/javascript\" src=\"path/to/p5.dom.js\"></script>
      \\n

      \\n <% } %>\\n <% if (item.module === \\'p5.sound\\') { %>\\n

      This function requires you include the p5.sound library. Add the following into the head of your index.html file:\\n

      <script language=\"javascript\" type=\"text/javascript\" src=\"path/to/p5.sound.js\"></script>
      \\n

      \\n <% } %>\\n\\n <% if (item.constRefs) { %>\\n

      Used by:\\n <%\\n var refs = item.constRefs;\\n for (var i = 0; i < refs.length; i ++) {\\n var ref = refs[i];\\n var name = ref;\\n if (name.substr(0, 3) === \\'p5.\\') {\\n name = name.substr(3);\\n }\\n\\tif (i !== 0) {\\n if (i == refs.length - 1) {\\n %> and <%\\n } else {\\n %>, <%\\n }\\n }\\n %>\"><%= name %>()<%\\n }\\n %>\\n

      \\n <% } %>\\n\\n
      \\n\\n<% if (isConstructor || !isClass) { %>\\n\\n
      \\n

      Syntax

      \\n

      \\n <% syntaxes.forEach(function(syntax) { %>\\n

      <%= syntax %>
      \\n <% }) %>\\n

      \\n
      \\n\\n\\n<% if (item.return) { %>\\n\\n \\n\\n<% } %>\\n\\n<% if (item.access) { %>\\n\"><%= item.access %>\\n<% } %>\\n\\n<% if (item.final) { %>\\nconstant\\n<% } %>\\n\\n<% if (item.chainable) { %>\\n

      chainable

      \\n<% } %>\\n\\n<% if (item.async) { %>\\nasync\\n<% } %>\\n\\n\\n\\n<% if (item.params) { %>\\n
      \\n

      Parameters

      \\n \\n <% for (var i=0; i\\n \\n \\n \\n \\n <% } %>\\n
      \\n <% var p = item.params[i] %>\\n <% if (p.optional) { %>\\n <%=p.name%>\\n <% } else { %>\\n <%=p.name%>\\n <% } %>\\n <%if (p.optdefault) { %>=<%=p.optdefault%><% } %>\\n \\n <% if (p.type) {\\n var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'$1\\');\\n %>\\n <%=type%>: <%=p.description%>\\n <% } %>\\n <% if (p.multiple) {%>\\n multiple\\n <% } %>\\n
      \\n
      \\n<% } %>\\n\\n<% if (item.return) { %>\\n
      \\n\\t

      Returns

      \\n <% if (item.return.type) { %>\\n

      <%=item.return.type%>: <%= item.return.description %>

      \\n <% } %>\\n
      \\n<% } %>\\n\\n<% } %>\\n';});\n\n", + "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n
      \\n \\n <%=constructor%>\\n
      \\n<% } %>\\n\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n

      Fields

      \\n

      \\n <% _.each(fields, function(item) { %>\\n \" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%>: <%= item.description %>\\n
      \\n <% }); %>\\n

      \\n<% } %>\\n\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n

      Methods

      \\n

      \\n \\n <% _.each(methods, function(item) { %>\\n \\n \\n \\n <% }); %>\\n
      \" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%>
      <%= item.description %>
      \\n

      \\n<% } %>\\n';});\n\n", + "\ndefine('text!tpl/itemEnd.html',[],function () { return '

      \\n\\n\\n\\n\\n

      If you see any errors or have suggestions, please let us know.

      \\n\\n \\n\\n <% if (item.file && item.line) { %>\\n

      Find any typos or bugs? <%=item.name%><% if (item.isMethod) { %>()<% } %> is documented and defined in /<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %>. Please feel free to #L<%= item.line %>\" target=\"_blank\" style=\"font-family: inherit\">edit the file and issue a pull request!

      \\n <% } %>\\n\\n

      \\n';});\n\n", "// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n *

      \n * For a fairly comprehensive set of languages see the\n * README\n * file that came with this source. At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n *

      \n * Usage:

        \n *
      1. include this source file in an html page via\n * {@code }\n *
      2. define style rules. See the example page for examples.\n *
      3. mark the {@code
        } and {@code } tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code } tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n\ndefine(\"prettify\", function(){});\n\n",
        -    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function (App, itemTpl, classTpl, endTpl) {\n\n  'use strict';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function () {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) syntax += 'new ';\n      else if (cleanItem.static && cleanItem.class) syntax += cleanItem.class + '.';\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i=0; i<cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) syntax += '[';\n            syntax += p.name;\n            if (p.optdefault) syntax += '='+p.optdefault;\n            if (p.optional) syntax += ']';\n            if (i !== cleanItem.params.length-1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function (item) {\n      if (item) {\n        var itemHtml = '',\n            cleanItem = this.clean(item),\n            isClass = item.hasOwnProperty('itemtype') ? 0 : 1,\n            collectionName = isClass ? 'Constructor' : this.capitalizeFirst(cleanItem.itemtype),\n            isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c){ return c.name === cleanItem.name; });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n\n        } else {\n\n          cleanItem.constRefs = item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({item:cleanItem});\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode();\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === \"method\"){\n            App.pageView.appendToDocumentTitle(item.name + \"()\");\n        }\n        else {\n            App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts).data('alt').split('\\n');\n\n            var examples = $('.example_container');\n\n            for (var i=0; i<examples.length; i++) {\n              $(examples[i]).prepend('<span class=\"visuallyhidden\">'+cleanItem.name+' example '+(i+1)+'</span>');\n            }\n\n            var canvases = $('.cnv_div');\n            for (var i=0; i<alts.length; i++) {\n              if (i < canvases.length) {\n                $(canvases[i]).append('<span class=\"visuallyhidden\">'+alts[i]+'</span>');\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function (item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function (item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      //window.scrollTo(0, 0); // LM\n\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function () {\n      this.$el.html(\"<p><br><br>Ouch. I am unable to find any item that match the current query.</p>\");\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({'scrollTop': 0}, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function (str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n\n});\n\n",
        +    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function(App, itemTpl, classTpl, endTpl) {\n  'use strict';\n\n  var appVersion = App.project.version || 'master';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function() {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) {\n        syntax += 'new ';\n      } else if (cleanItem.static && cleanItem.class) {\n        syntax += cleanItem.class + '.';\n      }\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i = 0; i < cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) {\n              syntax += '[';\n            }\n            syntax += p.name;\n            if (p.optdefault) {\n              syntax += '=' + p.optdefault;\n            }\n            if (p.optional) {\n              syntax += ']';\n            }\n            if (i !== cleanItem.params.length - 1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function(item) {\n      if (item) {\n        var itemHtml = '';\n        var cleanItem = this.clean(item);\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\n        var collectionName = isClass\n            ? 'Constructor'\n            : this.capitalizeFirst(cleanItem.itemtype),\n          isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c) {\n            return c.name === cleanItem.name;\n          });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n        } else {\n          cleanItem.constRefs =\n            item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode();\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === 'method') {\n          App.pageView.appendToDocumentTitle(item.name + '()');\n        } else {\n          App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts)\n              .data('alt')\n              .split('\\n');\n\n            var examples = $('.example_container');\n\n            for (var i = 0; i < examples.length; i++) {\n              $(examples[i]).prepend(\n                '<span class=\"visuallyhidden\">' +\n                  cleanItem.name +\n                  ' example ' +\n                  (i + 1) +\n                  '</span>'\n              );\n            }\n\n            var canvases = $('.cnv_div');\n            for (var j = 0; j < alts.length; j++) {\n              if (j < canvases.length) {\n                $(canvases[j]).append(\n                  '<span class=\"visuallyhidden\">' + alts[j] + '</span>'\n                );\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function(item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function(item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      //window.scrollTo(0, 0); // LM\n\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function() {\n      this.$el.html(\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\n      );\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function(str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n});\n\n",
             "\ndefine('text!tpl/menu.html',[],function () { return '<p>\\n  <small>\\n    <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\n    <a href=\"#/libraries/p5.dom\">p5.dom</a> <span id=\"reference-description2\">or</span>\\n    <a href=\"#/libraries/p5.sound\">p5.sound</a>.\\n    <span id=\"reference-description3\">You can download an offline version of the reference</span> <a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description4\">here</span></a>.\\n  </small>\\n</p>\\n\\n<% var i=0; %>\\n<% var max=Math.floor(groups.length/4); %>\\n<% var rem=groups.length%4; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% var m = rem > 0 ? 1 : 0 %>\\n  <% if (i === 0) { %>\\n    <dl>\\n  <% } %>\\n  <dd><a href=\"#group-<%=group%>\"><%=group%></a></dd>\\n  <% if (i === (max+m-1)) { %>\\n    </dl>\\n  \\t<% rem-- %>\\n  \\t<% i=0 %>\\n  <% } else { %>\\n  \\t<% i++ %>\\n  <% } %>\\n<% }); %>\\n';});\n\n",
             "define('menuView',[\n  'App',\n  'text!tpl/menu.html'\n], function(App, menuTpl) {\n\n  var menuView = Backbone.View.extend({\n    el: '#collection-list-nav',\n    /**\n     * Init.\n     * @returns {object} This view.\n     */\n    init: function() {\n      this.menuTpl = _.template(menuTpl);\n      return this;\n    },\n    /**\n     * Render.\n     * @returns {object} This view.\n     */\n    render: function() {\n\n      var groups = [];\n      _.each(App.modules, function (item, i) {\n        if (!item.is_submodule) {\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n            groups.push(item.name);\n          }\n        }\n        //}\n      });\n\n      // Sort groups by name A-Z\n      groups.sort();\n\n      var menuHtml = this.menuTpl({\n        'groups': groups\n      });\n\n      // Render the view\n      this.$el.html(menuHtml);\n    },\n\n    hide: function() {\n      this.$el.hide();\n    },\n\n    show: function() {\n      this.$el.show();\n    },\n\n    /**\n     * Update the menu.\n     * @param {string} el The name of the current route.\n     */\n    update: function(menuItem) {\n      //console.log(menuItem);\n      // this.$menuItems.removeClass('active');\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\n\n    }\n  });\n\n  return menuView;\n\n});\n\n",
             "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\n\\n<p><%= module.description %></p>\\n\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\n\\n<% var t = 0; col = 0; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% if (t == 0) { %> \\n    <div class=\"column_<%=col%>\">\\n  <% } %>\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\n    <% if (group.hash) { %> </a> <% } %>\\n  <% } %>\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\n    <% t++; %>\\n  <% }); %>\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\n    </div>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        diff --git a/src/templates/pages/reference/index.hbs b/src/templates/pages/reference/index.hbs
        index d8e96686c1..651d48c7e1 100644
        --- a/src/templates/pages/reference/index.hbs
        +++ b/src/templates/pages/reference/index.hbs
        @@ -44,15 +44,20 @@ slug: reference/
               var langs = ['es', 'ko', 'zh-Hans'];
               var routes = window.location.pathname.split('/');
               var lang = routes[1];
        +      console.log(lang)
               if (langs.indexOf(lang) != -1) {
        +      console.log('inside')
                 $.getJSON('/assets/reference/'+lang+'.json', function(data) {
        +
        +      console.log(data)
                   translations = data;
         
                   window.addEventListener('reference-rendered', function() {
                     console.log("rendered");
                     updateLanguage();
                   }, false);
        -        });
        +        })
        +        .error(function(e) { console.log(e) });
               }
             });
         
        diff --git a/src/templates/partials/i18n.hbs b/src/templates/partials/i18n.hbs
        index 88a84d4e88..10ed15c6de 100644
        --- a/src/templates/partials/i18n.hbs
        +++ b/src/templates/partials/i18n.hbs
        @@ -1,10 +1,11 @@
         ---
        -title: language buttons
        +titne: language buttons
         ---
         <!-- p5*js language buttons -->
         <div id="i18n-btn">
           <h1 class='visuallyhidden'>Language Settings</h1>
           <button data-lang='en'>EN</button>
           <button data-lang='es'>ES</button>
        +  <button data-lang='ko'>KO</button>
           <button data-lang='zh-Hans'>简体中文</button>
         </div>
        \ No newline at end of file
        
        From cc982adf900baf35bd369c7720e0ccbcf03d3884 Mon Sep 17 00:00:00 2001
        From: Lauren McCarthy <laurmccarthy@gmail.com>
        Date: Sat, 27 Apr 2019 07:12:52 +0900
        Subject: [PATCH 07/36] korean infrastructure
        
        ---
         src/assets/js/init.js                   |  2 +-
         src/templates/pages/reference/index.hbs | 10 +++-------
         src/templates/partials/i18n.hbs         |  2 +-
         3 files changed, 5 insertions(+), 9 deletions(-)
        
        diff --git a/src/assets/js/init.js b/src/assets/js/init.js
        index 1b9e67c630..8b8912c758 100644
        --- a/src/assets/js/init.js
        +++ b/src/assets/js/init.js
        @@ -1,4 +1,4 @@
        -var langs = ['en', 'es', 'zh-Hans'];
        +var langs = ['en', 'es', 'ko', 'zh-Hans'];
         
         // =================================================
         // Family bar:
        diff --git a/src/templates/pages/reference/index.hbs b/src/templates/pages/reference/index.hbs
        index 651d48c7e1..eb82da9397 100644
        --- a/src/templates/pages/reference/index.hbs
        +++ b/src/templates/pages/reference/index.hbs
        @@ -44,20 +44,16 @@ slug: reference/
               var langs = ['es', 'ko', 'zh-Hans'];
               var routes = window.location.pathname.split('/');
               var lang = routes[1];
        -      console.log(lang)
        -      if (langs.indexOf(lang) != -1) {
        +
        +      if (langs.indexOf(lang) !== -1) {
               console.log('inside')
                 $.getJSON('/assets/reference/'+lang+'.json', function(data) {
        -
        -      console.log(data)
                   translations = data;
        -
                   window.addEventListener('reference-rendered', function() {
                     console.log("rendered");
                     updateLanguage();
                   }, false);
        -        })
        -        .error(function(e) { console.log(e) });
        +        });
               }
             });
         
        diff --git a/src/templates/partials/i18n.hbs b/src/templates/partials/i18n.hbs
        index 10ed15c6de..204b9aac6d 100644
        --- a/src/templates/partials/i18n.hbs
        +++ b/src/templates/partials/i18n.hbs
        @@ -6,6 +6,6 @@ titne: language buttons
           <h1 class='visuallyhidden'>Language Settings</h1>
           <button data-lang='en'>EN</button>
           <button data-lang='es'>ES</button>
        -  <button data-lang='ko'>KO</button>
        +  <button data-lang='ko'>한국어</button>
           <button data-lang='zh-Hans'>简体中文</button>
         </div>
        \ No newline at end of file
        
        From cf3314557fcd084720a3cbca0fa45ce5ce151753 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Fri, 27 Mar 2020 02:57:43 +0900
        Subject: [PATCH 08/36] Korean Translation on ko.yml and reference ko.json
        
        ---
         src/data/ko.yml                               | 1153 +++++++++--------
         src/data/reference/ko.json                    |  100 +-
         .../pages/reference/assets/js/reference.js    |   16 +-
         .../reference/assets/js/reference.js.map      |   40 +-
         src/templates/partials/i18n.hbs               |    2 +-
         5 files changed, 656 insertions(+), 655 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index fe0a1152b8..9bc2cafca5 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -1,206 +1,207 @@
         Skip-To-Content: "Skip to content"
        -Language-Settings: "Language Settings"
        -Sidebar-Title: "Site Navigation"
        +Language-Settings: "언어 설정"
        +Sidebar-Title: "사이트 둘러보기"
         Home: "홈"
        -Editor: "Editor"
        +Editor: "에디터"
         Download: "다운로드"
        +Donate: "기부하기"
         Start: "시작하기"
         Reference: "레퍼런스"
         Libraries: "라이브러리"
        -Learn: "학습"
        +Learn: "배우기"
         Examples: "예제"
        -Books: "관련 책"
        +Books: "출판물"
         Community: "커뮤니티"
        -Contribute: "기여하기"
        +Contribute: "함께하기"
         Forum: "포럼"
        -Showcase: "Showcase"
        +Showcase: "쇼케이스"
         
         footerxh1: "Credits"
        -footer1: "p5.js는 "
        -footer2: "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 "
        -footer3: " 과 "
        -footer4: "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 : "
        +footer1: "p5.js는 로렌 맥카시 "
        +footer2: " 가 창안하고 협력자 커뮤니티와 함께 개발하였습니다. 지원: 프로세싱 재단 "
        +footer3: "과 "
        +footer4: " 아이덴티티 및 그래픽 디자인: "
         
        -tagline1: "Processing의 즐거움에 JavaScript의 매력을 곱하다"
        -tagline2: "Processing의 간명함에 JavaScript의 유연성을 곱하다"
        -tagline3: "Processing의 직관성에 JavaScript의 강력함을 곱하다"
        -tagline4: "Processing의 창조성에 JavaScript의 활력을 곱하다"
        -tagline5: "Processing 커뮤니티에 JavaScript 커뮤니티를 곱하다"
        -tagline6: "Processing의 강력함에 JavaScript의 범용성을 곱하다"
        +tagline1: "프로세싱의 즐거움에 자바스크립트의 매력을 곱하다*"
        +tagline2: "프로세싱의 간편함에 자바스크립트의 유연성을 곱하다*"
        +tagline3: "프로세싱의 직관성에 자바스크립트의 강력함을 곱하다*"
        +tagline4: "프로세싱의 창조성에 자바스크립트의 역동성을 곱하다*"
        +tagline5: "프로세싱 커뮤니티에 자바스크립트 커뮤니티를 곱하다*"
        +tagline6: "프로세싱의 강력함에 자바스크립트의 범용성을 곱하다*"
         
         home:
        -  start-creating: "Start creating with the p5 Editor!"
        -  p1xh1: "Hello!"
        -  p1x1: "p5.js is a JavaScript library for creative coding, with a focus on making coding accessible and inclusive for artists, designers, educators, beginners, and anyone else! p5.js is free and open-source because we believe software, and the tools to learn it, should be accessible to everyone."
        -  p1x2: "Using the metaphor of a sketch, p5.js has a full set of drawing functionality. However, you’re not limited to your drawing canvas. You can think of your whole browser page as your sketch, including HTML5 objects for text, input, video, webcam, and sound."
        -  p2xh2: "Community"
        -  p2x1: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
        -  p2x2: "p5.js is an interpretation of "
        -  p2x3: " for today’s web. We hold events and operate with support from the "
        -  p2x4: "."
        -  p2x5: "Learn more about "
        -  p2x6: "our community"
        -  p2x7: "."
        +  start-creating: "p5 에디터로 프로젝트 시작하기"
        +  p1xh1: "안녕하세요!"
        +  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 특히, 예술가, 디자이너, 교육자, 초심자, 그리고 모두에게 접근성이 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공됩니다. 이는 소프트웨어와 그 학습 도구들이 누구에게나 열려있어야 한다는 생각에 기반합니다."
        +  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 오브젝트를 사용할 수 있습니다."
        +  p2xh2: "커뮤니티"
        +  p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        +  p2x2: "p5.js는 "
        +  p2x3: " (프로세싱)을 오늘날의 웹에 맞게 해석한 버전이라 볼 수 있습니다. p5의 행사와 모임은 "
        +  p2x4: " (프로세싱 재단)의 지원을 받아 개최됩니다."
        +  p2x5: ""
        +  p2x6: "커뮤니티"
        +  p2x7: "에 대해 더 알아보세요."
         
        -  p3xh2: "Get Started"
        -  p3xp1: "Make your first sketch in the "
        -  p3xp2: ". Learn more about sketching with p5.js on the "
        -  p3xp3: "Get Started page"
        -  p3xp4: " and everything you can do in the "
        -  p3xp5: "Reference"
        -  p3xp6: "."
        +  p3xh2: "시작하기"
        +  p3xp1: "온라인 에디터인 "
        +  p3xp2: "에서 나만의 첫 스케치를 그려보세요! "
        +  p3xp3: "시작하기"
        +  p3xp4: "에서 p5 스케치에 대해 알아보고, "
        +  p3xp5: "레퍼런스"
        +  p3xp6: "로 더욱 많은 기능을 확인해보세요."
         
        -  p4xh2: "Get Involved"
        -  p4xp1: "There are many ways to contribute to p5.js:"
        -  p4xp2: "Involvement Options"
        -  p4xp3: "Share something you've made!"
        -  p4xp4: "Teach a workshop or class."
        -  p4xp5: "Organize a meet-up."
        -  p4xp6: "Contribute to the codebase."
        +  p4xh2: "함께하기"
        +  p4xp1: "p5.js와 커뮤니티에 기여할 수 있는 방법은 다양합니다:"
        +  p4xp2: "함께하는 방법"
        +  p4xp3: "나의 창작 프로젝트 공유하기"
        +  p4xp4: "p5 워크숍 또는 수업 운영하기"
        +  p4xp5: "행사 또는 모임 주관하기"
        +  p4xp6: "코딩 개발로 기여하기"
         
           sketch_by: "by"
        -  sketch_info: "Homepage sketch adapted from work by 9th grader Grace Obergfell"
        -  sketch_info_link: "CC Fest NYC on June 8, a free and inclusive coding event for students and teachers"
        +  sketch_info: "홈페이지 스케치는 9학년 그레이스 오버그펠(Grace Obergfell)의 작품을 만들었습니다."
        +  sketch_info_link: "6월 8일 CC Fest NYC, 학생과 선생님들을 포용하는 무료 코딩 행사"
         
         copyright:
        -  copyright-title: "Copyright Information"
        -  copyright1: "The p5.js library is free software; you can redistribute it and/or modify it under the terms of the "
        -  copyright2: " as published by the Free Software Foundation, version 2.1."
        +  copyright-title: "저작권"
        +  copyright1: "p5.js 라이브러리는 무료 소프트웨어입니다."
        +  copyright2: " Free Software Foundation의 조항(version 2.1.)에 따라 재배포 및 수정할 수 있습니다."
           copyright3: "The Reference for the language is under a "
           copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited."
         
         get started:
        -  get-started-title: "Get Started"
        -  get-started1: "This page walks you through setting up a p5.js project and making your first sketch."
        -  get-started2: "If you'd like to start with the new "
        -  get-started3: "p5.js Editor"
        -  get-started4: ", you can jump down to"
        -  get-started5: "Your First Sketch"
        -  download-title: "Download and File Setup"
        -  download1: "The easiest way to start is by using the empty example that comes with the "
        +  get-started-title: "시작하기"
        +  get-started1: "p5.js 프로젝트를 설정하고 나의 첫 스케치를 만드는 방법을 소개합니다."
        +  get-started2: ""
        +  get-started3: "p5.js 웹에디터"
        +  get-started4: "로 스케치를 만들고 싶다면 이 곳을 클릭하세요:"
        +  get-started5: "나의 첫 스케치"
        +  download-title: "다운로드 & 파일 설정"
        +  download1: " "
           download2: "p5.js complete"
        -  download3: " download."
        -  download4: "If you look in index.html, you'll notice that it links to the file p5.js. If you would like to use the minified version (compressed for faster page loading), change the link to p5.min.js."
        -  download5: "Alternatively, you can link to a p5.js file hosted online. All versions of p5.js are stored in a CDN (Content Delivery Network). You can see a history of these versions here: "
        -  download6: ". In this case you can change the link to:"
        -  download7: "A sample HTML page might look like this:"
        -  download8: "You can also start with this template from "
        +  download3: "와 함께 제공되는 빈 예제 프로젝트를 이용해 쉽게 테스트 해보세요."
        +  download4: "그 중 index.html 파일에는 p5.js 링크가 적혀있습니다. 로딩 시간을 단축하려면 이 p5.js 링크를 간략 버전인 p5.min.js로 아래와 같이 변경하면 됩니다. "
        +  download5: "또는, p5.js 파일의 온라인 링크를 입력하는 방법도 있습니다. p5.js의 모든 버전은 CDN (Content Delivery Network)에 저장되어 있으며, 버전 히스토리는 여기서 확인할 수 있습니다: "
        +  download6: ". 링크를 다음과 같이 변경해보세요:"
        +  download7: "아래는 HTML 페이지 샘플입니다:"
        +  download8: "위의 HTML 페이지 템플릿을 코드펜(CodePen)에 복사, 붙여넣기하여 프로젝트를 시작하는 것도 한 방법입니다: "
           download9: "."
        -  environment-title: "Environment"
        -  environment1: "You can use the "
        +  environment-title: "개발 환경"
        +  environment1: "여러분이 원하는 그 어떠한 "
           environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor"
        -  environment2: " code editor "
        -  environment3: "of your choice. Instructions for getting set up with "
        -  environment4: " are included below, other good editor options include "
        -  environment5: " and "
        -  environment6: "If you are a screen reader user and not using the p5 web editor, you may want to use "
        -  environment7: " or "
        -  environment8: "Open Sublime. Go to the File menu and choose Open... and choose the folder that your html and js files are located in. On the left sidebar, you should now see the folder name at the top, with a list of the files contained in the folder directly below."
        -  environment9: "Click on your sketch.js file and it will open on the right where you can edit it. "
        -  environment10: "p5 starter code opened up in sublime editor."
        -  environment11: "Open the index.html file in your browser by double clicking on it in your file manager or type:"
        +  environment2: "코드 에디터"
        +  environment3: "도 p5.js를 위해 사용할 수 있습니다. 아래에 "
        +  environment4: " 에디터를 설정하는 방법이 있습니다.  추천하는 또다른 에디터: "
        +  environment5: ", "
        +  environment6: " p5 웹에디터를 이용하지 않는 스크린 리더(screen reader)라면, 다음의 에디터를 고려해보세요: "
        +  environment7: " 나 "
        +  environment8: "먼저, Sublime Text 2 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, html 파일과 js 파일이 위치한 폴더를 선택하세요. 폴더 이름과 폴더에 포함된 파일 리스트가 좌측 사이드바에 보일 것입니다."
        +  environment9: "sketch.js 파일을 선택하면, 우측 편집 영역에서 파일이 열립니다. "
        +  environment10: "Sublime 에디터에서 p5 템플릿 코드를 편집 중인 화면"
        +  environment11: "index.html 파일을 브라우저에서 열어볼까요? 파일 관리 시스템에서 index.html 파일을 더블 클릭하거나 브라우저 주소창에 다음을 입력하세요:"
           environment12: "file:///the/file/path/to/your/html"
        -  environment13: " in the address bar to view your sketch."
        -  your-first-sketch-title: "Your First Sketch"
        -  your-first-sketch-intro1: "Processing users may want to check out the "
        +  environment13: " "
        +  your-first-sketch-title: "나의 첫 스케치"
        +  your-first-sketch-intro1: "프로세싱(Processing) 유저라면 다음의 페이지를 읽어보세요: "
           your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  your-first-sketch-intro3: "Processing transition tutorial"
        -  your-first-sketch-intro4: "In your editor, type the following:"
        -  your-first-sketch2: "This line of code means \"draw an ellipse, with the center 50 pixels over from the left and 50 pixels down from the top, with a width and height of 80 pixels\"."
        -  your-first-sketch3: "Save your sketch and refresh your page view in your browser. If you've typed  everything correctly, you'll see this appear in the display window:"
        -  your-first-sketch4: "If you are using a screen reader, you must either turn on the accessible outputs in the p5 online editor, outside the editor you must add the accessibility library in your html. To learn about "
        -  your-first-sketch5: "using p5 with a screen reader"
        -  your-first-sketch6: " and to learn more about "
        -  your-first-sketch7: "the accessibility library"
        -  your-first-sketch8: "canvas has a circle of width and height 50 at position 80 x and 80 y"
        -  your-first-sketch9: "If you didn't type it correctly, you might not see anything. If this happens, make sure that you've copied the example code exactly: the numbers should be contained within parentheses and have commas between each of them, and the line should end with a semicolon."
        -  your-first-sketch10: "One of the most difficult things about getting started with programming is that you have to be very specific about the syntax. The browser isn't always smart enough to know what you mean, and can be quite fussy about the placement of punctuation. You'll get used to it with a little practice. Depending on the browser you are using, you can also see errors by looking at the JavaScript \"console\". In Chrome, for example, this is under View > Developer > JavaScript Console."
        -  your-first-sketch11: "Next, we'll skip ahead to a sketch that's a little more exciting. Delete the text from the last example, and try this:"
        -  your-first-sketch12: "This program creates a canvas that is 640 pixels wide and 480 pixels high, and then starts drawing white circles at the position of the mouse. When a mouse button is pressed, the circle color changes to black. We'll explain more about the elements of this program in detail later. For now, run the code, move the mouse, and click to experience it."
        -  your-first-sketch13: "canvas has multiple circles drawn on it following the path of the mouse"
        -  first-sketch-heading1: "Code snippet with ellipse"
        -  first-sketch-heading2: "Note for screenreader users"
        -  first-sketch-heading3: "Code snippet with interaction"
        -  what-next-title: "What Next?"
        -  processing-transition1: "Read the "
        +  your-first-sketch-intro3: "Processing에서 p5.js로 변환하기 튜토리얼"
        +  your-first-sketch-intro4: "에디터에 다음을 입력하세요:"
        +  your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다: \"좌층 상단 모서리에서 아래로 50px, 오른쪽으로 50px 떨어진 점을 중심으로 삼는 타원을 그린다. 타원의 폭과 높이는 모두 80px로 한다.\" "
        +  your-first-sketch3: "스케치를 저장하고 브라우저 페이지에서 새로고침을 해보세요. 입력한 코드에 문제가 없는 한, 다음과 같은 화면을 볼 수 있습니다:"
        +  your-first-sketch4: "주의: 스크린 리더를 사용하는 경우, p5 웹에디터에서 Accessible Outputs를 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: "
        +  your-first-sketch5: "스크린 리더에서 p5를 사용하는 방법"
        +  your-first-sketch6: " , "
        +  your-first-sketch7: "접근성 라이브러리란?"
        +  your-first-sketch8: "캔버스에 폭과 높이가 50인 타원이 x 80, y 80의 위치에 그려져있다"
        +  your-first-sketch9: "코드를 잘못 입력할 경우 화면에 아무것도 나타나지 않을 수 있습니다. 예제 코드를 정확히 따라 썼는지 확인해 보세요. 숫자는 (괄호) 안에 포함하고, 각 숫자는 쉼표(,)로 구분해야 하며, 각 라인은 세미 콜론(;)으로 끝나야 합니다"
        +  your-first-sketch10: "프로그래밍 언어를 처음 접할 때 겪는 어려움 중 하나는 문법이 매우 까다롭다는 것입니다. 브라우저는 우리가 표현하고자 바가 무엇인지 스스로 이해할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감합니다. 처음에는 이런 문법이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바 스크립트 '콘솔'을 제공합니다. 크롬(Chrome)의 경우, 보기 > 개발자 > 자바 스크립트 콘솔을 클릭하여 '콘솔'을 활성화할 수 있습니다."
        +  your-first-sketch11: "이제 한층 더 재밌는 스케치를 만들어볼까요! 지난 예제의 코드를 에디터에서 삭제하고 아래의 코드를 입력해 보세요:"
        +  your-first-sketch12: "이제 프로그램은 폭 640px, 높이 480px의 캔버스를 생성하고, 마우스 커서 위치에서 흰 원을 그리기 시작합니다. 마우스 버튼을 누르고 있을 때는 원의 색이 검정색으로 바뀝니다. 마우스 위치에 대한 설명은 나중에 더 하기로 하고, 지금은 마우스를 움직이고 클릭하며 스케치의 변화를 살펴보세요."
        +  your-first-sketch13: "캔버스에 마우스 궤적을 따라 여러개의 원이 그려져있다"
        +  first-sketch-heading1: "타원과 코드 스니펫(snippet)"
        +  first-sketch-heading2: "Note for 스크린리더 사용자를 위한"
        +  first-sketch-heading3: "인터랙션과 코드 스니펫(snippet)"
        +  what-next-title: "다음 단계"
        +  processing-transition1: "Processing을 p5.js로 전환하는 방법과 둘 간의 차이점이 궁금하다면, "
           processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  processing-transition3: "Processing transition tutorial"
        -  processing-transition4: " to learn how to convert from Processing to p5.js, and the main differences between them."
        -  reference1: "View the "
        -  reference2: " reference"
        -  reference3: " for full documentation."
        -  learn1: "Check out the "
        -  learn2: "learn"
        -  learn3: " page and "
        -  learn4: "examples"
        -  learn5: " page for more."
        -  learn6: "If you wish to use p5 with a screenreader, check out the "
        -  learn7: "p5 with a screenreader tutorial"
        -  book1: "Parts of this tutorial were adapted from the book, Getting Started with p5.js, by Lauren McCarthy, Casey Reas, and Ben Fry, O'Reilly / Make. Copyright © 2015. All rights reserved."
        +  processing-transition3: "Processing에서 p5.js로 변환하기 튜토리얼"
        +  processing-transition4: "을 읽어보세요."
        +  reference1: "p5.js에 대한 전체 문서를 보려면 "
        +  reference2: "레퍼런스"
        +  reference3: "를 읽어보세요."
        +  learn1: "더 많은 학습 자료가 필요하다면 "
        +  learn2: "배우기"
        +  learn3: " 페이지와 "
        +  learn4: "예제"
        +  learn5: " 페이지를 살펴보세요."
        +  learn6: "스크린 리더 모드로 p5를 사용하고 싶다면, 다음 페이지를 읽어보세요: "
        +  learn7: "스크린 리더상 p5 사용하기 튜토리얼"
        +  book1: "본 튜토리얼의 일부는 로렌 맥카시(Lauren McCarthy), 캐시 리스(Casey Reas), 벤 프라이(Ben Fry), 오라일리(O'Reilly) 저 Getting Started with p5.js 에서 발췌하였습니다. / Make 2015. Copyright "
         
         download:
        -  Download: "Download"
        -  download-intro: "Welcome! While titled \"Download\" this page actually contains a collection of links to either download the library or begin working with it online. We've tried to order things to reflect what a beginner might want first, to resources that more experienced programmers may be looking for."
        -  editor-title: "Editor"
        -  p5.js-editor: "p5.js Editor"
        -  p5.js-editor-intro: "This link redirects you to the p5.js Editor online so you can begin using p5.js immediately."
        -  editor-includes: "Start coding using the p5.js Editor, no setup required!"
        -  complete-library-title: "Complete Library"
        -  complete-library-intro1: "This is a download containing the p5.js library file, the p5.sound addon, and an example project. It does not contain an editor. See "
        -  complete-library-intro2: "Get Started"
        -  complete-library-intro3: " to learn how to setup a p5.js project."
        -  p5.js-complete: "p5.js complete"
        -  includes-1: "Includes:"
        -  includes-2: "p5.js, p5.sound.js, and an example project"
        +  Download: "다운로드"
        +  download-intro: "안녕하세요! 이 페이지는 온라인에서 바로 사용가능한 웹에디터와 각종 다운로드 링크를 소개합니다. 초심자에게 꼭 필요한 자료부터 숙련된 개발자를 위한 리소스 모두를 포괄합니다."
        +  editor-title: "에디터"
        +  p5.js-editor: "p5.js 에디터"
        +  p5.js-editor-intro: "아래의 링크는 온라인 p5.js 에디터로 연결됩니다."
        +  editor-includes: "별도 설치가 필요없는 p5.js 웹에디터로 지금 바로 코딩을 시작해보세요!"
        +  complete-library-title: "모든 라이브러리"
        +  complete-library-intro1: "아래의 링크는 p5.js 라이브러리 파일, p5.sound, 그리고 예제 프로젝트를 포함합니다. "
        +  complete-library-intro2: "시작하기"
        +  complete-library-intro3: "에서 p5.js 프로젝트 설정 방법을 알아보세요."
        +  p5.js-complete: "모든 라이브러리"
        +  includes-1: "포함 사항:"
        +  includes-2: "p5.js, p5.sound.js, 예시 프로젝트 1개"
           includes-3: "Version "
        -  single-files-title: "Single Files"
        -  single-files-intro: "These are downloads or links to the p5.js library file. No additional contents are included."
        -  single-file: "Single file: "
        -  p5.js-uncompressed: "Full uncompressed version"
        -  compressed: "Compressed version"
        -  link: "Link: "
        -  statically-hosted-file: "Statically hosted file"
        -  etc-title: "Github Resources"
        -  older-releases: "Previous versions (older releases and changelog)"
        -  github-repository: "Code repository (GitHub)"
        -  report-bugs: "Report issues, bugs, and errors"
        -  supported-browsers: "Supported browsers "
        +  single-files-title: "개별 라이브러리"
        +  single-files-intro: "개별 라이브러리 파일입니다. "
        +  single-file: "개별 라이브러리: "
        +  p5.js-uncompressed: "개별 파일"
        +  compressed: "압축 버전"
        +  link: "링크: "
        +  statically-hosted-file: "정적 호스팅 파일"
        +  etc-title: "Github 리소스"
        +  older-releases: "이전 버전 (구버전 및 변경 로그)"
        +  github-repository: "코드 저장소 (GitHub)"
        +  report-bugs: "이슈, 버그, 에러 보고하기"
        +  supported-browsers: "지원 브라우저 "
         
        -  support-title: "Support p5.js!"
        -  support-options: "Support Options"
        -  support-1: "p5.js is free, open-source software. We want to make our community as open and inclusive as possible. You can support this work by "
        -  support-2: "becoming a member"
        -  support-3: " of the Processing Foundation as an individual, a studio, or an educational institution. You can also "
        -  support-4: "make a donation"
        -  support-5: " without purchasing a membership."
        -  support-6: "Individual"
        +  support-title: "p5.js를 후원해주세요!"
        +  support-options: "기부 방법"
        +  support-1: "p5.js는 무료 오픈 소스 소프트웨어입니다. p5.js는 다양성을 향해 늘 열려있고 이를 포용하는 커뮤니티를 지향합니다. "
        +  support-2: "프로세싱 재단 멤버십 가입"
        +  support-3: "을 통해 개인, 스튜디오, 또는 교육 기관 단위로 기부하거나, 또는 "
        +  support-4: "멤버십 가입 생략"
        +  support-5: " 후 기부할 수 있습니다."
        +  support-6: "개인"
           support-7: "$25"
        -  support-8: "Studio"
        +  support-8: "스튜디오"
           support-9: "$250"
        -  support-10: "Educational Institution"
        -  support-11: "$5/student or $500"
        -  support-12: "Your membership supports software development (for p5.js, Processing, Processing.py, Processing for Android and ARM devices, education resources like code examples and tutorials, "
        -  support-13: "Fellowships"
        -  support-14: ", and "
        -  support-15: "community events"
        -  support-16: ". We need your help!"
        -  support-17: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)"
        -  support-18: "Processing Fellow Saskia Freeke is organizing Code Liberation x Processing workshops in London (Image credit: Code Liberation Foundation)"
        -  support-19: "Learning to Teach, Teaching to Learn conference with SFPC (Image credit: Kira Simon-Kennedy)"
        -  support-20: "Processing Foundation Fellow Cassie Tarakajian's workshop at Code Art Miami (Image credit: Christian Arévalo Photography)"
        -  support-21: "Taeyoon Choi and ASL interpretor at Signing Coders p5.js workshop (Image credit: Taeyoon Choi)"
        -  support-22: "Google Summer of Code kickoff (Image credit: Taeyoon Choi)"
        -  support-23: "Processing Foundation Fellow Cassie Tarakajian's workshop at Code Art Miami (Image credit: Christian Arévalo Photography)"
        -  support-24: "Luisa Pereira and Yeseul Song helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        -  support-25: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)"
        -  support-26: "Processing Fellow Digital Citizens Lab hosts a panel on STEM teaching at the International Center of Photography (Image credit: International Center of Photography)"
        -  support-27: "Participants at p5.js workshop in Santiago, Chile, led by Aarón Montoya-Moraga (Image credit: Aarón Montoya-Moraga.)"
        +  support-10: "교육 기관"
        +  support-11: "$5/학생1인 또는 $500"
        +  support-12: "여러분의 멤버십 기부금은 소프트웨어(p5.js, Processing, Processing.py, Processing for Android Processing for ARM devices)와 코딩 예제 및 튜토리얼 등의 교육 자료 개발, "
        +  support-13: "펠로우십"
        +  support-14: ", 그리고 "
        +  support-15: "커뮤니티 행사"
        +  support-16: "를 지원하는 데에 사용됩니다. 여러분의 도움이 필요합니다!"
        +  support-17: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-18: "프로세싱 재단 펠로우 Saskia Freeke이 런던에서 주관한 Liberation x Processing workshops (이미지 저작권: Code Liberation Foundation)"
        +  support-19: "SPFC와 함께한 Learning to Teach, Teaching to Learn 컨퍼런스 (이미지 저작권: Kira Simon-Kennedy)"
        +  support-20: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
        +  support-21: "Signing Coders p5.js workshop에서의 최태윤(Taeyoon Choi)과 미국 수어(ASL) 해설자 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-22: "구글 썸머 오브 코드(Google Summer of Code) 킥오프 행사 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-23: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
        +  support-24: "최태윤의 수어 기반 p5.js workshop에서 진행을 돕는 Luisa Pereira와 송예슬Yeseul Song (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-25: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-26: "프로세싱 재단 펠로우 Digital Citizens Lab가 International Center of Photography에서 주최한 STEM teaching 패널 (이미지 저작권: International Center of Photography)"
        +  support-27: "칠레 산티아고에서 Aarón Montoya-Moraga가 진행한 p5.js workshop (이미지 저작권: Aarón Montoya-Moraga.)"
           support-28: "Claire Kearney-Volpe helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        -  support-29: "Processing Foundation Fellow DIY Girls run a creative coding program in Los Angeles (Image credit: DIY Girls)"
        -  support-30: "Processing Fellow Digital Citizens Lab"
        -  support-31: "Bicoastal p5.js meetup at UCLA DMA and NYU ITP"
        -  support-32: "The Processing Foundation"
        -  support-33: " was founded in 2012 after more than a decade of work with the original Processing software. The Foundation’s mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources."
        +  support-29: "프로세싱 재단 펠로우 DIY Girls가 미국 로스 엔젤레스(Los Angeles)에서 진행한 크리에이티브 코딩 프로그램 (이미지 저작권: DIY Girls)"
        +  support-30: "프로세싱 재단 펠로우 Digital Citizens Lab"
        +  support-31: "UCLA DMA와 NYU ITP 간의 동서-해안 p5.js 모임"
        +  support-32: "프로세싱 재단"
        +  support-33: "은 10여년 간의 프로세싱 소프트웨어(Processing Software) 개발 활동을 거쳐, 2012년에 설립되었습니다. 프로세싱 재단의 사명은 시각 예술계에서의 소프트웨어 리터러시와 기술 관련 분야에서의 시각적 리터러시를 증진하고, 나아가 이 두 분야에 대한 보다 많은 사람들의 접근성을 향상하는 데에 있습니다. 우리는 다양한 이해와 배경을 가진 사람들, 특히 코딩 학습을 위한 툴이나 자원에 대한 접근성이 없는 이들이 크리에이티브 코딩을 배울 수 있도록 돕는 것에 목표를 둡니다."
           support-17-alt: ""
           support-18-alt: ""
           support-19-alt: ""
        @@ -218,451 +219,451 @@ download:
           support-31-alt: ""
         
         learn:
        -  learn-title: "Learn"
        -  learn1: "These tutorials provide more in-depth or step-by-step overviews of particular topics. Check out the "
        -  learn2: "examples page"
        -  learn3: "to see short demonstrations of various p5.js topics."
        -  introduction-to-p5js-title: "Introduction to p5.js"
        +  learn-title: "배우기"
        +  learn1: "주제별 깊이있고 순차적인 설명과 튜토리얼을 제공합니다. p5.js 함수에 대해 종류별로 알고싶다면 "
        +  learn2: "예제"
        +  learn3: "를 클릭하세요."
        +  introduction-to-p5js-title: "p5.js 소개"
           hello-p5js-title: "Hello p5.js"
        -  hello-p5js: "This short video will introduce you to the library and what you can do with it."
        -  getting-started-title: "Getting Started"
        -  getting-started: "Welcome to p5.js! <br> This introduction covers the basics of setting up a p5.js project."
        -  p5js-overview-title: "p5.js overview"
        -  p5js-overview: "An overview of the main features of p5.js."
        -  p5js-processing-title: "p5.js and Processing"
        -  p5js-processing: "The main differences between the two, and how to convert from one to the other."
        -  p5-screen-reader-title: "p5 with a screen reader"
        -  p5-screen-reader: "Setting up p5 so that it can be used easily with a screen reader."
        -  using-local-server-title: "Using a local server"
        -  using-local-server: "How to set up a local server on Mac OSX, Windows, or Linux."
        -  p5js-wiki-title: "p5.js wiki"
        -  p5js-wiki: "Additonal documentation and tutorials contributed by the community"
        -  connecting-p5js-title: "Connecting p5.js"
        -  creating-libraries-title: "Creating libraries"
        -  creating-libraries: "Creating p5.js addon libraries."
        -  nodejs-and-socketio-title: "node.js and socket.io"
        -  nodejs-and-socketio: "Using a node.js server with p5.js, communication via socket.io."
        -  programming-topics-title: "Programming topics"
        -  beyond-the-canvas-title: "Beyond the canvas"
        -  beyond-the-canvas: "Creating and manipulating elements on the page beyond the canvas."
        +  hello-p5js: "이 영상을 통해 p5.js 라이브러리가 무엇인지, 또 어떻게 활용할 수 있을지 알아보세요."
        +  getting-started-title: "시작하기"
        +  getting-started: "p5.js에 오신 것을 환영합니다. <br> 이 섹션은 p5.js 프로젝트 설정을 위한 기본적인 내용들을 다룹니다."
        +  p5js-overview-title: "p5.js 주요 기능"
        +  p5js-overview: "p5.js 주요 기능에 대한 개괄 설명을 확인하세요."
        +  p5js-processing-title: "p5.js와 Processing"
        +  p5js-processing: "p5와 Processing 간의 주요 차이점, 그리고 호환 방법을 알아보세요."
        +  p5-screen-reader-title: "p5와 스크린 리더"
        +  p5-screen-reader: "스크린 리더를 위한 p5 설정 방법을 알아보세요."
        +  using-local-server-title: "로컬 서버 사용하기"
        +  using-local-server: "맥 OSX, 윈도우, 리눅스 상에서 로컬 서버 설정하기"
        +  p5js-wiki-title: "p5.js 위키(wiki)"
        +  p5js-wiki: "커뮤니티의 기여로 제작된 레퍼런스와 튜토리얼"
        +  connecting-p5js-title: "p5.js에 연결하기"
        +  creating-libraries-title: "라이브러리 만들기"
        +  creating-libraries: "p5.js 추가 라이브러리 만들기"
        +  nodejs-and-socketio-title: "node.js와 socket.io"
        +  nodejs-and-socketio: "p5.js로 node.js 서버 사용하기, socket.io로 연결, 통신하기"
        +  programming-topics-title: "프로그래밍 주제"
        +  beyond-the-canvas-title: "캔버스 너머서"
        +  beyond-the-canvas: "페이지상 캔버스 너머의 요소들 만들고 조작하기"
           3d-webgl-title: "3D/WebGL"
        -  3d-webgl: "Developing advanced graphics applications in p5.js using WEBGL mode."
        -  color-title: "Color"
        -  color: "An introduction to digital color."
        -  coordinate-system-and-shapes-title: "Coordinate System and Shapes"
        -  coordinate-system-and-shapes: "Drawing simple shapes and using the coordinate system."
        -  interactivity-title: "Interactivity"
        -  interactivity: "Introduction to interactivity with the mouse and keyboard."
        -  program-flow-title: "Program Flow"
        -  program-flow: "Introduction to controlling program flow in p5.js."
        -  curves-title: "Curves"
        -  curves: "An introduction to the three types of curves in p5.js: arcs, spline curves, and Bézier curves."
        -  becoming-a-better-programmer-title: "Becoming a better programmer"
        -  debugging-title: "Debugging"
        -  debugging: "Field guide to debugging for everyone."
        -  optimizing-title: "Optimizing p5.js code for performance"
        -  optimizing: "A tutorial of tips and tricks for optimizing your code to make it run faster and smoother."
        -  test-driven-development-title: "Unit testing and test driven development"
        -  test-driven-development: "Save yourself from agony on install day. What is unit testing and how to use it? By Andy Timmons."
        -  contributing-to-the-community-title: "Contributing to the community"
        -  development-title: "Development"
        -  development: "Getting started and overview for contributing to development."
        -  looking-inside-title: "Looking inside p5"
        -  looking-inside: "A friendly intro to the file structure and tools for p5.js development, by Luisa Pereira."
        -  writing-tutorial-title: "Writing a tutorial"
        -  writing-tutorial: "A guide to writing a p5.js programming tutorial."
        -  writing-a-tutorial-title: "Guide to contributing p5.js tutorials"
        -  writing-a-tutorial-author: "This tutorial was written by Tega Brain."
        -  writing-a-tutorial-1: "We invite educators, contributors and general enthusiasts to contribute p5js tutorials. The p5js project makes creative coding and open source development more accessible to a diverse community and we are excited to publish tutorials on all aspects of the development process. Our learning materials so far include guides on learning p5, programming technique and how to contribute to an open source project."
        -  writing-a-tutorial-2: "We welcome new written tutorial contributions and this guide outlines the steps of how to propose, prepare and contribute."
        -  writing-a-tutorial-how-start-title: "How to get started:"
        -  writing-a-tutorial-how-start-1: "Check that your proposed topic has not already been covered. There is "
        -  writing-a-tutorial-how-start-2: "a working spreadsheet here"
        -  writing-a-tutorial-how-start-3: "that outlines in progress tutorials. If your topic is listed as in progress, perhaps you can add to work being done and contribute to preparing existing work for publication so please reach out to us."
        -  writing-a-tutorial-how-start-4: "If your topic is not already covered and is not listed as in progress, please write a few sentences on what you propose to cover and email us this description at education@p5js.org."
        -  writing-a-tutorial-how-prepare-title: "How to prepare a p5js tutorial for publication online:"
        -  writing-a-tutorial-how-prepare-1: "When your tutorial is ready for publication, please follow these steps to prepare your content for the p5js website."
        -  writing-a-tutorial-how-prepare-2: "Prepare the content of your tutorial as a tutorial-name.hbs file with "
        -  writing-a-tutorial-how-prepare-3: "this basic structure"
        -  writing-a-tutorial-how-prepare-4: ". As is shown in this file, it must contain a header as shown below:"
        -  writing-a-tutorial-how-prepare-5: "The folder containing your tutorial will be placed in the 'tutorials' folder of the p5js site. The file called index.hbs is the "
        -  writing-a-tutorial-how-prepare-6: "p5.js tutorials landing page,"
        -  writing-a-tutorial-how-prepare-7: " and the test-tutorial.hbs file is the test tutorial."
        -  writing-a-tutorial-how-prepare-8: "All content should go in the:"
        -  writing-a-tutorial-how-prepare-9: "tags on the page, with formatting defined by the &lt;h1&gt; and &lt;h2&gt; tags, the &lt;p&gt; paragraph tags as is done shown on the"
        -  writing-a-tutorial-how-prepare-10: "test tutorial page."
        -  writing-a-tutorial-how-prepare-11: "If your tutorial contains images, they are to be placed in the assets folder of the p5 site, in the location src/assets/learn/test-tutorial/images as shown below."
        -  writing-a-tutorial-how-prepare-12: "To correctly format code in the html of the page use the tag:"
        -  writing-a-tutorial-embedding-title: "Embedding p5.js sketches"
        -  writing-a-tutorial-embedding-1: "Using p5js means you can illustrate your tutorial with animated, interactive or editable code examples to demonstrate programming concepts. Your examples should be prepared as p5.js sketches and can be embedded into the tutorial in two ways."
        -  writing-a-tutorial-embedding-2: "If the example is to be editable like in "
        -  writing-a-tutorial-embedding-3: "the reference pages"
        -  writing-a-tutorial-embedding-4: " of the p5js site, the p5 sketch should be embedded into the html page using the p5js widget. Follow "
        -  writing-a-tutorial-embedding-5: "this guide "
        -  writing-a-tutorial-embedding-6: "on how to embed p5js sketches using the widget written by "
        -  writing-a-tutorial-embedding-7: ". You can also see this in action on the"
        -  writing-a-tutorial-embedding-8: " test tutorial page"
        -  writing-a-tutorial-embedding-9: "."
        -  writing-a-tutorial-embedding-10: "If the example is to be animated and/or interactive but not editable. The p5.js sketch should be embedded into the page as an iframe as described below."
        -  writing-a-tutorial-iframe-title: "Embed a p5 sketch using an iframe"
        -  writing-a-tutorial-iframe-1: "An iframe is like creating a window through which you can see another page, sandboxed from the rest of your page. In this case it will be a window to the index.html containing your p5.js sketch. "
        -  writing-a-tutorial-iframe-2: "Put your p5 sketches in the /src/assets/learn folder of the site, in a folder labelled with the name of your sketch as shown in the screenshot. This is where all the images and p5 sketches linked by iframe should be stored."
        -  writing-a-tutorial-iframe-3: "In the subfolders containing your p5 examples there should be a sketch.js file and the embed.html file for the sketch. "
        -  writing-a-tutorial-iframe-4: "Make sure your embed.html file has the correct paths to the p5 libraries of the site. If your file structure is the same as above, the path to the p5.js library should be \"../../../js/p5.min.js\"."
        -  writing-a-tutorial-iframe-5: "You can then embed the p5js index files as iframes in the .hbs file that contains your tutorial content. The embed code for the iframe would then be: "
        -  writing-a-tutorial-iframe-6: "Styling for the iframe (this could directly into the post or in a stylesheet):  "
        -  writing-a-tutorial-iframe-7: "Here you can see the naked sketch running: "
        -  writing-a-tutorial-iframe-8: "And here it is embedded in the p5 site using the code below:  "
        -  writing-a-tutorial-iframe-9: "One thing to note is that you need to manually set the size of the iframe, so it works best if things are a standard size."
        -  writing-a-tutorial-iframe-10: "Also note that the links to the p5.js library files do not happen from the .eps page with all the tutorial content. Instead they will be located in the html page that is rendering your sketch (in this case, called embed.html)."
        -  writing-a-tutorial-iframe-11: "More information on embedding p5.js sketches can be found "
        -  writing-a-tutorial-embed-iframe-12: "here."
        -  writing-a-tutorial-finishing-title: "Finishing up"
        -  writing-a-tutorial-finishing-1: "Once your have finished writing your tutorial and your content has been given the thumbs up. Fork the p5.js website repository, prepare your content as described above and then issue a pull request to the p5.js website repository so we can publish your contribution!"
        -  writing-a-tutorial-finishing-2: "Thank you!"
        -  color-description1: "This tutorial is from the book Learning Processing by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to P5 by Kelly Chang. If you see any errors or have comments, "
        -  color-description2: " please let us know."
        -  color-p1x1: "In the digital world, when we want to talk about a color, precision is required. Saying \"Hey, can you make that circle bluish-green?\" will not do. Color, rather, is defined as a range of numbers. Let's start with the simplest case: black & white or grayscale. 0 means black, 255 means white. In between, every other number—50, 87, 162, 209, and so on—is a shade of gray ranging from black to white."
        -  color-p2x1: "By adding the "
        -  color-p2x2: " and "
        -  color-p2x3: " functions before something is drawn, we can set the color of any given shape. There is also the function "
        -  color-p2x4: ", which sets a background color for the window. Here's an example."
        -  color-code1: "background(255);    // Setting the background to white \n stroke(0);          // Setting the outline (stroke) to black \n fill(150);          // Setting the interior of a shape (fill) to grey \n rect(50,50,75,100); // Drawing the rectangle"
        -  color-p3x1: "Stroke or fill can be eliminated with the functions: "
        -  color-p3x2: " and "
        -  color-p3x3: ". Our instinct might be to say \"stroke(0)\" for no outline, however, it is important to remember that 0 is not \"nothing\", but rather denotes the color black. Also, remember not to eliminate both—with "
        -  color-p3x4: " and "
        -  color-p3x5: ", nothing will appear!"
        -  color-p4x1: "In addition, if we draw two shapes, p5.js will always use the most recently specified stroke and fill, reading the code from top to bottom."
        -  color-rgb-title: "RGB Color"
        -  color-rgb-p1x1: "Remember finger painting? By mixing three \"primary\" colors, any color could be generated. Swirling all colors together resulted in a muddy brown. The more paint you added, the darker it got. Digital colors are also constructed by mixing three primary colors, but it works differently from paint. First, the primaries are different: red, green, and blue (i.e., \"RGB\" color). And with color on the screen, you are mixing light, not paint, so the mixing rules are different as well."
        -  color-rgb-li1: "Red + Green = Yellow"
        -  color-rgb-li2: "Red + Blue = Purple"
        -  color-rgb-li3: "Green + Blue = Cyan (blue-green)"
        -  color-rgb-li4: "Red + Green + Blue = White"
        -  color-rgb-li5: "No colors = Black"
        -  color-rgb-p2x1: "This assumes that the colors are all as bright as possible, but of course, you have a range of color available, so some red plus some green plus some blue equals gray, and a bit of red plus a bit of blue equals dark purple. While this may take some getting used to, the more you program and experiment with RGB color, the more it will become instinctive, much like swirling colors with your fingers. And of course you can't say \"Mix some red with a bit of blue,\" you have to provide an exact amount. As with grayscale, the individual color elements are expressed as ranges from 0 (none of that color) to 255 (as much as possible), and they are listed in the order R, G, and B. You will get the hang of RGB color mixing through experimentation, but next we will cover some code using some common colors."
        -  color-transparency-title: "Color Transparency"
        -  color-transparency-p1x1: "In addition to the red, green, and blue components of each color, there is an additional optional fourth component, referred to as the color's \"alpha\". Alpha means transparency and is particularly useful when you want to draw elements that appear partially see-through on top of one another. The alpha values for an image are sometimes referred to collectively as the \"alpha channel\" of an image."
        -  color-transparency-p2x1: "It is important to realize that pixels are not literally transparent, this is simply a convenient illusion that is accomplished by blending colors. Behind the scenes, p5.js takes the color numbers and adds a percentage of one to a percentage of another, creating the optical perception of blending. (If you are interested in programming \"rose-colored\" glasses, this is where you would begin.)"
        -  color-transparency-p3x1: "Alpha values also range from 0 to 255, with 0 being completely transparent (i.e., 0% opaque) and 255 completely opaque (i.e., 100% opaque)."
        -  color-custom-ranges-title: "Custom Color Ranges"
        -  color-custom-ranges-p1x1: "RGB color with ranges of 0 to 255 is not the only way you can handle color in p5.js, in fact, it allows us to think about color any way we like. For example, you might prefer to think of color as ranging from 0 to 100 (like a percentage). You can do this by specifying a custom "
        -  color-custom-ranges-p2x1: "The above function says: \"OK, we want to think about color in terms of red, green, and blue. The range of RGB values will be from 0 to 100.\""
        -  color-custom-ranges-p3x1: "Although it is rarely convenient to do so, you can also have different ranges for each color component:"
        -  color-custom-ranges-p4x1: "Now we are saying \"Red values go from 0 to 100, green from 0 to 500, blue from 0 to 10, and alpha from 0 to 255.\""
        -  color-custom-ranges-p5x1: "Finally, while you will likely only need RGB color for all of your programming needs, you can also specify colors in the HSB (hue, saturation, and brightness) mode. Without getting into too much detail, HSB color works as follows:"
        -  color-custom-ranges-li1x1: "Hue"
        -  color-custom-ranges-li1x2: "—The color type, ranges from 0 to 255 by default."
        -  color-custom-ranges-li2x1: "Saturation"
        -  color-custom-ranges-li2x2: "—The vibrancy of the color, 0 to 255 by default."
        -  color-custom-ranges-li3x1: "Brightness"
        -  color-custom-ranges-li3x2: "—The, well, brightness of the color, 0 to 255 by default."
        -  color-custom-ranges-p6x1: "With "
        -  color-custom-ranges-p6x2: " you can set your own ranges for these values. Some prefer a range of 0-360 for hue (think of 360 degrees on a color wheel) and 0-100 for saturation and brightness (think of 0-100%)."
        -  coordinate-system-description1: "This tutorial is from the book "
        +  3d-webgl: "WebGL 모드 기반의 고급 그래픽 개발하기"
        +  color-title: "색상"
        +  color: "디지털 색상 소개"
        +  coordinate-system-and-shapes-title: "좌표와 도형"
        +  coordinate-system-and-shapes: "좌표계를 활용하여 간단한 도형 그리기"
        +  interactivity-title: "인터랙션"
        +  interactivity: "마우스 및 키보드 인터랙션 소개"
        +  program-flow-title: "프로그램 흐름(flow)"
        +  program-flow: "p5.js에서 프로그램 플로우 조정하는 법 소개"
        +  curves-title: "곡선"
        +  curves: "p5.js상의 곡선 3가지 소개: 아치형 곡선, 스플라인 곡선, 베지어 곡선"
        +  becoming-a-better-programmer-title: "더 나은 프로그래머 되기"
        +  debugging-title: "디버깅"
        +  debugging: "모두를 위한 디버깅 필드 가이드"
        +  optimizing-title: "ps.js 성능 최적화"
        +  optimizing: "더 빠르고 부드러운 코딩을 위한 최적화 팁"
        +  test-driven-development-title: "유닛 테스팅 및 테스트 기반 개발"
        +  test-driven-development: "설치로 인한 고통에서 벗어나세요. 유닛 테스팅이란 무엇이고 어떻게 사용하는가? 제작: 앤디 티몬스(Andy Timmons)"
        +  contributing-to-the-community-title: "커뮤니티에 함께하기"
        +  development-title: "개발"
        +  development: "개발 기여 시작하기 및 둘러보기"
        +  looking-inside-title: "p5 들여다보기"
        +  looking-inside: "p5.js 개발용 파일 구조 및 도구에 대한 친절한 소개. 제작: 루이자 페레이라(Luisa Pereira)"
        +  writing-tutorial-title: "튜토리얼 만들기"
        +  writing-tutorial: "프로그래밍 튜토리얼 제작 가이드."
        +  writing-a-tutorial-title: "p5.js 튜토리얼 기여를 위한 가이드"
        +  writing-a-tutorial-author: "이 튜토리얼은 테가 브레인(Tega Brain)이 제작하였습니다."
        +  writing-a-tutorial-1: "p5.js 튜토리얼 기여는 이에 열정을 느끼는 교육자와 모든분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 기여 방법 등에 대한 내용을 다룹니다."
        +  writing-a-tutorial-2: "새로운 튜토리얼을 제안하거나, 튜토리얼 준비 및 기여에 대한 가이드라인 제작을 환영합니다."
        +  writing-a-tutorial-how-start-title: "커뮤니티 기여 시작하기:"
        +  writing-a-tutorial-how-start-1: "우선, 제안하려는 튜토리얼이 현재 진행 중인 내용들과 겹치는 지의 여부를 이 "
        +  writing-a-tutorial-how-start-2: "스프레드시트"
        +  writing-a-tutorial-how-start-3: "에서 확인하세요. 만약 제안하고자 하는 튜토리얼 주제가 현재 진행 중인 것이라면, 해당 주제의 마무리 또는 p5.js 웹사이트 공개 작업에 참여할 수 있고 관련해서는 아래의 이메일로 연락을 주시면 감사하겠습니다. "
        +  writing-a-tutorial-how-start-4: "제안하려는 튜토리얼이 스프레드시트 리스트에 포함되지 않는다면, 튜토리얼에 대한 간략한 설명을 education@p5js.org로 보내주세요."
        +  writing-a-tutorial-how-prepare-title: "p5.js 튜토리얼 온라인 공개 준비하기:"
        +  writing-a-tutorial-how-prepare-1: "튜토리얼을 p5.js 웹사이트상 공개할 준비가 되었다면, 다음의 단계를 따라주세요."
        +  writing-a-tutorial-how-prepare-2: "튜토리얼 콘텐츠를 이 "
        +  writing-a-tutorial-how-prepare-3: "기본 구조"
        +  writing-a-tutorial-how-prepare-4: "에 따라 tutorial-name.hbs 파일로 변환해주세요. 콘텐츠에는 아래와 같은 헤더(header)가 반드시 포함되어야 합니다:"
        +  writing-a-tutorial-how-prepare-5: "튜토리얼을 포함한 폴더는 p5js 웹사이트 상 'tutorials' 폴더에 배치됩니다. index.hbs 파일은 "
        +  writing-a-tutorial-how-prepare-6: "p5.js 튜토리얼 랜딩 페이지"
        +  writing-a-tutorial-how-prepare-7: "에 해당하며, test-tutorial.hbs 파일은 테스트 튜토리얼입니다."
        +  writing-a-tutorial-how-prepare-8: "모든 콘텐츠는 페이지상"
        +  writing-a-tutorial-how-prepare-9: "태그에 포함되어야하며, &lt;h1&gt; 와 &lt;h2&gt; 태그, 그리고 &lt;p&gt; 문단 태그로서 문서 형식이 정의되어야 합니다. 형식 예시는 다음의 페이지에서 확인해보세요:  "
        +  writing-a-tutorial-how-prepare-10: "테스트 튜토리얼"
        +  writing-a-tutorial-how-prepare-11: "튜토리얼이 이미지 파일을 포함할 경우, p5 웹사이트의 에셋(assets) 폴더에 배치됩니다. 파일 경로는 아래와 같이 src/assets/learn/test-tutorial/images에 해당합니다."
        +  writing-a-tutorial-how-prepare-12: "페이지의 HTML에 형식을 맞추기 위해 다음의 태그를 사용하세요:"
        +  writing-a-tutorial-embedding-title: "웹페이지에 p5.js 스케치 올리기(embedding)"
        +  writing-a-tutorial-embedding-1: "p5.js를 사용한다는 것은 튜토리얼 설명을 위해 예제에 각종 애니메이션, 인터랙션, 그리고 수정 기능을 포함할 수 있음을 뜻합니다. 이 경우, 튜토리얼 예제는 p5.js 스케치의 형태로 준비되어야하며, 튜토리얼 페이지상 다음의 두가지 방식으로 임베드될 수 있습니다."
        +  writing-a-tutorial-embedding-2: "만약 튜토리얼 예제가 p5.js 웹페이지의"
        +  writing-a-tutorial-embedding-3: "레퍼런스"
        +  writing-a-tutorial-embedding-4: "와 같이 코드를 수정할 수 있는 형태라면, p5js 위젯을 사용하여 HTML 페이지에 임베드할 수 있습니다."
        +  writing-a-tutorial-embedding-5: "이 가이드"
        +  writing-a-tutorial-embedding-6: "를 따라 위젯으로 p5js를 임베드하는 방법에 대해 알아보세요. 가이드는"
        +  writing-a-tutorial-embedding-7: "가 작성하였습니다. 이러한 사례에 해당하는 튜토리얼이 작동하는 모습은 "
        +  writing-a-tutorial-embedding-8: "테스트 튜토리얼 페이지"
        +  writing-a-tutorial-embedding-9: "에서 확인할 수 있습니다."
        +  writing-a-tutorial-embedding-10: "튜토리얼 예제가 애니메이션 그리고/또는 인터랙션을 포함하나 코드 수정 기능을 포함하지 않는다면, 다음과 같이 iframe을 사용하여 p5.js 스케치를 페이지상 임베드할 수 있습니다."
        +  writing-a-tutorial-iframe-title: "iframe을 사용하여 p5 스케치 임베드하기"
        +  writing-a-tutorial-iframe-1: "iframe은 한 페이지상 다른 페이지를 보기 위해 만드는 창문틀과도 같습니다. 이 창문틀을 따라 페이지상의 다른 내용들로부터 구분되는 셈이지요. 이 경우, p5.js 스케치를 포함한 index.html를 보여주는 창문틀의 역할을 합니다. "
        +  writing-a-tutorial-iframe-2: "스크린샷에 보이듯, p5 웹사이트 /src/assets/learn 폴더에 스케치의 이름을 딴 별도의 폴더를 새로이 생성하여 여러분의 튜토리얼용 p5 스케치를 올리세요. 이 경로를 통해 iframe에서 보여줄 모든 이미지와 p5 스케치가 저장됩니다."
        +  writing-a-tutorial-iframe-3: "여러분의 p5 예제를 포함한 폴더의 하위에는 sketch.js 파일과 embed.html 파일이 반드시 있어야 합니다."
        +  writing-a-tutorial-iframe-4: "embed.html 파일이 웹사이트의 p5 라이브러리와도 일치하는지를 확인하세요. 만약, 여러분의 파일 구조가 위와 같다면 p5.js 라이브러리 경로는 \"../../../js/p5.min.js\" 일것 입니다."
        +  writing-a-tutorial-iframe-5: "그리고나면, 튜토리얼 콘텐츠를 담고 있는 .hbs 파일상 p5js index 파일을 iframe의 형태로 임베드할 수 있습니다. iframe 임베드를 위한 코드는 다음과 같습니다: "
        +  writing-a-tutorial-iframe-6: "iframe 서식 바꾸기:  "
        +  writing-a-tutorial-iframe-7: "iframe을 이용한 무제 스케치 작동 확인하기: "
        +  writing-a-tutorial-iframe-8: "위의 스케치가 p5 site에 임베드된 모습:  "
        +  writing-a-tutorial-iframe-9: "한가지 주의해야할 점은, iframe의 사이즈는 반드시 직접 조정해야된다는 것입니다. 특히, 튜토리얼 콘텐츠의 크기가 규격화된 경우 그러합니다."
        +  writing-a-tutorial-iframe-10: "또한, p5.js 라이브러리 파일 연결 링크는 튜토리얼 콘텐츠가 포함되어있는 .eps 페이지가 아닌, 스케치를 렌더링하는 별도의 html 페이지에 위치합니다. (이 경우, 해당 html 페이지의 명칭은 embed.html입니다.)"
        +  writing-a-tutorial-iframe-11: "p5.js 스케치를 임베드하는 방법에 대해 더 알고 싶다면 다음의 링크를 확인하세요: "
        +  writing-a-tutorial-embed-iframe-12: "링크"
        +  writing-a-tutorial-finishing-title: "마무리하기"
        +  writing-a-tutorial-finishing-1: "앞서 언급된 메일을 통해 튜토리얼 콘텐츠 확인을 마쳤다면, p5.js-website repository를 Fork 하세요. 그리고 상기된 방법에 따라 콘텐츠를 준비하고 풀 리퀘스트(pull request)를 하여, 여러분의 기여 내용이 웹사이트에 공개될 수 있도록 하세요!"
        +  writing-a-tutorial-finishing-2: "감사합니다!"
        +  color-description1: "이 튜토리얼은 다니엘 쉬프만(Daniel Shiffman) 저, 모건 카우프만(Morgan Kaufmann) 출판 도서 Learning Processing에서 발췌하였습니다 © 2008 Elsevier Inc. 또한, 발췌본은 켈리 장(Kelly Chang)에 의해 p5로 옮겨졌습니다. 오류를 발견하거나 의견을 남기고 싶다면 "
        +  color-description2: "언제든 알려주세요."
        +  color-p1x1: "디지털 세상에서 색상에 대해 이야기할 땐, 아주 정밀한 표현이 필요합니다. 아쉽게도, \"푸른빛의 초록색 원을 만들 수 있어?\" 와 같은 표현은 통하지 않습니다. 이 곳에서 색상은 언제나 숫자와 범위값에 의해 정의됩니다. 간단한 예시로 시작해볼까요. 검정색, 하얀색, 또는 회색 음영. 0은 검정색을, 255은 하얀색을, 그리고 그 사이에 존재하는 50, 87, 162, 209와 같은 다른 숫자들은 흑과 백 사이의 회색 음영을 뜻합니다."
        +  color-p2x1: "모양을 그리기에 앞서 테두리"
        +  color-p2x2: " 와 면채우기"
        +  color-p2x3: " 함수를 사용하면 색상을 지정할 수 있습니다. 또, 배경"
        +  color-p2x4: " 함수를 통해 윈도우창의 배경색을 지정할 수 있습니다. 한 번 예시를 볼까요."
        +  color-code1: "background(255);    // 배경색을 하얀색으로 정하기 \n stroke(0);          // 테두리(stroke)색을 검정색으로 정하기 \n fill(150);          // 면(fill)색을 회색으로 정하기 \n rect(50,50,75,100); // 사각형 그리기"
        +  color-p3x1: "테두리(Stroke)나 면채우기(fill)는 다음의 함수를 통해 제거할 수 있습니다: "
        +  color-p3x2: " 과"
        +  color-p3x3: ". 본능적으로 우리는 \"stroke(0)\" 를 통해 테두리를 제거할 수 있을 거라 생각하지만, 코딩 언어의 세계에서 0은 \"아무것도 없음\"이 아니라, 검정색을 지칭합니다. "
        +  color-p3x4: " 과 "
        +  color-p3x5: "를 사용하면 선도 색상도, 아무것도 보이지 않을 거에요!"
        +  color-p4x1: "또한, 두개의 도형을 그릴 때 p5.js는 가장 마지막 줄에 지정된 stroke와 fill을 반영합니다. 코드를 위에서부터 아래로 읽고 수행하기 때문이지요."
        +  color-rgb-title: "RGB 색상"
        +  color-rgb-p1x1: "어린 시절 손가락으로 물감을 섞어본 기억이 있나요? 세가지의 \"원색\"을 사용하면, 그 어떠한 색상도 만들어 낼 수 있었지요. 여러가지 물감을 섞다보면 진흙빛의 갈색이 탄생하기도 합니다. 물감을 더할 수록 색이 어두워지고요. 디지털 색상들 역시 삼원색을 섞는 원리를 바탕으로 만들어졌지만, 물감과는 또다르게 작동합니다. 먼저, 디지털 색상에서의 삼원색은 빨강(red), 초록(green), 파랑(blue) (일명, \"RGB\" 색상)을 뜻합니다. 또, 화면상 보이는 색상은 기본적으로 물감이 아닌 빛의 조합입니다. 따라서, 색상이 조합되는 방식이 다른 것이지요."
        +  color-rgb-li1: "빨강 + 초록 = 노랑"
        +  color-rgb-li2: "빨강 + 파랑 = 보라"
        +  color-rgb-li3: "초록 + 파랑 = 청록"
        +  color-rgb-li4: "빨강 + 초록 + 파랑 = 하양"
        +  color-rgb-li5: "무채색 = 검정"
        +  color-rgb-p2x1: "이는 디지털 색상을 밝은 빛으로서 가정하는 데에서 비롯된 것인데, 색상 범위를 조정하여 원하는 색을 만들 수 있습니다. 예를 들어, 빨강색에 초록색, 파랑색을 더하면 회색이 됩니다. 그리고 약간의 빨강색에 약간의 파랑색을 더하면 어두운 보라색이 됩니다. RGB 색상을 더 많이 프로그래밍하고 실험할수록, 손가락으로 물감을 휘젔던 색상 본능만큼 디지털 색상에 따른 본능 역시 커질 것입니다. 한편, 우리는 \"빨강색 적당하게 쓰고 여기에 약간의 파란색을 섞어줘\"라는 식으로도 말할 수 없습니다. 반드시 정확한 양을 지정해야합니다. 회색 음영과 마찬가지로, 각각의 색상 요소는 0(색상 0가지)부터 255(최대한 많은 색상 수)에 이르는 범위 내에서 표현됩니다. 그리고 R, G, B의 순서에 따라 정렬됩니다. 이번엔 좀 더 일반적인 색상에 대해 알아볼까요"
        +  color-transparency-title: "색상 투명도"
        +  color-transparency-p1x1: "R, G, B값에 더해, 각 색상을 구성하는 네 번째 요소가 있습니다. 일명 \"알파(alpha)값\"인데요, 알파는 색상의 투명도를 말하고, 한 도형 위에 다른 도형을 얹을시 겹치는 지점을 보이게 할 때 유용하겠지요? 한 이미지에 대한 여러 알파값들을 통칭 \"알파 채널(alpha channel)\"이라 부르기도 합니다."
        +  color-transparency-p2x1: "픽셀은 그 자체로는 투명하지 않아요. 다만, 여러가지 색상을 섞어 마치 투명해보이는 듯한 착시현상을 만드는 것이지요. 이처럼 p5.js는 한 색상값과 다른 색상값들 간의 비율차를 이용하여 마치 이들이 섞인것처럼 보이게 만든답니다. (만약 여러분이 \"장밋빛\" 안경을 프로그래밍하고자 했다면 바로 이 지점부터 이해하고 넘어가면 되겠지요?)"
        +  color-transparency-p3x1: "알파값은 0부터 255 사이 조정가능합니다. 0은 완전히 투명한 상태(즉, 0% 투명도)이고 255는 완전히 불투명한 상태(즉, 100% 투명도)입니다."
        +  color-custom-ranges-title: "색상 조정 범위"
        +  color-custom-ranges-p1x1: " p5.js에서 다룰 수 있는 색채는 0부터 255까지에 이르는 RGB뿐만이 아닙니다. 사실 우리가 원하는대로 그 범위를 조정할 수도 있지요! 예를 들어, 색상 범위를 마치 퍼센티지처럼 0부터 100으로 설정할 수도 있습니다. 색상 범위 커스터마이징은 다음의 간단한 함수를 통해 가능합니다:"
        +  color-custom-ranges-p2x1: "위의 함수는: \"난 RGB색상에 대해 조정하고싶고, 그 색상 범위는 0부터 100으로 설정하고 싶어\"라고 말하는 것입니다."
        +  color-custom-ranges-p3x1: "조금 더 복잡하긴 하지만, 아래와 같은 방법을 통해 R, G, B 각 색상별로도 조정 범위를 설정할 수 있습니다:"
        +  color-custom-ranges-p4x1: "위의 내용은 \"빨강(R)은 0부터 100까지, 초록(G)은 0부터 500가지, 파랑(B)은 0부터 10까지, 그리고 투명도는 0부터 255까지 설정하고 싶어\"라고 말하는 것이지요."
        +  color-custom-ranges-p5x1: "여러분은 사실상 RGB값 설정만으로도 프로그래밍에 필요한 모든 색상을 누릴 수 있을텐데요, 마지막으로 RGB 외에 조정할 수 있는 색상 요소인 HSB(색조 Hue, 채도 Saturation, 밝기 Brightness)를 소개합니다"
        +  color-custom-ranges-li1x1: "색조 Hue"
        +  color-custom-ranges-li1x2: "—색상의 종류, 기본 범위 0부터 255까지"
        +  color-custom-ranges-li2x1: "채도 Saturation"
        +  color-custom-ranges-li2x2: "—색상의 생생함 정도, 기본 범위 0부터 255까지"
        +  color-custom-ranges-li3x1: "밝기 Brightness"
        +  color-custom-ranges-li3x2: "—(당연히) 색상의 밝은 정도, 기본 범위 0부터 255까지"
        +  color-custom-ranges-p6x1: "이 "
        +  color-custom-ranges-p6x2: " 함수를 이용하여 HSB값 범위 또한 설정할 수 있습니다. 어떤 사람들은 색조(Hue)를 0부터 360까지 설정하거나(위의 사진처럼 360도의 둥근 색상띠가 생각나지요), 채도와 밝기는 0부터 100까지 설정(0-100% 퍼센티지와 유비되지요)하는 것을 선호하기도 합니다."
        +  coordinate-system-description1: "이 튜토리얼은 다니엘 쉬프만(Daniel Shiffman)저, 모건 카우프만(Morgan Kaufmann) 출판 도서 "
           coordinate-system-description2: "Learning Processing"
        -  coordinate-system-description3: " by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to p5.js by Alex Yixuan Xu. If you see any errors or have comments, please "
        -  coordinate-system-description4: "let us know"
        +  coordinate-system-description3: " 에서 발췌하였습니다.by © 2008 Elsevier Inc. All rights reserved. 또한 발췌본은 알렉스 이쑤안 쑤(Alex Yixuan Xu)에 의해 p5로 옮겨졌습니다. 오류를 발견하거나 의견을 남기고 싶다면 "
        +  coordinate-system-description4: "언제든 알려주세요"
           coordinate-system-description5: "."
        -  coordinate-system-description-title: "Coordinate System and Shapes"
        -  coordinate-system-description-p1x1: "Before we begin programming with p5, we must first channel our eighth grade selves, pull out a piece of graph paper, and draw a line. The shortest distance between two points is a good old fashioned line, and this is where we begin, with two points on that graph paper."
        -  coordinate-system-description-p2x1: "The above figure shows a line between point A (1,0) and point B (4,5). If you wanted to direct a friend of yours to draw that same line, you would give them a shout and say \"draw a line from the point one-zero to the point four-five, please.\" Well, for the moment, imagine your friend was a computer and you wanted to instruct this digital pal to display that same line on its screen. The same command applies (only this time you can skip the pleasantries and you will be required to employ a precise formatting). Here, the instruction will look like this:"
        -  coordinate-system-description-p3x1: "Even without having studied the syntax of writing code, the above statement should make a fair amount of sense. We are providing a command (which we will refer to as a \"function\") for the machine to follow entitled \"line.\" In addition, we are specifying some arguments for how that line should be drawn, from point A (1,0) to point B (4,5). If you think of that line of code as a sentence, the function is a verb and the arguments are the objects of the sentence. The code sentence also ends with a semicolon instead of a period."
        -  coordinate-system-description-p4x1: "The key here is to realize that the computer screen is nothing more than a fancier piece of graph paper. Each pixel of the screen is a coordinate - two numbers, an \"x\" (horizontal) and a \"y\" (vertical) - that determines the location of a point in space. And it is our job to specify what shapes and colors should appear at these pixel coordinates."
        -  coordinate-system-description-p5x1: "Nevertheless, there is a catch here. The graph paper from eighth grade (\"Cartesian coordinate system\") placed (0,0) in the center with the y-axis pointing up and the x-axis pointing to the right (in the positive direction, negative down and to the left). The coordinate system for pixels in a computer window, however, is reversed along the y-axis. (0,0) can be found at the top left with the positive direction to the right horizontally and down vertically."
        -  coordinate-system-simple-shapes-title: "Simple Shapes"
        -  coordinate-system-simple-shapes-p1x1: "The vast majority of the programming examples you'll see with p5 are visual in nature. These examples, at their core, involve drawing shapes and setting pixels. Let's begin by looking at four primitive shapes."
        -  coordinate-system-simple-shapes-p2x1: "For each shape, we will ask ourselves what information is required to specify the location and size (and later color) of that shape and learn how p5 expects to receive that information. In each of the diagrams below, we'll assume a window with a width of 100 pixels and height of 100 pixels."
        -  coordinate-system-simple-shapes-p3x1: "A "
        -  coordinate-system-simple-shapes-p3x2: " is the easiest of the shapes and a good place to start. To draw a point, we only need an x and y coordinate."
        -  coordinate-system-simple-shapes-p4x1: "A "
        -  coordinate-system-simple-shapes-p4x2: " isn't terribly difficult either and simply requires two points: (x1,y1) and (x2,y2):"
        -  coordinate-system-simple-shapes-p5x1: "Once we arrive at drawing a "
        -  coordinate-system-simple-shapes-p5x2: ", things become a bit more complicated. In p5, a rectangle is specified by the coordinate for the top left corner of the rectangle, as well as its width and height."
        -  coordinate-system-simple-shapes-p6x1: "A second way to draw a rectangle involves specifying the centerpoint, along with width and height. If we prefer this method, we first indicate that we want to use the "
        -  coordinate-system-simple-shapes-p6x2: " mode before the instruction for the rectangle itself. Note that p5 is case-sensitive."
        -  coordinate-system-simple-shapes-p7x1: "Finally, we can also draw a rectangle with two points (the top left corner and the bottom right corner). The mode here is "
        -  coordinate-system-simple-shapes-p7x2: ". Note this example gives the same result on screen as the example above."
        -  coordinate-system-simple-shapes-p8x1: "Once we have become comfortable with the concept of drawing a rectangle, an "
        -  coordinate-system-simple-shapes-p8x2: " is a snap. In fact, it is identical to "
        -  coordinate-system-simple-shapes-p8x3: " with the difference being that an ellipse is drawn where the bounding box of the rectangle would be. The default mode for "
        -  coordinate-system-simple-shapes-p8x4: " is "
        -  coordinate-system-simple-shapes-p8x5: ", rather than "
        -  coordinate-system-simple-shapes-p8x6: "."
        -  coordinate-system-simple-shapes-p9x1: "Now let's look at what some code with shapes in more complete form, with canvas dimensions of 200 by 200. Note the use of the createCanvas() function to specify the width and height of the canvas."
        +  coordinate-system-description-title: "좌표와 도형"
        +  coordinate-system-description-p1x1: "p5로 프로그래밍을 시작하기 전에, 먼저 중학교 2학년 시절의 우리를 떠올리며 연습장에 선 하나를 그려볼까요? 두 개의 점을 그린 뒤 그 사이를 연결하면 하나의 선분이 탄생합니다. 연습장 위 이 두개의 점과 둘간을 연결하는 선. 바로 여기가 우리의 시작점입니다."
        +  coordinate-system-description-p2x1: "여기 점A(1,0)과 점B(4,5) 사이의 선 하나가 보입니다. 만약 똑같은 선을 친구가 그릴 수 있게하려면 \"1콤마 0에서 시작하는 점에서부터 4콤마 5를 향해 선을 그려죠\"라고 말하겠지요. 이제 그 친구가 컴퓨터라고 가정해볼까요? 우리의 컴퓨터 친구도 똑같은 선을 그리게 하려면 위와 동일한 문장을 입력하면 됩니다. 좀 더 구체적인 형식을 갖춰 컴퓨터 친구에게 말을 건네볼까요?"
        +  coordinate-system-description-p3x1: "코딩 문법에 대해 익숙하지 않더라도 위 문장의 뜻을 어느정도 감잡을 수 있습니다. 우리는 일명 \"함수\"라 불리는 명령문을 통해 컴퓨터와 대화하는 셈입니다. 여기서 \"line\"은 선을 그리는 함수입니다. 여기에 더해, 우리는 이 함수 내에서 구체적인 인수(argument)를 지시할 수 있습니다. 예를 들어, 점 A (1,0)부터 점 B (4,5)까지라는 인수를 함수 괄호 안에 포함 시킨 것이지요. 코드 한 줄을 하나의 문장으로 본다면, 함수는 동사(verb)이고 인수는 목적어(object)인 셈입니다. 단, 코드는 문장과 달리 마침표가 아니라 \"세미콜론(;)\"으로 끝나는 점 주의하세요!"
        +  coordinate-system-description-p4x1: "컴퓨터 화면은 그저 좀 더 멋진 모양새를 갖춘 연습장과도 같습니다. 화면상의 각 픽셀은 x값(가로)과 y값(세로)이라는 두개의 숫자가 합쳐진, 하나의 좌표값과도 같습니다. 그리고 이 좌표로 화면이라는 공간 내의 위치를 정하지요. 이제 우리는 이 픽셀 좌표값에 모양과 색상을 더하면 됩니다."
        +  coordinate-system-description-p5x1: "*** 한가지 주의사항! 우리가 중학교 2학년 때 배운 \"카테시안 좌표계\"는 (0,0)을 중심에 두고, y축을 그 중심에서 위로, 그리고 x축을 중심으로부터 오른쪽을 향해 뻗어나갑니다(양수일 경우엔 이러하고, 음수일 경우 각각 아래와 왼쪽을 향하지요.) 하지만, 컴퓨터 화면 속 픽셀 좌표계에서의 y축은 그 반대로 적용됩니다. 픽셀 좌표계의 (0,0)은 화면상 좌측 최상단에 위치하고, y값이 증가할 수록 아래를 향해 내려옵니다. x값은 그대로 오른쪽을 향해 증가합니다."
        +  coordinate-system-simple-shapes-title: "간단한 도형"
        +  coordinate-system-simple-shapes-p1x1: "여러분이 앞으로 마주할 p5 기반 프로그래밍 예제들은 본질적으로 시각적이고 조형적입니다. 다음 예제들의 핵심은 모양을 그리고 픽셀을 설정하는 데에 있습니다. 4개의 기본 도형을 살펴보며 시작해볼까요!"
        +  coordinate-system-simple-shapes-p2x1: "위의 모양들을 그리기 위해 필요한 위치와 크기(그 다음, 색상까지도) 정보가 무엇일지 고민해볼까요. 아래의 도식들을 보면, 우리는 먼저 너비 100 픽셀 그리고 높이 100 픽셀에 해당하는 창을 만듭니다."
        +  coordinate-system-simple-shapes-p3x1: "점그리기를 뜻하는 "
        +  coordinate-system-simple-shapes-p3x2: " 함수는 우리가 그릴 수 있는 가장 쉬운 모양이자, 좋은 시작점이 됩니다. 점을 그리기 위해 우리는 x와 y 좌표값만 정하면 되지요."
        +  coordinate-system-simple-shapes-p4x1: "선그리기를 뜻하는 "
        +  coordinate-system-simple-shapes-p4x2: " 함수 역시 아주 어렵진 않습니다. 선을 그리기 위해 우리는 (x1,y1)과 (x2,y2)라는 두개의 좌표값만 필요합니다:"
        +  coordinate-system-simple-shapes-p5x1: "사각형 그리기 함수인 "
        +  coordinate-system-simple-shapes-p5x2: "의 경우 조금 복잡해집니다. p5에서 사각형은 그것이 그려지기 시작하는 상단 좌측의 좌표값과 더불어 너비(width)와 높이(height)를 정하는 숫자들이 필요합니다."
        +  coordinate-system-simple-shapes-p6x1: "사각형을 그리는 또 다른 방법으로, 중앙값, 너비(width), 높이값(height) 설정하기가 있습니다. 이 경우, 먼저 상단의 setup() 함수에 센터 "
        +  coordinate-system-simple-shapes-p6x2: " 모드를 불러오고, 그 뒤에 사각형의 중앙값, 너비, 높이값을 지정해야 합니다. p5는 대문자와 소문자 구분에 민감하니 주의하세요!"
        +  coordinate-system-simple-shapes-p7x1: "마지막으로, 점 두 개 만으로 사각형을 그리는 방법도 있습니다. 바로, 상단 좌측 코너와 하단 우측 코너의 좌표를 지정하는 것이지요. 여기서 우리가 setup() 함수에 포함시킬 모드는 코너 "
        +  coordinate-system-simple-shapes-p7x2: " 입니다. 그 결과물은 위의 예제와 동일합니다."
        +  coordinate-system-simple-shapes-p8x1: "사각형 그리기에 익숙해졌다면, 타원그리기 "
        +  coordinate-system-simple-shapes-p8x2: " 는 식은죽 먹기지요. 타원을 그리는 원리는 "
        +  coordinate-system-simple-shapes-p8x3: " 와 거의 동일하나, 다만 동일한 좌표값을 가진 사각형의 경계선 안쪽에 그려진다는 점에서 차이가 있습니다. "
        +  coordinate-system-simple-shapes-p8x4: " 함수의 기본 모드 설정은 센터 "
        +  coordinate-system-simple-shapes-p8x5: "에 해당합니다. 코너 "
        +  coordinate-system-simple-shapes-p8x6: " 모드로 그리기 위해선 별도 설정이 필요합니다."
        +  coordinate-system-simple-shapes-p9x1: "자, 이제 좀 더 완성도있는 그림을 그려볼까요! 아래의 코드는 200x200 픽셀 크기의 캔버스 위에 여러개의 도형을 그립니다. createCanvas() 함수를 사용하여 캔버스의 너비(width)와 높이(height)를 설정할 수 있습니다."
         
         test-tutorial:
         
         libraries:
        -  Libraries: "Libraries"
        -  core-libraries: "Core Libraries"
        -  community-libraries: "Community Libraries"
        -  libraries-created-by: "Created by:"
        -  p5.sound: "p5.sound extends p5 with Web Audio functionality including audio input, playback, analysis and synthesis."
        -  p5.accessibility: "p5.accessibility makes the p5 canvas more accessible to people who are blind and visually impaired."
        -  asciiart: "p5.asciiart is a simple and easy to use image - to - ASCII art converter for p5js."
        -  p5.ble: "A Javascript library that enables communication between BLE devices and p5 sketches."
        -  blizard.js: "a library for making DOM manipulation simple"
        -  p5.bots: "With p5.bots you can interact with your Arduino (or other microprocessor) from within the browser. Use sensor data to drive a sketch; use a sketch to drive LEDs, motors, and more! Created by "
        -  p5.clickable: "Event driven, easy-to-use button library for p5.js."
        +  Libraries: "라이브러리"
        +  core-libraries: "주요 라이브러리"
        +  community-libraries: "커뮤니티 라이브러리"
        +  libraries-created-by: "제작: "
        +  p5.sound: "p5.sound는 p5에 웹 오디오 기능(오디오 입력, 재생, 분석 합성 등)을 더해줍니다. "
        +  p5.accessibility: "p5.accessibility는 p5 캔버스에 대한 맹인 또는 시각 장애인의 접근성을 높여줍니다. "
        +  asciiart: "p5.asciiart는 p5js를 아스키(ASCII) 아트로 쉽고 간단하게 변환해줍니다. 즉, p5js를 위한 아스키 아트 컨버터입니다. "
        +  p5.ble: "p5.ble은 BLE 기기와 p5 스케치를 연결해주는 자바스크립트 라이브러리입니다. "
        +  blizard.js: "blizard.js는 DOM 조작을 간단하게 처리해주는 라이브러리입니다. "
        +  p5.bots: "p5.bots를 통해 브라우저와 아두이노(Arduino) 및 여타 마이크로프로세서 간의 인터랙션을 만들 수 있습니다. 센서 데이터로 스케치를 만들거나, 스케치로 LED, 모터, 그 외의 것을 작동시켜 보세요! "
        +  p5.clickable: "이벤트 기반의, 사용이 편리한 p5.js 버튼 라이브러리입니다. "
           p5.cmyk.js: "CMYK ColorSpace"
        -  p5.collide2D: "p5.collide2D provides tools for calculating collision detection for 2D geometry with p5.js."
        -  p5.createloop: "Create animation loops with noise and GIF exports in one line of code."
        -  p5.dimensions: "p5.dimensions extends p5.js' vector functions to work in any number of dimensions."
        -  p5.EasyCam: "Simple 3D camera control with inertial pan, zoom, and rotate. Major contributions by Thomas Diewald."
        -  p5.experience: "Extensive library for p5.js that adds additional event-listening functionality for creating canvas-based web applications."
        -  p5.func: "p5.func is a p5 extension that provides new objects and utilities for function generation in the time, frequency, and spatial domains."
        -  p5.geolocation: "p5.geolocation provides techniques for acquiring, watching, calculating, and geofencing user locations for p5.js."
        -  p5.gibber: "p5.gibber provides rapid music sequencing and audio synthesis capabilities."
        -  grafica.js: "grafica.js lets you add simple but highly configurable 2D plots to your p5.js sketches."
        -  p5.gui: "p5.gui generates a graphical user interface for your p5.js sketches."
        -  p5.localmessage: "p5.localmessage provides a simple interface to send messages locally from one sketch to another for easy multi-window sketching!"
        -  marching: "Raster to vector conversion, isosurfaces."
        -  mappa: "Mappa provides a set of tools for working with static maps, tile maps, and geo-data. Useful when building geolocation-based visual representations."
        -  ml5.js: "ml5.js builds on Tensorflow.js and provides friendly access to machine learning algorithms and models in the browser."
        -  p5.play: "p5.play provides sprites, animations, input and collision functions for games and gamelike applications."
        -  p5.particle: "The Particle and Fountain objects can be used to create data-driven effects that are defined through user structures or JSON input and user-draw functions."
        -  p5.Riso: "p5.Riso is a library for generating files suitable for Risograph printing. It helps turn your sketches into multi-color prints."
        -  rita.js: "RiTa.js provides a set of natural language processing objects for generative literature."
        -  RotatingKnobs: "Make knobs you can rotate with custom graphics and return value ranges"
        -  p5.scenemanager: "p5.SceneManager helps you create sketches with multiple states / scenes. Each scene is a like a sketch within the main sketch."
        -  p5.screenPosition: "Adds the screenX and screenY functionality from Processing to P5js."
        -  p5.scribble: "Draw 2D primitives in a sketchy look. Created by Janneck Wullschleger, based on a port of the original Processing library "
        -  p5.serial: "p5.serial enables serial communication between devices that support serial (RS-232) and p5 sketches running in the browser."
        -  Shape5: "Shape5 is a 2D primative library for elementary students who are learning to code for the first time."
        -  p5.shape.js: "A library built to add more simple shapes to the p5.js framework."
        -  p5.speech: "p5.speech provides simple, clear access to the Web Speech and Speech Recognition APIs, allowing for the easy creation of sketches that can talk and listen."
        -  p5.start2d.js: "p5 extension for 2D static art using px, mm, cm or inches"
        -  p5.tiledmap: "p5.tiledmap provides drawing and helper functions to include maps in your sketches."
        -  p5.touchgui: "A multi-touch and mouse GUI Library for p5.js."
        -  tramontana: "Tramontana is a platform for easily use many devices (iOS, Android, tramontana Board, ...) to create interactive environments, interactive spaces or just prototype experiences at scale and in space."
        -  vida: "Vida is a simple library that adds camera (or video) based motion detection and blob tracking functionality to p5js."
        -  p5.voronoi: "p5.voronoi provides a set of tools to draw and utilize voronoi diagrams in your p5.js sketches."
        -  p5.3D: "3D Text and Images in WebGL."
        -  using-a-library-title: "Using a library"
        -  using-a-library1: "A p5.js library can be any JavaScript code that extends or adds to the p5.js core functionality. There are two categories of libraries. Core libraries ("
        -  using-a-library3: ") are part of the p5.js distribution, while contributed libraries are developed, owned, and maintained by members of the p5.js community."
        -  using-a-library4: "To include a library in your sketch, link it into your HTML file, after you have linked in p5.js. An example HTML file might look like this:"
        -  create-your-own-title: "Create Your Own"
        -  create-your-own1: "p5.js welcomes libraries contributed by others! Check out the"
        -  create-your-own2: "libraries tutorial"
        -  create-your-own3: "for more specifics about how to create one."
        -  create-your-own4: "If you have created a library and would like to have it included on this page, submit this form!"
        +  p5.collide2D: "p5.collide2D는 p5.js로 제작된 2D 기하 간의 충돌 감지 계산 툴을 제공합니다. "
        +  p5.createloop: "단 한 줄의 코드로 노이즈와 GIF로 이루어진 애니메이션 루프를 만들어보세요. "
        +  p5.dimensions: "p5.dimensions은 p5.js의 벡터 기능을 확장하여 n차원에서 작동하도록 합니다. "
        +  p5.EasyCam: "패닝, 줌, 회전이 가능한 간단한 3D 카메라 컨트롤. Thomas Diewald가 핵심적으로 기여하였습니다. "
        +  p5.experience: "확장형 p5.js 라이브러리로, 캔버스 기반 웹 어플리케이션 제작을 위한 이벤트리스닝 기능을 추가할 수 있습니다. "
        +  p5.func: "p5.func은 시간(time), 빈도(frequency), 그리고 공간 영역에서의 기능 생성을 위한 새로운 오브젝트와 유틸리티를 제공합니다. "
        +  p5.geolocation: "p5.geolocation은 사용자 위치를 획득, 관찰, 계산, 지오펜싱(geo-fencing)하기 위한 기술을 제공합니다. "
        +  p5.gibber: "p5.gibber는 빠른 속도의 음악 시퀀싱 및 오디오 합성 기능을 제공합니다. "
        +  grafica.js: "grafica.js는 p5.js 스케치상 변형이 쉬운 2D 플롯을 더합니다. "
        +  p5.gui: "p5.gui는 p5.js 스케치를 위한 그래픽 유저 인터페이스를 생성합니다. "
        +  p5.localmessage: "p5.localmessage는 멀티윈도우 스케칭을 위한 스케치 간 로컬 메시지 전송 기능 및 인터페이스를 제공합니다. "
        +  marching: "래스터(raster)에서 벡터(vector)로의 변환, 등면."
        +  mappa: "Mappa는 정적 맵, 타일 맵, 지오 데이터 활용을 위한 툴을 제공합니다. 지리정보 기반의 시각적 재현물을 제작할 때 용이합니다. "
        +  ml5.js: "ml5.js는 Tensorflow.js를 기반으로하며, 머신러닝 알고리즘 및 모델에 대한 브라우저상의 접근성을 높입니다. "
        +  p5.play: "p5.play는 게임과 같은 어플리케이션 제작을 위한 스프라이트(sprite), 애니메이션, 인풋, 충돌 기능을 제공합니다. "
        +  p5.particle: "파티클은 사용자가 제작한 구조 및 기능 또는 JSON 인풋으로 정의된 데이터를 기반으로 한 효과를 만드는 데에 사용됩니다. "
        +  p5.Riso: "p5.Riso는 석판화와 같은 파일을 생성하는 라이브러리입니다. 스케치를 다양한 색상의 판화처럼 만들어줍니다. "
        +  rita.js: "RiTa.js는 제너레이티브 문학을 위한 자연어 처리 오브젝트를 제공합니다. "
        +  RotatingKnobs: "Knob을 만들어 커스텀 그래픽을 회전할 수 있으며, 또 그 범위값을 반환합니다. "
        +  p5.scenemanager: "p5.SceneManager는 스케치를 여러 단계의 씬(scene)들로 구성할 수 있도록 합니다. 각각의 씬은 메인 스케치에 포함된 일부 스케치와도 같습니다. "
        +  p5.screenPosition: "프로세싱의 screenX 및 screenY 기능을 p5js에 적용합니다."
        +  p5.scribble: "2D 기본 조형을 손그림으로 표현합니다. 제작: Janneck Wullschleger, 프로세싱 라이브러리 포트 기반 "
        +  p5.serial: "p5.serial는 시리얼 (RS-232)와 p5 웹 에디터를 지원하는 기기상에서의 직렬 통신을 구현합니다. "
        +  Shape5: "Shape5는 코딩을 처음 배우는 초등학생을 위한 2D 기본 조형 라이브러리입니다."
        +  p5.shape.js: "p5.js 프레임워크에 더 많은 기본 도형을 추가하고자 제작된 라이브러리입니다."
        +  p5.speech: "p5.speech는 웹 스피치 및 스피치 인식 API에 대한 접근 권한을 제공하여, 음성을 인식하고 출력할 수 있는 스케치를 쉽게 만들 수 있게 합니다. "
        +  p5.start2d.js: "픽셀(px), 밀리미터(mm), 센티미터(cm) 또는 인치(inches) 단위를 활용하여 정적 2D 아트를 만들기 위한 p5 확장 라이브러리입니다. "
        +  p5.tiledmap: "p5.tiledmap은 스케치에 지도를 포함하기 위한 드로잉 및 도움 기능을 제공합니다. "
        +  p5.touchgui: "p5.js를 위한 멀티터치 및 마우스 그래픽 유저 인터페이스(GUI) 라이브러리 "
        +  tramontana: "Tramontana는 인터랙티브 환경 및 공간을 창작하거나, 또는 공간에서의 스케일 기능을 프로토타이핑하는 데에 있어 여러가지 기기(iOS, Android, tramontana Board, ...)를 쉽게 쓸 수 있도록 하는 플랫폼입니다. "
        +  vida: "Vida는 카메라(또는 비디오) 기반의 모션 감지 및 얼룩(blob) 트래킹 기능을 더하는 p5js 라이브러리입니다. "
        +  p5.voronoi: "p5.voronoi는 p5.js 스케치상 보로노이 다이어그램을 그리고 활용할 수 있는 툴을 제공합니다. "
        +  p5.3D: "WebGL로 3D 텍스트 및 이미지를 쓸 수 있습니다. "
        +  using-a-library-title: "라이브러리 이용하기"
        +  using-a-library1: "라이브러리란 p5.js의 핵심 기능을 확장하거나 추가하는 자바스크립트 코드를 말합니다. 라이브러리에는 크게 두 종류가 있습니다. 주요 라이브러리인 "
        +  using-a-library3: "의 경우 p5.js 자체 배포물인 반면, 커뮤니티 라이브러리는 커뮤니티 기여자에 의해 개발, 소유, 유지됩니다."
        +  using-a-library4: "스케치에 라이브러리를 사용하려면 우선 스케치에 p5.js 링크를 걸고, 그 다음 HTML 파일에 라이브러리 링크를 걸면 됩니다. 링크가 걸린 HTML 파일은 이렇게 보입니다:"
        +  create-your-own-title: "나만의 라이브러리 만들기"
        +  create-your-own1: "p5.js는 여러분만의 라이브러리 제작을 환영합니다! 라이브러리 제작에 대해 더 알고 싶다면 "
        +  create-your-own2: "라이브러리 튜토리얼"
        +  create-your-own3: "을 확인해보세요. 제작한 라이브러리를 이 페이지에 추가하고 싶다면 "
        +  create-your-own4: "이 문서를 제출하세요!"
         
         community:
        -  community-title: "Community"
        -  community-statement-title: "p5.js Community Statement"
        -  community-statement1: "p5.js is a community interested in exploring the creation of art and design with technology."
        -  community-statement2: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
        -  community-statement3: "We like these hashtags: #noCodeSnobs (because we value community over efficiency), #newKidLove (because we all started somewhere), #unassumeCore (because we don't assume knowledge), and #BlackLivesMatter (because of course)."
        -  in-practice-title: "In practice:"
        -  in-practice1: " We are not code snobs. We do not assume knowledge or imply there are things that somebody should know. "
        -  in-practice2: "We insist on actively engaging with requests for feedback regardless of their complexity."
        -  in-practice3: "We welcome newcomers and prioritize the education of others. We strive to approach all tasks with the enthusiasm of a newcomer. Because we believe that newcomers are just as valuable in this effort as experts."
        -  in-practice4: "We consistently make the effort to actively recognize and validate multiple types of contributions."
        -  in-practice5: "We are always willing to offer help or guidance."
        -  in-times-conflict-title: "In times of conflict:"
        -  in-times-conflict1: "We listen."
        -  in-times-conflict2: "We clearly communicate while acknowledging other's feelings."
        -  in-times-conflict3: "We admit when we're wrong, apologize, and accept responsibility for our actions."
        -  in-times-conflict4: "We are continuously seeking to improve ourselves and our community."
        -  in-times-conflict5: "We keep our community respectful and open."
        -  in-times-conflict6: "We make everyone feel heard."
        -  in-times-conflict7: "We are mindful and kind in our interactions."
        -  in-the-future-title: "In the future:"
        -  in-the-future1: "The future is now."
        -  sharing-title: "Sharing"
        -  sharing1: "This statement is licensed under a "
        +  community-title: "커뮤니티"
        +  community-statement-title: "p5.js 커뮤니티 성명서"
        +  community-statement1: "p5.js는 기술을 재료삼아 예술과 디자인을 창작하는 커뮤니티입니다."
        +  community-statement2: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        +  community-statement3: "우리가 좋아하는 해시태그는 #noCodeSnobs(우리는 효율성보다 커뮤니티를 우선시합니다), #newKidLove(우리는 모두 한 때 초심자였으니깐요!), #unassumeCore(우리는 상대가 무엇을 알고 있는지에 대해 섣불리 가정하지 않습니다), and #BlackLivesMatter (말할 필요도 없이 중요한 사실이지요!) 입니다."
        +  in-practice-title: "실천:"
        +  in-practice1: "우리는 잘난체하는 개발자들이 아닙니다. 우리는 상대가 이미 어떠한 것을 알고 있을거라 섣불리 가정하거나, 모든 사람이 반드시 알아야 할 지식이 있다고 생각하지 않습니다. "
        +  in-practice2: "피드백이 필요한 경우, 언제든 적극적으로 응합니다."
        +  in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 초심자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
        +  in-practice4: "우리는 언제나 모든 형태의 기여와 참여를 적극적으로 인정하고 인증하고자 합니다."
        +  in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다."
        +  in-times-conflict-title: "갈등 발생시:"
        +  in-times-conflict1: "서로의 생각에 귀 기울입니다. "
        +  in-times-conflict2: "명확한 의사소통을 하되, 타인의 감정을 생각합니다."
        +  in-times-conflict3: "우리가 잘못한 경우에는 그 잘못을 인정하고, 용서를 구하며, 행동에 대한 책임을 집니다. "
        +  in-times-conflict4: "더 나은 우리 자신과 커뮤니티를 향해 지속적으로 노력합니다. "
        +  in-times-conflict5: "서로 존중하며 개방된 자세를 유지합니다. "
        +  in-times-conflict6: "모든 사람의 의견을 존중하고 경청합니다. "
        +  in-times-conflict7: "사려깊고 친절한 태도로 소통합니다. "
        +  in-the-future-title: "미래에 우리는: "
        +  in-the-future1: "지금이 바로 미래입니다."
        +  sharing-title: "공유하기"
        +  sharing1: "이 성명서는 "
           sharing2: "Creative Commons license"
        -  sharing3: ". Please feel free to share and remix with attribution."
        +  sharing3: "에 의해 라이선스를 부여받습니다. 출처와 함께 자유롭게 공유하고 응용하셔도 좋습니다."
         
        -  contribute-title: "Contribute"
        -  contribute1: "Our community is always looking for enthusiasts to help in all different ways."
        -  develop-title: "Develop."
        +  contribute-title: "함께하기"
        +  contribute1: "우리 커뮤니티는 다양한 방법으로 도움을 줄 수 있는 열정가 분들을 항시 찾고 있습니다. "
        +  develop-title: "개발: "
           develop1: "GitHub"
        -  develop2: " is the main place where code is collected, issues are documented, and discussions about code are had. Check out the "
        -  develop3: " development tutorial"
        -  develop4: " to get started, or "
        -  develop5: "create your own library."
        -  document-title: "Document."
        -  document1: " Everyone loves documentation. Help is needed "
        -  document2: "porting examples"
        -  document3: ", and"
        -  document4: " adding documentation"
        -  document5: ", and creating tutorials."
        -  teach-title: "Teach."
        -  teach1: " Teach a workshop, a class, a friend, a collaborator! Tag @p5xjs on Twitter and we will do our best to share what you're doing."
        -  create-title: "Create."
        -  create1: " p5.js is looking for designers, artists, coders, programmers to bring your creative and amazing work to show on the front page and inspire other people. Submit your work to "
        +  develop2: "는 코드, 버그와 에러, 개발 이슈 등이 문서화되며, 관련 논의가 진행되는 곳입니다. p5.js 개발에 기여하려면"
        +  develop3: " 개발 튜토리얼"
        +  develop4: "을 참고하거나, "
        +  develop5: "라이브러리를 제작해보세요."
        +  document-title: "문서화: "
        +  document1: "문서화 작업은 너무나도 소중하지요! 현재 도움이 필요한 부분으로는 "
        +  document2: "예제 이전하기"
        +  document3: ","
        +  document4: " 문서 추가하기"
        +  document5: ", 그리고 튜토리얼 제작이 있습니다."
        +  teach-title: "가르치기: "
        +  teach1: " 워크샵이나 수업을 통해 친구, 협업자에게 p5.js를 가르치는 것도 좋은 기여 방법입니다. 트위터에서 @p5xjs를 태그해주시면 여러분의 프로젝트를 공유할게요."
        +  create-title: "창작하기: "
        +  create1: " p5.js는 사용자들에게 영감을 줄 수 있는 프로젝트를 웹사이트 첫 페이지에 게재합니다. 디자이너, 예술가, 개발자, 프로그래머, 그 누구의 작업도 좋습니다! 여러분이 만든 창의적인 프로젝트를 다음의 메일 주소로 제출해보세요: "
           create2: "hello@p5js.org"
           create3: "."
        -  donate-title: "Donate."
        -  donate1: " p5.js is free and open source and made by artists. Help support the development of p5.js through a donation to the "
        -  donate2: "Processing Foundation"
        -  donate3: "."
        -  contributors-conference-title: "p5.js Contributors Conference"
        -  contributors-conference1: "While most work happens online, we also convene IRL. We've had two contributors conferences held at the "
        -  contributors-conference2: "at Carnegie Mellon University in Pittsburgh, PA. Artists, designers, developers, educators, and got together to advance the p5.js project."
        -  participants-title: "Participants"
        -  support-title: "Support"
        -  support1: "Our contributor conference took place at the"
        -  support2: "at Carnegie Mellon University, an academic laboratory for atypical, anti-disciplinary, and inter-institutional research at the intersections of arts, science, technology, and culture."
        -  support3: "This event was made possible by a grant from the"
        -  support4: "and generous support from the"
        -  support5: "and"
        -  support6: "Thank you!"
        -  mailing-list-title: "Mailing list"
        -  mailing-list-1: "Enter your email address to receive occasional updates from the Processing Foundation."
        +  donate-title: "기부하기: "
        +  donate1: " p5.js는 예술가들이 만든 무료 오픈 소스입니다. "
        +  donate2: "프로세싱 재단"
        +  donate3: " 기부를 통해 p5.js를 후원해주세요!"
        +  contributors-conference-title: "p5.js 기여자 컨퍼런스"
        +  contributors-conference1: "대부분의 커뮤니티 활동은 온라인에서 진행되지만, 오프라인에서도 일어난답니다! 그동안 두 차례의 기여자 컨퍼런스가 있었는데요, 미국 피츠버그(Pittsburgh) 소재 카네기 멜론 대학교(Carnegie Mellon University)의 "
        +  contributors-conference2: "에서 진행된 것이 그 중 하나입니다. 예술가, 디자이너, 개발자, 교육자들이 모여 p5.js의 개선 방향에 대해 논의하였습니다."
        +  participants-title: "참여자"
        +  support-title: "지원"
        +  support1: "기여자 컨퍼러스는 카네기 멜론 대학교의"
        +  support2: "에서 열렸습니다. 이 곳은 예술, 과학, 기술, 그리고 문화의 교차점에서, 비정형적, 반-학제적 및 간-기관적 연구를 진행하는 학술랩입니다."
        +  support3: "이 행사는 "
        +  support4: "의 기금과 "
        +  support5: "과"
        +  support6: "의 지원 덕분에 가능했습니다. 감사합니다!"
        +  mailing-list-title: "소식지 받기"
        +  mailing-list-1: "프로세싱 재단의 정기 소식을 수신하려면 이메일 주소를 입력하세요."
         
        -  2015contributors-conference-title: "Contributors Conference 2015"
        -  2015contributors-conference-date: "May 25-31"
        -  2015contributors-conference1: "A group of approximately 30 participants gathered spent a week at the "
        -  2015contributors-conference2: ", advancing the code, documentation, and community outreach tools of the p5.js programming environment. Participants came from as far away as Hong Kong, Seattle, Los Angeles, Boston and New York. Most were working professionals in the fields of creative technology, interaction design, and new-media arts, but the group also included a half-dozen undergraduate and graduate students from Carnegie Mellon’s Schools of Art and Architecture."
        -  2015contributors-conference3: "Photos by Taeyoon Choi"
        -  2015contributors-conference-diversity-title: "Diversity"
        -  2015contributors-conference-diversity1: "Alongside technical development, one of the main focuses of this conference was outreach, community, and diversity. The conference began with a panel"
        -  2015contributors-conference-diversity2: "Diversity: Seven Voices on Race, Gender, Ability &amp; Class for FLOSS and the Internet"
        -  2015contributors-conference-diversity3: ". "
        -  2015contributors-conference-diversity4: "Organized by"
        -  2015contributors-conference-diversity5: "and"
        -  2015contributors-conference-diversity6: ", "
        -  2015contributors-conference-diversity7: "the panel took place Tuesday, 25 May 2015 in Kresge Auditorium at Carnegie Mellon University. Speakers included"
        -  2015contributors-conference-diversity8: "and"
        -  2015contributors-conference-diversity9: "."
        -  2015cc_1: "Diverse group of participants smile and make a p5 sign with their hands"
        -  2015cc_2: "Participants jump, smile and throw their hands in the air on a green lawn"
        -  2015cc_3: "Woman presenting the p5.js community statement from her laptop"
        -  2015cc_4: "Woman expressively speaks into a microphone while two male collaborators look on"
        -  2015cc_5: "Participants attentively smile and listen to a presentation"
        -  2015cc_6: "Woman reads about p5.js into a microphone to three female students"
        -  2015cc_7: "Participants sit in a circle around a white board with sticky notes on it while a female student speaks into a microphone"
        -  2015cc_8: "Participants sit around a table looking at each others laptops and compare code "
        -  2015cc_9: "Whiteboard with different colored sticky and written notes about programming "
        -  2015cc_10: "Woman speaking into a microphone about valuing different skill sets while a group of participants with laptops look at her powerpoint in a classroom"
        -  2015cc_11: "Woman speaks at a podium in an auditorium while three participants sit on the stage and another three are skyping in on the stage screen"
        -  2015cc_12: "Overhead view of a classroom with participants working on their laptops"
        -  2015cc_13: "Five people having a discussion in a circle"
        -  2015cc_14: "Five people in a circle with their laptops sharing their notes"
        -  2015cc_15: "Man in a classroom with a microphone speaking out to a group of participants"
        -  2019contributors-conference-title: "Contributors Conference 2019"
        -  2019contributors-conference-date: "August 13-18"
        -  2019contributors-conference1: "An interdisciplinary group of 35 participants gathered at the "
        -  2019contributors-conference2: ", advancing the code, documentation, and community outreach tools and exploring the current landscape of the p5.js programming environment. Comprising a diverse range of participants within the fields of creative technology, interaction design, and new media arts, the conference was aimed at fostering dialogue through a multidisciplinary lens. Working groups focused on several topic areas: Access; Music and Code in Performance; Landscape of Creative Tech; and Internationalization."
        -  2019contributors-conference3: "Videos by Qianqian Ye"
        -  2019contributors-conference4: "Photos by Jacquelyn Johnson"
        -  outputs: "Outputs"
        -  output1: ". An implementation of highly flexible triangle, square, hexagon, and octagon girds for p5.js. Created by Aren Davey."
        -  output2: ". A set of template files for building a multi-device, multiplayer game where multiple clients can connect to a specified host page. Created by L05."
        -  output3: "Experiments using"
        -  output3-1: ", testing early implementations of softCompile, OSC interfacing and added connectivity with demo for MIDI setup. A p5.js collaborative live-coding vj environment! Created by Ted Davis."
        -  output4: "A panel on Blackness and Gender in Virtual Space led by American Artist, with shawné michaelain holloway and LaJuné McMillian."
        -  output5: "Workshops led by Everest Pipkin and Jon Chambers."
        -  output6: "A prototype of a "
        -  output6-1: "notebook interface for p5.js."
        -  output6-2: "Created by Allison Parrish."
        -  output7: "New art installations by Stalgia Grigg, LaJuné McMillian, Aatish Bhatia, and Jon Chambers."
        -  output8: "p5.js Global Contributor's Toolkit."
        -  output8-1: "Created by Aarón Montoya-Moraga, Kenneth Lim, Guillermo Montecinos, Qianqian Ye,  Dorothy R. Santos, and Yasheng She."
        -  output9: "How to write non-violent creative code."
        -  output9-1: " A zine led by Olivia Ross."
        -  output10: "An overhaul of the p5.js website for accessibility. Including updates for screen reader accessibility, and improvements to the home, download, getting started, and reference pages. With contributions from Claire Kearney-Volpe, Sina Bahram, Kate Hollenbach, Olivia Ross, Luis Morales-Navarro, Lauren McCarthy, and Evelyn Masso."
        -  output11: "Collaborative performances by Luisa Pereira, Jun Shern Chan, Shefali Nayak, Sona Lee, Ted Davis, and Carlos Garcia."
        -  output12: "A performance by Natalie Braginsky."
        -  output13: "A design of the p5.js library system for the p5 Editor. Created by Cassie Tarakajian and Luca Damasco."
        -  output14: "Prototypes connecting p5 to other libraries. Created by Alex Yixuan Xu and Lauren Valley."
        -  output15: "A closing campfire circle led by Golan Levin."
        -  2019cc_1: "Man at a podium giving a presentation to the group"
        -  2019cc_2: "Participants sitting at a long table having lunch and a discussion"
        -  2019cc_3: "Participants in a classroom, some working on their laptops, others talking "
        -  2019cc_4: "Classroom of participants working on their laptops"
        -  2019cc_5: "Participants in a meeting in a dark classroom"
        -  2019cc_6: "Woman giving presentation in a classroom of diverse participants"
        -  2019cc_7: "Participants conversing in a busy classroom"
        -  2019cc_8: "Woman with microphone speaking to fellow participants in a classroom"
        -  2019cc_9: "Participant speaks at a podium in front of projected text about the problem with anonymyzing data"
        -  2019cc_10: "Person with a microphone speaking to fellow participants in front of text that reads p5.js will not add any new features except those that increase access"
        -  2019cc_11: "Woman speaking into a microphone talking to fellow participants "
        -  2019cc_12: "A man with a microphone speaking to fellow participants"
        -  2019cc_13: "Participants sit in a classroom towards the speakers listening intently"
        -  2019cc_14: "Classroom of participants facing a speaker listen intently "
        -  2019cc_15: "Woman with microphone speaking to fellow participants with the text sacred boundaries in the projection behind her"
        -  2019cc_16: "Overhead view of participants listening to a panel of people with an image of a 3d rendered man on it "
        -  2019cc_17: "Participants sit around a table with their laptops and observe code on a screen"
        -  2019cc_18: "Woman sitting next to a lifesize teddy bear works on her laptop"
        -  2019cc_19: "Participants standing outside smiling"
        -  2019cc_20: "Four participants standing in a circle conversing"
        -  2019cc_21: "Participants sitting outside eating lunch together"
        -  2019cc_22: "Participants sitting around a large U shaped table looking towards the front of the classroom"
        -  2019cc_23: "Man sitting in front of the classroom speaking energetically into a microphone"
        -  2019cc_24: "Group photo of participants smiling enthusiastically with their hands in the air"
        -  2019cc_25: "Group of people sit around campfire made from four LCD monitors."
        +  2015contributors-conference-title: "2015년 기여자 컨퍼런스"
        +  2015contributors-conference-date: "5월 25-31일"
        +  2015contributors-conference1: "약 30여명의 참여자들이 "
        +  2015contributors-conference2: "에 모여, p5.js의 프로그래밍 코드와 문서화 작업을 진전시키고, 커뮤니티를 확장하는 방안에 대해 논의하였습니다. 멀리서는 홍콩, 그리고 시애틀, 로스 엔젤레스, 보스턴, 뉴욕 등지에서 찾아온 참여자들이 함께하였습니다. 대부분의 참여자들이 크리에이티브 기술, 인터랙션 디자인, 그리고 뉴미디어 아트 분야의 전문 종사자였고, 카네기 멜론 미술 및 건축 대학교 출신의 학부생 및 대학원생도 6명 정도 포함하였습니다."
        +  2015contributors-conference3: "사진 촬영: 최태윤(Taeyoon Choi)"
        +  2015contributors-conference-diversity-title: "다양성"
        +  2015contributors-conference-diversity1: "기술 개발 문제 외에도 중요하게 다루어졌던 컨퍼런스 주제는 커뮤니티, 확장, 다양성이었습니다. 컨퍼런스는 패널"
        +  2015contributors-conference-diversity2: "다양성: 인종, 젠더, 능력에 대한 7가지의 목소리 &amp; FLOSS와 인터넷을 위한 수업"
        +  2015contributors-conference-diversity3: "과 함께 시작하였습니다. "
        +  2015contributors-conference-diversity4: "패널 진행은 "
        +  2015contributors-conference-diversity5: "과"
        +  2015contributors-conference-diversity6: "가 맡았으며, "
        +  2015contributors-conference-diversity7: "2015년 5월 25일 화요일 카네기 멜론 대학교 Kresge Auditorium 에서 열렸습니다. 연사는"
        +  2015contributors-conference-diversity8: "과"
        +  2015contributors-conference-diversity9: "였습니다."
        +  2015cc_1: "다양한 배경 출신의 참여자들이 미소를 지으며 손으로 p5 사인을 만드는 모습"
        +  2015cc_2: "잔디 위에서 뛰놀고, 웃으며, 손을 하늘 위로 들어올리는 참여자들의 모습"
        +  2015cc_3: "노트북으로 p5.js 커뮤니티 성명서를 발표하고 있는 여성"
        +  2015cc_4: "마이크에 대고 열정적으로 말하고 있는 여성과 그를 쳐다보는 남성 협력자 두 명"
        +  2015cc_5: "미소를 띄우며 발표를 경청하는 참여자들 모습"
        +  2015cc_6: "마이크에 대고 3명의 여학생들을 향해 p5.js를 설명하는 여성"
        +  2015cc_7: "여학생 한명이 마이크에 대고 발표하는 동안, 포스트잇이 붙은 화이트보드를 둘러앉은 참여자들의 모습"
        +  2015cc_8: "책상에 둘러앉아 서로의 노트북을 보며 코드를 비교하는 참여자들의 모습"
        +  2015cc_9: "프로그래밍에 대한 노트가 적힌 여러가지 색의 포스트잇이 화이트보드에 붙어있는 모습"
        +  2015cc_10: "한 교실에서 다양한 기술 능력의 가치를 존중하는 것에 대해 발표하는 여성과 그의 파워포인트를 바라보는 참여자들의 모습"
        +  2015cc_11: "대강당 무대 위 단상에서 발표하는 여성과 무대에 앉아있는 세명의 참여자들, 그리고 무대 위 스크린상의 스카이프 화면을 통해 보이는 또다른 세명의 원격 참여자들"
        +  2015cc_12: "노트북으로 작업하는 참여자들이 있는 교실 전경"
        +  2015cc_13: "둥그렇게 앉아 토론하는 5명의 사람들"
        +  2015cc_14: "노트북과 함께 둥그렇게 앉아 자신의 필기를 공유하는 5명의 사람들"
        +  2015cc_15: "교실에서 참여자들을 향해 마이크로 발표하는 남성"
        +  2019contributors-conference-title: "2019년 기여자 컨퍼런스"
        +  2019contributors-conference-date: "8월 13-18일"
        +  2019contributors-conference1: "다학제적 배경을 지닌 35명의 참여자들이 "
        +  2019contributors-conference2: "에 모여 p5.js의 프로그래밍 환경과 그 현주소를 탐색하고, 코드 및 문서 개발, 그리고 커뮤니티 확장 방법에 대해 논의하였습니다. 참여자들은 크리에이티브 기술, 인터랙션 디자인, 뉴미디어 아트를 아우르는 다양한 분야의 종사자들로 구성되었으며, 컨퍼런스에서의 논의는 이러한 다학제적인 시각을 바탕으로 진행되었습니다. 참여자 그룹은 접근성, 퍼포먼스 속 음악과 코딩, 크리에이티브 기술 지형, 그리고 국제화를 포함한 여러 주제에 초점을 두었습니다." 
        +  2019contributors-conference3: "비디오 촬영: 치안치안 예(Qianqian Ye)"
        +  2019contributors-conference4: "사진 촬영: 재클린 존슨(Jacquelyn Johnson)"
        +  outputs: "결과물"
        +  output1: ". p5.js를 위한 아주 유연한 삼각형, 사각형, 육각형, 그리고 팔각형 묶음 구현. 제작: 아렌 데이비(Aren Davey)"
        +  output2: ". 복수의 클라이언트를 특정 호스트 페이지에 연결하는 멀티디바이스 및 멀티플레이어 게임을 위한 템플릿 파일. 제작: L05"
        +  output3: ""
        +  output3-1: "를 이용한 실험들. softCompile 및 OSC 인터페이스 초기 단계 구현과 더불어 MIDI 셋업에 연결한 데모. p5.js 협업 라이브 코딩 VJ 환경 구현. 제작: 테드 데이비스(Ted Davis)"
        +  output4: "가상 공간에서의 블랙니스(Blackness)와 젠더를 다룬 패널, 아메리칸 아티스트(American Artist)이 진행하고 shawné michaelain holloway와 LaJuné McMillian이 함께함."
        +  output5: "에베레스트 핍킨(Everest Pipkin)과 존 챔버스(Jon Chambers)가 진행한 워크숍"
        +  output6: ""
        +  output6-1: "p5.js를 위한 노트북 인터페이스"
        +  output6-2: "의 프로토타입. 제작: 앨리슨 패리쉬(Allison Parrish)"
        +  output7: "새로운 설치 예술 작품. 제작: Stalgia Grigg, LaJuné McMillian, Aatish Bhatia, 그리고 Jon Chambers."
        +  output8: "p5.js의 전세계 기여자를 위한 툴킷"
        +  output8-1: "제작: Aarón Montoya-Moraga, Kenneth Lim, Guillermo Montecinos, Qianqian Ye, Dorothy R. Santos, 그리고 Yasheng She."
        +  output9: "비폭력적 크리이에티브 코드 작성법. "
        +  output9-1: "올리비아 로스(Olivia Ross) 진행 잡지."
        +  output10: "p5.js 웹사이트의 접근성에 대한 점검. 스크린 리더 접근성 향상 기능을 비롯하여, 홈, 다운로드, 시작하기, 레퍼런스 페이지 등을 업데이트. 기여: Claire Kearney-Volpe, Sina Bahram, Kate Hollenbach, Olivia Ross, Luis Morales-Navarro, Lauren McCarthy, 그리고 Evelyn Masso"
        +  output11: "협업 퍼포먼스. 제작: Luisa Pereira, Jun Shern Chan, Shefali Nayak, Sona Lee, Ted Davis, 그리고 Carlos Garcia."
        +  output12: "퍼포먼스. 제작: 나탈리 브래긴스키(Natalie Braginsky)"
        +  output13: "p5 에디터를 위한 p5.js 라이브러리 시스템 디자인. 제작: 캐시 타라카지안(Cassie Tarakajian)과 루카 다마스코(Luca Damasco)"
        +  output14: "p5와 다른 라이브러리 연결을 위한 프로토타입들. 제작: 알렉스 이쑤안 쑤(Alex Yixuan Xu)와 로렌 밸리(Lauren Valley)"
        +  output15: "클로징 캠프파이어. 진행: 골렌 레빈(Golan Levin)"
        +  2019cc_1: "단상 위에서 한 그룹을 향해 발표를 하는 남성"
        +  2019cc_2: "긴 테이블에 앉아 점심을 먹으며 토론하는 참여자들"
        +  2019cc_3: "교실 속 참가자들의 모습으로, 어떤 이들은 노트북으로 작업하고, 다른 이들은 대화를 나눈다"
        +  2019cc_4: "교실에서 노트북으로 작업하는 참여자들의 모습"
        +  2019cc_5: "어두운 교실에서 미팅을 하는 참여자들"
        +  2019cc_6: "여러 참여자들이 모인 교실에서 발표를 하는 여성"
        +  2019cc_7: "많은 이들이 모여있는 교실에서 대화를 나누는 참가자들"
        +  2019cc_8: "한 교실에서 동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_9: "데이터 익명화의 문제점에 대한 글이 투사된 스크린과 그 앞 단상에서 말하는 참여자"
        +  2019cc_10: "\"p5.js는 접근성을 증진을 위한 기능 외에는 새로운 기능을 추가하지 않을 것입니다\"라고 적힌 텍스트 앞에 서서, 동료 참여자를 향해 마이크에 대고 말하는 사람"
        +  2019cc_11: "동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_12: "동료 참여자를 향해 마이크에 대고 말하는 남성"
        +  2019cc_13: "교실 속, 경청 중인 발표자들을 향해 앉아있는 참여자들"
        +  2019cc_14: "교실 속, 경청 중인 발표자를 마주하고 있는 참여자들"
        +  2019cc_15: "\"신성한 경계\"라 적힌 스크린을 뒤로하고, 동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_16: "3D 렌더링된 사람 이미지를 보여주는 패널에 경청하는 참여자들 전경"
        +  2019cc_17: "노트북과 함께 테이블에 둘러앉아 TV 스크린 상의 코드를 살펴보는 참여자들"
        +  2019cc_18: "등신 크기의 테디 베어 옆에 앉아 노트북으로 작업하는 여성"
        +  2019cc_19: "밖에 나와 미소를 짓는 참여자들"
        +  2019cc_20: "동그랗게 모여 서서 대화를 나누는 4명의 참여자들"
        +  2019cc_21: "밖에 나와 앉아 함께 점심을 먹는 참여자들"
        +  2019cc_22: "거대한 U자형 테이블에 둘러앉아 교실 앞쪽을 쳐다보는 참여자들"
        +  2019cc_23: "교실 앞에 앉아 마이크에 대고 활력적으로 말하는 남성"
        +  2019cc_24: "하늘 향해 손을 들고 활기차게 미소짓는 모습이 담긴 참여자 단체 사진"
        +  2019cc_25: "LCD 모니터로 만들어진 캠프파이어에 둘러앉은 사람들"
         
         books:
        -  books-title: "관련 책"
        +  books-title: "출판물"
         
         examples:
           Examples: "예제"
        -  back-examples: "Back to Examples"
        -  Structure: "Structure"
        -  Form: "Form"
        -  Data: "Data"
        -  Arrays: "Arrays"
        -  Control: "Control"
        -  Image: "Image"
        -  Color: "Color"
        -  Math: "Math"
        -  Simulate: "Simulate"
        -  Interaction: "Interaction"
        -  Objects: "Objects"
        -  Lights: "Lights"
        -  Motion: "Motion"
        -  Instance_Mode: "Instance Mode"
        +  back-examples: "예제로 돌아가기"
        +  Structure: "구조"
        +  Form: "도형"
        +  Data: "데이터"
        +  Arrays: "배열"
        +  Control: "컨트롤"
        +  Image: "이미지"
        +  Color: "색상"
        +  Math: "수학"
        +  Simulate: "시뮬레이션"
        +  Interaction: "인터랙션"
        +  Objects: "오브젝트"
        +  Lights: "라이트"
        +  Motion: "모션"
        +  Instance_Mode: "인스턴스 모드"
           Dom: "DOM"
        -  Drawing: "Drawing"
        -  Transform: "Transform"
        -  Typography: "Typography"
        +  Drawing: "드로잉"
        +  Transform: "변형"
        +  Typography: "타이포그래피"
           3D: "3D"
        -  Input: "Input"
        -  Advanced_Data: "Advanced Data"
        -  Sound: "Sound"
        -  Mobile: "Mobile"
        +  Input: "입력"
        +  Advanced_Data: "고급 데이터"
        +  Sound: "사운드"
        +  Mobile: "모바일"
           Hello_P5: "Hello p5"
         
         reference:
           Reference: "레퍼런스"
         
         showcase:
        -  showcase-title: "Showcase"
        -  showcase-intro1: "Introducing Showcase, curated by " 
        -  showcase-intro2: "We're celebrating how people are using p5.js to make creative work, learning, and open source more interesting and inclusive. Together, we make community."
        -  showcase-intro3: "During Summer 2019, we asked a few creators to share more about how they've used p5.js. Nominate someone's p5.js work or your own to be featured here!"
        +  showcase-title: "쇼케이스"
        +  showcase-intro1: "쇼케이스 페이지는 p5.js를 보다 흥미진진하고 포용적으로 만든 창작물, 학습물, 오픈 소스 사례들을 기쁘게 소개하고자 합니다. 쇼케이스 페이지 기획 및 제작: 애슐리 강 " 
        +  showcase-intro2: "이렇게 우리는 함께 커뮤니티를 만들어 나가는게 아닐까요?:)"
        +  showcase-intro3: "2019년 여름, 몇몇 창작자들에게 그들의 p5.js 기반의 프로젝트 소개를 요청하였습니다. 아래의 버튼을 눌러 자신 또는 타인의 p5.js 작품을 추천해보세요!"
           showcase-featuring: "Featuring"
        -  project-tag-art: "Art"
        -  project-tag-design: "Design"
        -  project-tag-code: "Code"
        -  project-tag-curriculum: "Curriculum"
        -  project-tag-documentation: "Documentation"
        -  project-tag-game: "Game"
        -  project-tag-library: "Library"
        -  project-tag-organizing: "Organizing"
        -  project-tag-tool: "Tool"
        -  project-tag-tutorial: "Tutorial"
        -  project-roni: "Programmed Plotter Drawings"
        +  project-tag-art: "예술"
        +  project-tag-design: "디자인"
        +  project-tag-code: "코드"
        +  project-tag-curriculum: "커리큘럼"
        +  project-tag-documentation: "문서화"
        +  project-tag-game: "게임"
        +  project-tag-library: "라이브러리"
        +  project-tag-organizing: "행사 또는 모임"
        +  project-tag-tool: "툴"
        +  project-tag-tutorial: "튜토리얼"
        +  project-roni: "프로그래밍된 각도기 드로잉(Programmed Plotter Drawings)"
           credit-roni: "Roni Cantor"
        -  description-roni: "Sine waves and lerps generated in p5.js, exported as SVG, and drawn with a plotter and pens."
        +  description-roni: "p5.js로 제작한 싸인파(Sine wave)와 선형 보간(lerp)으로, 실물 각도기와 펜과 연결되어 드로잉하고, SVG 파일로 내보내기 가능."
           project-phuong: "Airi Flies"
           credit-phuong: "Phuong Ngo"
        -  description-phuong: "In this game developed with p5.play, help Airi fly by saying PEW. Created to encourage people to get out of their comfort zone and feel more confident about themselves regardless of what they do and how they look or sound."
        +  description-phuong: "p5.play로 제작된 게임으로, PEW라고 말해 Airi가 날 수 있도록 돕는다. 사용자들이 자신의 안전 지대를 벗어난 곳에서도 행동, 외모, 발언에 상관없이 자신감을 갖게하고자 하는 취지에서 제작."
           project-daein: "Chillin'"
        -  credit-daein: "Dae In Chung"
        -  description-daein: "An interactive typographic poster that uses a mobile device's motion sensor with p5.js."
        +  credit-daein: "정대인 (Dae In Chung)"
        +  description-daein: "모바일 기기의 모션 센서와 p5.js를 활용한, 인터랙티브 타이포그래픽 포스터"
           project-qianqian: "Qtv"
           credit-qianqian: "Qianqian Ye"
        -  description-qianqian: "A video channel with 1-minute videos in Mandarin about creative coding, art, and technology, including p5.js tutorials for beginners. Available on YouTube, Instagram, Bilibili, and TikTok."
        -  project-casey-louise: "p5.js Shaders"
        +  description-qianqian: "초심자를 위한 p5.js 튜토리얼을 포함하여, 코딩, 예술, 그리고 기술에 대해 다루는 1분 길이의 중국어 영상 채널들. 유투브, 인스타그램, 비리비리(Bilibili), 틱톡(TikTok)에서 확인 가능."
        +  project-casey-louise: "p5.js 셰이더(Shaders)"
           credit-casey-louise: "Casey Conchinha, Louise Lessél"
        -  description-casey-louise: "A resource for learning the what, why, and how of using shaders in p5.js."
        -  project-moon-xin: "Moving Responsive Posters"
        -  credit-moon-xin: "Moon Jang, Xin Xin, and students"
        -  description-moon-xin: "Browser-based moving posters that use graphical systems, transformation methods, and p5.js to address the connotations of a word less than 8 letters. Designed by students for a graphic design course (Visual Narrative Systems) at the University of Georgia."
        +  description-casey-louise: "셰이더(Shaders)란 무엇이고, 이를 p5.js에서 왜, 그리고 어떻게 사용하는지 배울 수 있는 자료."
        +  project-moon-xin: "움직이는 반응형 포스터(Moving Responsive Posters)"
        +  credit-moon-xin: "Moon Jang, Xin Xin, 그리고 학생들"
        +  description-moon-xin: "브라우저 기반의 움직이는 포스터로, 그래픽 시스템과 변형 메소드, 그리고 p5.js를 사용하여 8자 미만 단어가 내포하는 바를 표현. 조지아 대학교(University of Georgia)의 그래픽 디자인 과정인 'Visual Narrative Systems'의 수강생들이 디자인."
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 90f89d6a8a..9e24eb2b20 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -3,95 +3,95 @@
           "Download": "다운로드",
           "Start": "시작하기",
           "Reference": "레퍼런스",
        -  "reference-tagline": "la intuición de Processing x el poder de JavaScript",
        +  "reference-tagline": "프로세싱의 직관성에 자바스크립트의 강력함을 곱하다*",
           "reference-search": "API 검색",
           "reference-menu-home": "홈",
           "reference-menu-download": "다운로드",
           "reference-menu-get-started": "시작하기",
           "reference-menu-reference": "레퍼런스",
           "reference-menu-libraries": "라이브러리",
        -  "reference-menu-learn": "학습",
        +  "reference-menu-learn": "배우기",
           "reference-menu-examples": "예제",
        -  "reference-menu-books": "관련 책",
        +  "reference-menu-books": "출판물",
           "reference-menu-community": "커뮤니티",
           "reference-menu-forum": "포럼",
        -  "reference-description1": "찾는 항목이 이곳에 없다면, 다음의 페이지를 살펴보세요:",
        -  "reference-description2": " 혹은 ",
        +  "reference-description1": "찾는 항목이 없다면, 다음의 페이지를 살펴보세요:",
        +  "reference-description2": " 또는 ",
           "reference-description3": "오프라인 버전의 레퍼런스는 다음 링크에서 다운받을 수 있습니다: ",
           "reference-description4": "레퍼런스 다운로드",
           "reference-contribute1": "잘못된 부분이나 제안사항이 있다면",
        -  "reference-contribute2": "알려주세요",
        -  "reference-error1": "오타나 버그를 발견했다구요?",
        +  "reference-contribute2": "언제든 알려주세요",
        +  "reference-error1": "오타나 버그를 발견했다면",
           "reference-error2": "관련 문서는 이곳에 있습니다: ",
           "reference-error3": "p5.js에 기여하고 싶다면, ",
           "reference-error4": "파일을 수정하고",
        -  "reference-error5": "pull request 해주세요!",
        +  "reference-error5": "에 풀 리퀘스트(pull request) 해주세요!",
           "reference-example": "예제",
           "reference-description": "설명",
           "reference-extends": "확장",
           "reference-parameters": "변수",
           "reference-syntax": "문법",
        -  "reference-returns": "리턴",
        +  "reference-returns": "반환(return)",
           "footer1": "p5.js는 ",
        -  "footer2": "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 ",
        +  "footer2": "가 창안하고 협력자 커뮤니티와 함께 개발되었습니다. 지원: 프로세싱 재단 ",
           "footer3": " 과 ",
        -  "footer4": "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 :",
        +  "footer4": " 아이덴티티 및 그래픽 디자인:",
           "Libraries": "라이브러리",
        -  "Learn": "학습",
        +  "Learn": "배우기",
           "Examples": "예제",
        -  "Books": "관련 책",
        +  "Books": "출판물",
           "Community": "커뮤니티",
        -  "Contribute": "기여하기",
        +  "Contribute": "함께하기",
           "Forum": "포럼",
           "h1": "레퍼런스",
        -  "Color": "Color",
        -  "Shape": "Shape", 
        -  "Creating & Reading": "Creating & Reading", 
        -  "Setting": "Setting", 
        -  "2D Primitives": "2D Primitives", 
        +  "Color": "색상",
        +  "Shape": "도형", 
        +  "Creating & Reading": "만들기 & 읽기", 
        +  "Setting": "설정하기", 
        +  "2D Primitives": "2D 기본 조형", 
           "Attributes": "Attributes",  
        -  "Curves": "Curves", 
        -  "Vertex": "Vertex", 
        -  "3D Models": "3D Models",  
        -  "3D Primitives": "3D Primitives", 
        -  "Constants": "Constants",  
        -  "Structure": "Structure",  
        -  "Environment": "Environment",  
        +  "Curves": "곡선 Curves", 
        +  "Vertex": "버텍스 Vertex", 
        +  "3D Models": "3D 모델",  
        +  "3D Primitives": "3D 기본 조형", 
        +  "Constants": "상수",  
        +  "Structure": "구조",  
        +  "Environment": "환경",  
           "DOM": "DOM", 
        -  "Rendering": "Rendering",  
        -  "Transform": "Transform", 
        -  "Data": "Data",  
        -  "Dictionary": "Dictionary",  
        -  "Array Functions": "Array Functions",  
        -  "Conversion": "Conversion", 
        -  "String Functions": "String Functions",  
        -  "Events": "Events",  
        -  "Acceleration": "Acceleration",  
        -  "Keyboard": "Keyboard",  
        -  "Mouse": "Mouse", 
        -  "Touch": "Touch", 
        -  "Image": "Image",  
        -  "Loading & Displaying": "Loading & Displaying", 
        -  "Pixels": "Pixels",  
        +  "Rendering": "렌더링",  
        +  "Transform": "변형(Transform)", 
        +  "Data": "데이터",  
        +  "Dictionary": "사전(Dictionary)",  
        +  "Array Functions": "배열 기능",  
        +  "Conversion": "변환(Conversion)", 
        +  "String Functions": "문자열(String) 기능",  
        +  "Events": "이벤트",  
        +  "Acceleration": "가속",  
        +  "Keyboard": "키보드",  
        +  "Mouse": "마우스", 
        +  "Touch": "터치", 
        +  "Image": "이미지",  
        +  "Loading & Displaying": "로딩 & 디스플레이", 
        +  "Pixels": "픽셀",  
           "IO": "IO", 
        -  "Input": "Input", 
        -  "Output": "Output", 
        -  "Table": "Table", 
        -  "Time & Date": "날짜와 시간",  
        +  "Input": "입력(Input)", 
        +  "Output": "아웃풋", 
        +  "Table": "테이블", 
        +  "Time & Date": "날짜 & 시간",  
           "XML": "XML", 
           "Math": "수학", 
           "Calculation": "계산",  
           "Noise": "노이즈", 
        -  "Trigonometry": "Trigonometry",  
        +  "Trigonometry": "삼각법",  
           "Typography": "타이포그래피", 
           "Font": "폰트", 
        -  "Lights, Camera": "Lights, Camera",  
        +  "Lights, Camera": "라이트, 카메라",  
           "Camera": "카메라",  
        -  "Lights": "빛",  
        -  "Material": "Material",
        +  "Lights": "라이트"",  
        +  "Material": "재질(Material)",
           "p5": {
             "background": {
        -      "description": "background() 함수는 p5.js 캔버스 배경 색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 한번만 설정하면 되는 경우에 setup() 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.",
        +      "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 일회적으로 설정할 경우 setup() 함수 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.",
               "params": ["p5.Color: color() 함수를 통해 만들어진 값",
                        "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex",
                        "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js
        index 7b0ca9e5bc..29a5a885c5 100644
        --- a/src/templates/pages/reference/assets/js/reference.js
        +++ b/src/templates/pages/reference/assets/js/reference.js
        @@ -448,10 +448,10 @@ define('text',['module'], function (module) {
         });
         
         
        -define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\n<form>\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\n  <label class="sr-only" for="search_reference_field">Search reference</label>\n</form>\n\n';});
        +define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\r\n<form>\r\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\r\n  <label class="sr-only" for="search_reference_field">Search reference</label>\r\n</form>\r\n\r\n';});
         
         
        -define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\n\n  <strong><%=name%></strong>\n\n  <span class="small">\n    <% if (final) { %>\n    constant\n    <% } else if (itemtype) { %>\n    <%=itemtype%> \n    <% } %>\n\n    <% if (className) { %>\n    in <strong><%=className%></strong>\n    <% } %>\n\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\n    <% } %>\n  </span>\n\n</p>';});
        +define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\r\n\r\n  <strong><%=name%></strong>\r\n\r\n  <span class="small">\r\n    <% if (final) { %>\r\n    constant\r\n    <% } else if (itemtype) { %>\r\n    <%=itemtype%> \r\n    <% } %>\r\n\r\n    <% if (className) { %>\r\n    in <strong><%=className%></strong>\r\n    <% } %>\r\n\r\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\r\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\r\n    <% } %>\r\n  </span>\r\n\r\n</p>';});
         
         /*!
          * typeahead.js 0.10.2
        @@ -2303,7 +2303,7 @@ define('searchView',[
         });
         
         
        -define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\n  <div class="reference-group clearfix main-ref-page">  \n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\n    <div class="reference-subgroups clearfix main-ref-page">  \n    <% _.each(group.subgroups, function(subgroup, ind) { %>\n      <div class="reference-subgroup">\n        <% if (subgroup.name !== \'0\') { %>\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\n        <% } %>\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\n        <% _.each(subgroup.items, function(item) { %>\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\n        <% }); %>\n        </ul>\n      </div>\n    <% }); %>\n    </div>\n  </div>\n<% }); %>\n';});
        +define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\r\n  <div class="reference-group clearfix main-ref-page">  \r\n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\r\n    <div class="reference-subgroups clearfix main-ref-page">  \r\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\r\n      <div class="reference-subgroup">\r\n        <% if (subgroup.name !== \'0\') { %>\r\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\r\n        <% } %>\r\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\r\n        <% _.each(subgroup.items, function(item) { %>\r\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\r\n        <% }); %>\r\n        </ul>\r\n      </div>\r\n    <% }); %>\r\n    </div>\r\n  </div>\r\n<% }); %>\r\n';});
         
         define('listView',[
           'App',
        @@ -2442,13 +2442,13 @@ define('listView',[
         });
         
         
        -define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\n\n<% if (item.example) { %>\n<div class="example">\n  <h3 id="reference-example">Examples</h3>\n\n  <div class="example-content" data-alt="<%= item.alt %>">\n    <% _.each(item.example, function(example, i){ %>\n      <%= example %>\n    <% }); %>\n  </div>\n</div>\n<% } %>\n\n<div class="description">\n    \n  <h3 id="reference-description">Description</h3>\n\n  <% if (item.deprecated) { %>\n    <p>\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n    </p>\n  <% } %>\n      \n\n  <span class=\'description-text\'><%= item.description %></span>\n\n  <% if (item.extends) { %>\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\n  <% } %>\n\n  <% if (item.module === \'p5.sound\') { %>\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\n    </p>\n  <% } %>\n\n  <% if (item.constRefs) { %>\n    <p>Used by:\n  <%\n      var refs = item.constRefs;\n      for (var i = 0; i < refs.length; i ++) {\n        var ref = refs[i];\n        var name = ref;\n        if (name.substr(0, 3) === \'p5.\') {\n          name = name.substr(3);\n        }\n  if (i !== 0) {\n          if (i == refs.length - 1) {\n            %> and <%\n          } else {\n            %>, <%\n          }\n        }\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\n      }\n  %>\n    </p>\n  <% } %>\n</div>\n\n<% if (isConstructor || !isClass) { %>\n\n<div>\n  <h3 id="reference-syntax">Syntax</h3>\n  <p>\n    <% syntaxes.forEach(function(syntax) { %>\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\n    <% }) %>\n  </p>\n</div>\n\n\n<% if (item.params) { %>\n  <div class="params">\n    <h3 id="reference-parameters">Parameters</h3>\n    <ul aria-labelledby=\'reference-parameters\'>\n    <% for (var i=0; i<item.params.length; i++) { %>\n      <% var p = item.params[i] %>\n      <li>\n        <div class=\'paramname\'><%=p.name%></div>\n        <% if (p.type) { %>\n          <div class=\'paramtype\'>\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\n          <% if (p.optional) { %> (Optional)<% } %>\n          </div>\n        <% } %>\n      </li>\n    <% } %>\n    </ul>\n  </div>\n<% } %>\n\n<% if (item.return && item.return.type) { %>\n  <div>\n    <h3 id="reference-returns">Returns</h3>\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\n  </div>\n<% } %>\n\n<% } %>\n';});
        +define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\r\n\r\n<% if (item.example) { %>\r\n<div class="example">\r\n  <h3 id="reference-example">Examples</h3>\r\n\r\n  <div class="example-content" data-alt="<%= item.alt %>">\r\n    <% _.each(item.example, function(example, i){ %>\r\n      <%= example %>\r\n    <% }); %>\r\n  </div>\r\n</div>\r\n<% } %>\r\n\r\n<div class="description">\r\n    \r\n  <h3 id="reference-description">Description</h3>\r\n\r\n  <% if (item.deprecated) { %>\r\n    <p>\r\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\r\n    </p>\r\n  <% } %>\r\n      \r\n\r\n  <span class=\'description-text\'><%= item.description %></span>\r\n\r\n  <% if (item.extends) { %>\r\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\r\n  <% } %>\r\n\r\n  <% if (item.module === \'p5.sound\') { %>\r\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\r\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\r\n    </p>\r\n  <% } %>\r\n\r\n  <% if (item.constRefs) { %>\r\n    <p>Used by:\r\n  <%\r\n      var refs = item.constRefs;\r\n      for (var i = 0; i < refs.length; i ++) {\r\n        var ref = refs[i];\r\n        var name = ref;\r\n        if (name.substr(0, 3) === \'p5.\') {\r\n          name = name.substr(3);\r\n        }\r\n  if (i !== 0) {\r\n          if (i == refs.length - 1) {\r\n            %> and <%\r\n          } else {\r\n            %>, <%\r\n          }\r\n        }\r\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\r\n      }\r\n  %>\r\n    </p>\r\n  <% } %>\r\n</div>\r\n\r\n<% if (isConstructor || !isClass) { %>\r\n\r\n<div>\r\n  <h3 id="reference-syntax">Syntax</h3>\r\n  <p>\r\n    <% syntaxes.forEach(function(syntax) { %>\r\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\r\n    <% }) %>\r\n  </p>\r\n</div>\r\n\r\n\r\n<% if (item.params) { %>\r\n  <div class="params">\r\n    <h3 id="reference-parameters">Parameters</h3>\r\n    <ul aria-labelledby=\'reference-parameters\'>\r\n    <% for (var i=0; i<item.params.length; i++) { %>\r\n      <% var p = item.params[i] %>\r\n      <li>\r\n        <div class=\'paramname\'><%=p.name%></div>\r\n        <% if (p.type) { %>\r\n          <div class=\'paramtype\'>\r\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\r\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\r\n          <% if (p.optional) { %> (Optional)<% } %>\r\n          </div>\r\n        <% } %>\r\n      </li>\r\n    <% } %>\r\n    </ul>\r\n  </div>\r\n<% } %>\r\n\r\n<% if (item.return && item.return.type) { %>\r\n  <div>\r\n    <h3 id="reference-returns">Returns</h3>\r\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\r\n  </div>\r\n<% } %>\r\n\r\n<% } %>\r\n';});
         
         
        -define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n<div class="constructor">\n  <!--<h2>Constructor</h2>--> \n  <%=constructor%>\n</div>\n<% } %>\n\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n  <h4>Fields</h4>\n  <p>\n    <% _.each(fields, function(item) { %>\n      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>\n      <br>\n    <% }); %>\n  </p>\n<% } %>\n\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n  <h4>Methods</h4>\n  <p>\n    <table>\n    <% _.each(methods, function(item) { %>\n      <tr>\n      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>\n      </tr>\n    <% }); %>\n    </table>\n  </p>\n<% } %>\n';});
        +define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <!--<h2>Constructor</h2>--> \r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h4>Fields</h4>\r\n  <p>\r\n    <% _.each(fields, function(item) { %>\r\n      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>\r\n      <br>\r\n    <% }); %>\r\n  </p>\r\n<% } %>\r\n\r\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h4>Methods</h4>\r\n  <p>\r\n    <table>\r\n    <% _.each(methods, function(item) { %>\r\n      <tr>\r\n      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>\r\n      </tr>\r\n    <% }); %>\r\n    </table>\r\n  </p>\r\n<% } %>\r\n';});
         
         
        -define('text!tpl/itemEnd.html',[],function () { return '\n<br><br>\n\n<div>\n<% if (item.file && item.line) { %>\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\n<% } %>\n</div>\n\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\n<br><br>\n';});
        +define('text!tpl/itemEnd.html',[],function () { return '\r\n<br><br>\r\n\r\n<div>\r\n<% if (item.file && item.line) { %>\r\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\r\n<% } %>\r\n</div>\r\n\r\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\r\n<br><br>\r\n';});
         
         // Copyright (C) 2006 Google Inc.
         //
        @@ -4332,7 +4332,7 @@ define('itemView',[
         });
         
         
        -define('text!tpl/menu.html',[],function () { return '<div>\n  <br>\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\n</div>\n\n<div id=\'collection-list-categories\'>\n<h2 class="sr-only" id="categories">Categories</h2>\n<% var i=0; %>\n<% var max=Math.floor(groups.length/4); %>\n<% var rem=groups.length%4; %>\n\n<% _.each(groups, function(group){ %>\n  <% var m = rem > 0 ? 1 : 0 %>\n  <% if (i === 0) { %>\n    <ul aria-labelledby="categories">\n    <% } %>\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\n    <% if (i === (max+m-1)) { %>\n    </ul>\n  \t<% rem-- %>\n  \t<% i=0 %>\n  <% } else { %>\n  \t<% i++ %>\n  <% } %>\n<% }); %>\n</div>\n';});
        +define('text!tpl/menu.html',[],function () { return '<div>\r\n  <br>\r\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\r\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\r\n</div>\r\n\r\n<div id=\'collection-list-categories\'>\r\n<h2 class="sr-only" id="categories">Categories</h2>\r\n<% var i=0; %>\r\n<% var max=Math.floor(groups.length/4); %>\r\n<% var rem=groups.length%4; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% var m = rem > 0 ? 1 : 0 %>\r\n  <% if (i === 0) { %>\r\n    <ul aria-labelledby="categories">\r\n    <% } %>\r\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\r\n    <% if (i === (max+m-1)) { %>\r\n    </ul>\r\n  \t<% rem-- %>\r\n  \t<% i=0 %>\r\n  <% } else { %>\r\n  \t<% i++ %>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define('menuView',[
           'App',
        @@ -4401,7 +4401,7 @@ define('menuView',[
         });
         
         
        -define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\n\n<p><%= module.description %></p>\n\n<div id="library-page" class="reference-group clearfix">  \n\n<% var t = 0; col = 0; %>\n\n<% _.each(groups, function(group){ %>\n  <% if (t == 0) { %> \n    <div class="column_<%=col%>">\n  <% } %>\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\n    <% if (group.hash) { %> </a> <% } %>\n  <% } %>\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\n    <% t++; %>\n  <% }); %>\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\n    </div>\n  <% } %>\n<% }); %>\n</div>\n';});
        +define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define(
           'libraryView',[
        diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map
        index 7337a93988..dfd60136e2 100644
        --- a/src/templates/pages/reference/assets/js/reference.js.map
        +++ b/src/templates/pages/reference/assets/js/reference.js.map
        @@ -29,26 +29,26 @@
           "file": "reference.js",
           "sourcesContent": [
             "(function () {\n",
        -    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define('documented-method',[], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    module.exports = factory();\n  } else {\n    root.DocumentedMethod = factory();\n  }\n}(this, function () {\n  function extend(target, src) {\n    Object.keys(src).forEach(function(prop) {\n      target[prop] = src[prop];\n    });\n    return target;\n  }\n\n  function DocumentedMethod(classitem) {\n    extend(this, classitem);\n\n    if (this.overloads) {\n      // Make each overload inherit properties from their parent\n      // classitem.\n      this.overloads = this.overloads.map(function(overload) {\n        return extend(Object.create(this), overload);\n      }, this);\n\n      if (this.params) {\n        throw new Error('params for overloaded methods should be undefined');\n      }\n\n      this.params = this._getMergedParams();\n    }\n  }\n\n  DocumentedMethod.prototype = {\n    // Merge parameters across all overloaded versions of this item.\n    _getMergedParams: function() {\n      var paramNames = {};\n      var params = [];\n\n      this.overloads.forEach(function(overload) {\n        if (!overload.params) {\n          return;\n        }\n        overload.params.forEach(function(param) {\n          if (param.name in paramNames) {\n            return;\n          }\n          paramNames[param.name] = param;\n          params.push(param);\n        });\n      });\n\n      return params;\n    }\n  };\n\n  return DocumentedMethod;\n}));\n\n",
        -    "/**\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/requirejs/text for details\n */\n/*jslint regexp: true */\n/*global require, XMLHttpRequest, ActiveXObject,\n  define, window, process, Packages,\n  java, location, Components, FileUtils */\n\ndefine('text',['module'], function (module) {\n    'use strict';\n\n    var text, fs, Cc, Ci, xpcIsWindows,\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = {},\n        masterConfig = (module.config && module.config()) || {};\n\n    text = {\n        version: '2.0.10',\n\n        strip: function (content) {\n            //Strips <?xml ...?> declarations so that external SVG and XML\n            //documents can be added to a document without worry. Also, if the string\n            //is an HTML document, only the part inside the body tag is returned.\n            if (content) {\n                content = content.replace(xmlRegExp, \"\");\n                var matches = content.match(bodyRegExp);\n                if (matches) {\n                    content = matches[1];\n                }\n            } else {\n                content = \"\";\n            }\n            return content;\n        },\n\n        jsEscape: function (content) {\n            return content.replace(/(['\\\\])/g, '\\\\$1')\n                .replace(/[\\f]/g, \"\\\\f\")\n                .replace(/[\\b]/g, \"\\\\b\")\n                .replace(/[\\n]/g, \"\\\\n\")\n                .replace(/[\\t]/g, \"\\\\t\")\n                .replace(/[\\r]/g, \"\\\\r\")\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\n        },\n\n        createXhr: masterConfig.createXhr || function () {\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n            var xhr, i, progId;\n            if (typeof XMLHttpRequest !== \"undefined\") {\n                return new XMLHttpRequest();\n            } else if (typeof ActiveXObject !== \"undefined\") {\n                for (i = 0; i < 3; i += 1) {\n                    progId = progIds[i];\n                    try {\n                        xhr = new ActiveXObject(progId);\n                    } catch (e) {}\n\n                    if (xhr) {\n                        progIds = [progId];  // so faster next time\n                        break;\n                    }\n                }\n            }\n\n            return xhr;\n        },\n\n        /**\n         * Parses a resource name into its component parts. Resource names\n         * look like: module/name.ext!strip, where the !strip part is\n         * optional.\n         * @param {String} name the resource name\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n         * where strip is a boolean.\n         */\n        parseName: function (name) {\n            var modName, ext, temp,\n                strip = false,\n                index = name.indexOf(\".\"),\n                isRelative = name.indexOf('./') === 0 ||\n                             name.indexOf('../') === 0;\n\n            if (index !== -1 && (!isRelative || index > 1)) {\n                modName = name.substring(0, index);\n                ext = name.substring(index + 1, name.length);\n            } else {\n                modName = name;\n            }\n\n            temp = ext || modName;\n            index = temp.indexOf(\"!\");\n            if (index !== -1) {\n                //Pull off the strip arg.\n                strip = temp.substring(index + 1) === \"strip\";\n                temp = temp.substring(0, index);\n                if (ext) {\n                    ext = temp;\n                } else {\n                    modName = temp;\n                }\n            }\n\n            return {\n                moduleName: modName,\n                ext: ext,\n                strip: strip\n            };\n        },\n\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n        /**\n         * Is an URL on another domain. Only works for browser use, returns\n         * false in non-browser environments. Only used to know if an\n         * optimized .js version of a text resource should be loaded\n         * instead.\n         * @param {String} url\n         * @returns Boolean\n         */\n        useXhr: function (url, protocol, hostname, port) {\n            var uProtocol, uHostName, uPort,\n                match = text.xdRegExp.exec(url);\n            if (!match) {\n                return true;\n            }\n            uProtocol = match[2];\n            uHostName = match[3];\n\n            uHostName = uHostName.split(':');\n            uPort = uHostName[1];\n            uHostName = uHostName[0];\n\n            return (!uProtocol || uProtocol === protocol) &&\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\n                   ((!uPort && !uHostName) || uPort === port);\n        },\n\n        finishLoad: function (name, strip, content, onLoad) {\n            content = strip ? text.strip(content) : content;\n            if (masterConfig.isBuild) {\n                buildMap[name] = content;\n            }\n            onLoad(content);\n        },\n\n        load: function (name, req, onLoad, config) {\n            //Name has format: some.module.filext!strip\n            //The strip part is optional.\n            //if strip is present, then that means only get the string contents\n            //inside a body tag in an HTML string. For XML/SVG content it means\n            //removing the <?xml ...?> declarations so the content can be inserted\n            //into the current doc without problems.\n\n            // Do not bother with the work if a build and text will\n            // not be inlined.\n            if (config.isBuild && !config.inlineText) {\n                onLoad();\n                return;\n            }\n\n            masterConfig.isBuild = config.isBuild;\n\n            var parsed = text.parseName(name),\n                nonStripName = parsed.moduleName +\n                    (parsed.ext ? '.' + parsed.ext : ''),\n                url = req.toUrl(nonStripName),\n                useXhr = (masterConfig.useXhr) ||\n                         text.useXhr;\n\n            // Do not load if it is an empty: url\n            if (url.indexOf('empty:') === 0) {\n                onLoad();\n                return;\n            }\n\n            //Load the text. Use XHR if possible and in a browser.\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                text.get(url, function (content) {\n                    text.finishLoad(name, parsed.strip, content, onLoad);\n                }, function (err) {\n                    if (onLoad.error) {\n                        onLoad.error(err);\n                    }\n                });\n            } else {\n                //Need to fetch the resource across domains. Assume\n                //the resource has been optimized into a JS module. Fetch\n                //by the module name + extension, but do not include the\n                //!strip part to avoid file system issues.\n                req([nonStripName], function (content) {\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                    parsed.strip, content, onLoad);\n                });\n            }\n        },\n\n        write: function (pluginName, moduleName, write, config) {\n            if (buildMap.hasOwnProperty(moduleName)) {\n                var content = text.jsEscape(buildMap[moduleName]);\n                write.asModule(pluginName + \"!\" + moduleName,\n                               \"define(function () { return '\" +\n                                   content +\n                               \"';});\\n\");\n            }\n        },\n\n        writeFile: function (pluginName, moduleName, req, write, config) {\n            var parsed = text.parseName(moduleName),\n                extPart = parsed.ext ? '.' + parsed.ext : '',\n                nonStripName = parsed.moduleName + extPart,\n                //Use a '.js' file name so that it indicates it is a\n                //script that can be loaded across domains.\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\n\n            //Leverage own load() method to load plugin value, but only\n            //write out values that do not have the strip argument,\n            //to avoid any potential issues with ! in file names.\n            text.load(nonStripName, req, function (value) {\n                //Use own write() method to construct full module value.\n                //But need to create shell that translates writeFile's\n                //write() to the right interface.\n                var textWrite = function (contents) {\n                    return write(fileName, contents);\n                };\n                textWrite.asModule = function (moduleName, contents) {\n                    return write.asModule(moduleName, fileName, contents);\n                };\n\n                text.write(pluginName, nonStripName, textWrite, config);\n            }, config);\n        }\n    };\n\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\n            typeof process !== \"undefined\" &&\n            process.versions &&\n            !!process.versions.node &&\n            !process.versions['node-webkit'])) {\n        //Using special require.nodeRequire, something added by r.js.\n        fs = require.nodeRequire('fs');\n\n        text.get = function (url, callback, errback) {\n            try {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            } catch (e) {\n                errback(e);\n            }\n        };\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\n            text.createXhr())) {\n        text.get = function (url, callback, errback, headers) {\n            var xhr = text.createXhr(), header;\n            xhr.open('GET', url, true);\n\n            //Allow plugins direct access to xhr headers\n            if (headers) {\n                for (header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                    }\n                }\n            }\n\n            //Allow overrides specified in config\n            if (masterConfig.onXhr) {\n                masterConfig.onXhr(xhr, url);\n            }\n\n            xhr.onreadystatechange = function (evt) {\n                var status, err;\n                //Do not explicitly handle errors, those should be\n                //visible via console output in the browser.\n                if (xhr.readyState === 4) {\n                    status = xhr.status;\n                    if (status > 399 && status < 600) {\n                        //An http 4xx or 5xx error. Signal an error.\n                        err = new Error(url + ' HTTP status: ' + status);\n                        err.xhr = xhr;\n                        errback(err);\n                    } else {\n                        callback(xhr.responseText);\n                    }\n\n                    if (masterConfig.onXhrComplete) {\n                        masterConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            };\n            xhr.send(null);\n        };\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\n        //Why Java, why is this so awkward?\n        text.get = function (url, callback) {\n            var stringBuffer, line,\n                encoding = \"utf-8\",\n                file = new java.io.File(url),\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                content = '';\n            try {\n                stringBuffer = new java.lang.StringBuffer();\n                line = input.readLine();\n\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                // http://www.unicode.org/faq/utf_bom.html\n\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\n                    // Eat the BOM, since we've already found the encoding on this file,\n                    // and we plan to concatenating this buffer with others; the BOM should\n                    // only appear at the top of a file.\n                    line = line.substring(1);\n                }\n\n                if (line !== null) {\n                    stringBuffer.append(line);\n                }\n\n                while ((line = input.readLine()) !== null) {\n                    stringBuffer.append(lineSeparator);\n                    stringBuffer.append(line);\n                }\n                //Make sure we return a JavaScript string and not a Java string.\n                content = String(stringBuffer.toString()); //String\n            } finally {\n                input.close();\n            }\n            callback(content);\n        };\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\n            typeof Components !== 'undefined' && Components.classes &&\n            Components.interfaces)) {\n        //Avert your gaze!\n        Cc = Components.classes,\n        Ci = Components.interfaces;\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\n\n        text.get = function (url, callback) {\n            var inStream, convertStream, fileObj,\n                readData = {};\n\n            if (xpcIsWindows) {\n                url = url.replace(/\\//g, '\\\\');\n            }\n\n            fileObj = new FileUtils.File(url);\n\n            //XPCOM, you so crazy\n            try {\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\n                           .createInstance(Ci.nsIFileInputStream);\n                inStream.init(fileObj, 1, 0, false);\n\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\n                                .createInstance(Ci.nsIConverterInputStream);\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\n\n                convertStream.readString(inStream.available(), readData);\n                convertStream.close();\n                inStream.close();\n                callback(readData.value);\n            } catch (e) {\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\n            }\n        };\n    }\n    return text;\n});\n\n",
        -    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\n<form>\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\n</form>\\n\\n';});\n\n",
        -    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\n\\n  <strong><%=name%></strong>\\n\\n  <span class=\"small\">\\n    <% if (final) { %>\\n    constant\\n    <% } else if (itemtype) { %>\\n    <%=itemtype%> \\n    <% } %>\\n\\n    <% if (className) { %>\\n    in <strong><%=className%></strong>\\n    <% } %>\\n\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\n    <% } %>\\n  </span>\\n\\n</p>';});\n\n",
        -    "/*!\n * typeahead.js 0.10.2\n * https://github.com/twitter/typeahead.js\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\n */\ndefine('typeahead',[], function() {\n\n//(function($) {\n\n\n    var _ = {\n        isMsie: function() {\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\n        },\n        isBlankString: function(str) {\n            return !str || /^\\s*$/.test(str);\n        },\n        escapeRegExChars: function(str) {\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n        },\n        isString: function(obj) {\n            return typeof obj === \"string\";\n        },\n        isNumber: function(obj) {\n            return typeof obj === \"number\";\n        },\n        isArray: $.isArray,\n        isFunction: $.isFunction,\n        isObject: $.isPlainObject,\n        isUndefined: function(obj) {\n            return typeof obj === \"undefined\";\n        },\n        bind: $.proxy,\n        each: function(collection, cb) {\n            $.each(collection, reverseArgs);\n            function reverseArgs(index, value) {\n                return cb(value, index);\n            }\n        },\n        map: $.map,\n        filter: $.grep,\n        every: function(obj, test) {\n            var result = true;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (!(result = test.call(null, val, key, obj))) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        some: function(obj, test) {\n            var result = false;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (result = test.call(null, val, key, obj)) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        mixin: $.extend,\n        getUniqueId: function() {\n            var counter = 0;\n            return function() {\n                return counter++;\n            };\n        }(),\n        templatify: function templatify(obj) {\n            return $.isFunction(obj) ? obj : template;\n            function template() {\n                return String(obj);\n            }\n        },\n        defer: function(fn) {\n            setTimeout(fn, 0);\n        },\n        debounce: function(func, wait, immediate) {\n            var timeout, result;\n            return function() {\n                var context = this, args = arguments, later, callNow;\n                later = function() {\n                    timeout = null;\n                    if (!immediate) {\n                        result = func.apply(context, args);\n                    }\n                };\n                callNow = immediate && !timeout;\n                clearTimeout(timeout);\n                timeout = setTimeout(later, wait);\n                if (callNow) {\n                    result = func.apply(context, args);\n                }\n                return result;\n            };\n        },\n        throttle: function(func, wait) {\n            var context, args, timeout, result, previous, later;\n            previous = 0;\n            later = function() {\n                previous = new Date();\n                timeout = null;\n                result = func.apply(context, args);\n            };\n            return function() {\n                var now = new Date(), remaining = wait - (now - previous);\n                context = this;\n                args = arguments;\n                if (remaining <= 0) {\n                    clearTimeout(timeout);\n                    timeout = null;\n                    previous = now;\n                    result = func.apply(context, args);\n                } else if (!timeout) {\n                    timeout = setTimeout(later, remaining);\n                }\n                return result;\n            };\n        },\n        noop: function() {}\n    };\n    var VERSION = \"0.10.2\";\n    var tokenizers = function(root) {\n        return {\n            nonword: nonword,\n            whitespace: whitespace,\n            obj: {\n                nonword: getObjTokenizer(nonword),\n                whitespace: getObjTokenizer(whitespace)\n            }\n        };\n        function whitespace(s) {\n            return s.split(/\\s+/);\n        }\n        function nonword(s) {\n            return s.split(/\\W+/);\n        }\n        function getObjTokenizer(tokenizer) {\n            return function setKey(key) {\n                return function tokenize(o) {\n                    return tokenizer(o[key]);\n                };\n            };\n        }\n    }();\n    var LruCache = function() {\n        function LruCache(maxSize) {\n            this.maxSize = maxSize || 100;\n            this.size = 0;\n            this.hash = {};\n            this.list = new List();\n        }\n        _.mixin(LruCache.prototype, {\n            set: function set(key, val) {\n                var tailItem = this.list.tail, node;\n                if (this.size >= this.maxSize) {\n                    this.list.remove(tailItem);\n                    delete this.hash[tailItem.key];\n                }\n                if (node = this.hash[key]) {\n                    node.val = val;\n                    this.list.moveToFront(node);\n                } else {\n                    node = new Node(key, val);\n                    this.list.add(node);\n                    this.hash[key] = node;\n                    this.size++;\n                }\n            },\n            get: function get(key) {\n                var node = this.hash[key];\n                if (node) {\n                    this.list.moveToFront(node);\n                    return node.val;\n                }\n            }\n        });\n        function List() {\n            this.head = this.tail = null;\n        }\n        _.mixin(List.prototype, {\n            add: function add(node) {\n                if (this.head) {\n                    node.next = this.head;\n                    this.head.prev = node;\n                }\n                this.head = node;\n                this.tail = this.tail || node;\n            },\n            remove: function remove(node) {\n                node.prev ? node.prev.next = node.next : this.head = node.next;\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\n            },\n            moveToFront: function(node) {\n                this.remove(node);\n                this.add(node);\n            }\n        });\n        function Node(key, val) {\n            this.key = key;\n            this.val = val;\n            this.prev = this.next = null;\n        }\n        return LruCache;\n    }();\n    var PersistentStorage = function() {\n        var ls, methods;\n        try {\n            ls = window.localStorage;\n            ls.setItem(\"~~~\", \"!\");\n            ls.removeItem(\"~~~\");\n        } catch (err) {\n            ls = null;\n        }\n        function PersistentStorage(namespace) {\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\n            this.ttlKey = \"__ttl__\";\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\n        }\n        if (ls && window.JSON) {\n            methods = {\n                _prefix: function(key) {\n                    return this.prefix + key;\n                },\n                _ttlKey: function(key) {\n                    return this._prefix(key) + this.ttlKey;\n                },\n                get: function(key) {\n                    if (this.isExpired(key)) {\n                        this.remove(key);\n                    }\n                    return decode(ls.getItem(this._prefix(key)));\n                },\n                set: function(key, val, ttl) {\n                    if (_.isNumber(ttl)) {\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\n                    } else {\n                        ls.removeItem(this._ttlKey(key));\n                    }\n                    return ls.setItem(this._prefix(key), encode(val));\n                },\n                remove: function(key) {\n                    ls.removeItem(this._ttlKey(key));\n                    ls.removeItem(this._prefix(key));\n                    return this;\n                },\n                clear: function() {\n                    var i, key, keys = [], len = ls.length;\n                    for (i = 0; i < len; i++) {\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\n                            keys.push(key.replace(this.keyMatcher, \"\"));\n                        }\n                    }\n                    for (i = keys.length; i--; ) {\n                        this.remove(keys[i]);\n                    }\n                    return this;\n                },\n                isExpired: function(key) {\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\n                }\n            };\n        } else {\n            methods = {\n                get: _.noop,\n                set: _.noop,\n                remove: _.noop,\n                clear: _.noop,\n                isExpired: _.noop\n            };\n        }\n        _.mixin(PersistentStorage.prototype, methods);\n        return PersistentStorage;\n        function now() {\n            return new Date().getTime();\n        }\n        function encode(val) {\n            return JSON.stringify(_.isUndefined(val) ? null : val);\n        }\n        function decode(val) {\n            return JSON.parse(val);\n        }\n    }();\n    var Transport = function() {\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\n        function Transport(o) {\n            o = o || {};\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\n        }\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\n            maxPendingRequests = num;\n        };\n        Transport.resetCache = function clearCache() {\n            requestCache = new LruCache(10);\n        };\n        _.mixin(Transport.prototype, {\n            _get: function(url, o, cb) {\n                var that = this, jqXhr;\n                if (jqXhr = pendingRequests[url]) {\n                    jqXhr.done(done).fail(fail);\n                } else if (pendingRequestsCount < maxPendingRequests) {\n                    pendingRequestsCount++;\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\n                } else {\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\n                }\n                function done(resp) {\n                    cb && cb(null, resp);\n                    requestCache.set(url, resp);\n                }\n                function fail() {\n                    cb && cb(true);\n                }\n                function always() {\n                    pendingRequestsCount--;\n                    delete pendingRequests[url];\n                    if (that.onDeckRequestArgs) {\n                        that._get.apply(that, that.onDeckRequestArgs);\n                        that.onDeckRequestArgs = null;\n                    }\n                }\n            },\n            get: function(url, o, cb) {\n                var resp;\n                if (_.isFunction(o)) {\n                    cb = o;\n                    o = {};\n                }\n                if (resp = requestCache.get(url)) {\n                    _.defer(function() {\n                        cb && cb(null, resp);\n                    });\n                } else {\n                    this._get(url, o, cb);\n                }\n                return !!resp;\n            }\n        });\n        return Transport;\n        function callbackToDeferred(fn) {\n            return function customSendWrapper(url, o) {\n                var deferred = $.Deferred();\n                fn(url, o, onSuccess, onError);\n                return deferred;\n                function onSuccess(resp) {\n                    _.defer(function() {\n                        deferred.resolve(resp);\n                    });\n                }\n                function onError(err) {\n                    _.defer(function() {\n                        deferred.reject(err);\n                    });\n                }\n            };\n        }\n    }();\n    var SearchIndex = function() {\n        function SearchIndex(o) {\n            o = o || {};\n            if (!o.datumTokenizer || !o.queryTokenizer) {\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\n            }\n            this.datumTokenizer = o.datumTokenizer;\n            this.queryTokenizer = o.queryTokenizer;\n            this.reset();\n        }\n        _.mixin(SearchIndex.prototype, {\n            bootstrap: function bootstrap(o) {\n                this.datums = o.datums;\n                this.trie = o.trie;\n            },\n            add: function(data) {\n                var that = this;\n                data = _.isArray(data) ? data : [ data ];\n                _.each(data, function(datum) {\n                    var id, tokens;\n                    id = that.datums.push(datum) - 1;\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\n                    _.each(tokens, function(token) {\n                        var node, chars, ch;\n                        node = that.trie;\n                        chars = token.split(\"\");\n                        while (ch = chars.shift()) {\n                            node = node.children[ch] || (node.children[ch] = newNode());\n                            node.ids.push(id);\n                        }\n                    });\n                });\n            },\n            get: function get(query) {\n                var that = this, tokens, matches;\n                tokens = normalizeTokens(this.queryTokenizer(query));\n                _.each(tokens, function(token) {\n                    var node, chars, ch, ids;\n                    if (matches && matches.length === 0) {\n                        return false;\n                    }\n                    node = that.trie;\n                    chars = token.split(\"\");\n                    while (node && (ch = chars.shift())) {\n                        node = node.children[ch];\n                    }\n                    if (node && chars.length === 0) {\n                        ids = node.ids.slice(0);\n                        matches = matches ? getIntersection(matches, ids) : ids;\n                    } else {\n                        matches = [];\n                        return false;\n                    }\n                });\n                return matches ? _.map(unique(matches), function(id) {\n                    return that.datums[id];\n                }) : [];\n            },\n            reset: function reset() {\n                this.datums = [];\n                this.trie = newNode();\n            },\n            serialize: function serialize() {\n                return {\n                    datums: this.datums,\n                    trie: this.trie\n                };\n            }\n        });\n        return SearchIndex;\n        function normalizeTokens(tokens) {\n            tokens = _.filter(tokens, function(token) {\n                return !!token;\n            });\n            tokens = _.map(tokens, function(token) {\n                return token.toLowerCase();\n            });\n            return tokens;\n        }\n        function newNode() {\n            return {\n                ids: [],\n                children: {}\n            };\n        }\n        function unique(array) {\n            var seen = {}, uniques = [];\n            for (var i = 0; i < array.length; i++) {\n                if (!seen[array[i]]) {\n                    seen[array[i]] = true;\n                    uniques.push(array[i]);\n                }\n            }\n            return uniques;\n        }\n        function getIntersection(arrayA, arrayB) {\n            var ai = 0, bi = 0, intersection = [];\n            arrayA = arrayA.sort(compare);\n            arrayB = arrayB.sort(compare);\n            while (ai < arrayA.length && bi < arrayB.length) {\n                if (arrayA[ai] < arrayB[bi]) {\n                    ai++;\n                } else if (arrayA[ai] > arrayB[bi]) {\n                    bi++;\n                } else {\n                    intersection.push(arrayA[ai]);\n                    ai++;\n                    bi++;\n                }\n            }\n            return intersection;\n            function compare(a, b) {\n                return a - b;\n            }\n        }\n    }();\n    var oParser = function() {\n        return {\n            local: getLocal,\n            prefetch: getPrefetch,\n            remote: getRemote\n        };\n        function getLocal(o) {\n            return o.local || null;\n        }\n        function getPrefetch(o) {\n            var prefetch, defaults;\n            defaults = {\n                url: null,\n                thumbprint: \"\",\n                ttl: 24 * 60 * 60 * 1e3,\n                filter: null,\n                ajax: {}\n            };\n            if (prefetch = o.prefetch || null) {\n                prefetch = _.isString(prefetch) ? {\n                    url: prefetch\n                } : prefetch;\n                prefetch = _.mixin(defaults, prefetch);\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\n            }\n            return prefetch;\n        }\n        function getRemote(o) {\n            var remote, defaults;\n            defaults = {\n                url: null,\n                wildcard: \"%QUERY\",\n                replace: null,\n                rateLimitBy: \"debounce\",\n                rateLimitWait: 300,\n                send: null,\n                filter: null,\n                ajax: {}\n            };\n            if (remote = o.remote || null) {\n                remote = _.isString(remote) ? {\n                    url: remote\n                } : remote;\n                remote = _.mixin(defaults, remote);\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\n                remote.ajax.type = remote.ajax.type || \"GET\";\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\n                delete remote.rateLimitBy;\n                delete remote.rateLimitWait;\n                !remote.url && $.error(\"remote requires url to be set\");\n            }\n            return remote;\n            function byDebounce(wait) {\n                return function(fn) {\n                    return _.debounce(fn, wait);\n                };\n            }\n            function byThrottle(wait) {\n                return function(fn) {\n                    return _.throttle(fn, wait);\n                };\n            }\n        }\n    }();\n    (function(root) {\n        var old, keys;\n        old = root.Bloodhound;\n        keys = {\n            data: \"data\",\n            protocol: \"protocol\",\n            thumbprint: \"thumbprint\"\n        };\n        root.Bloodhound = Bloodhound;\n        function Bloodhound(o) {\n            if (!o || !o.local && !o.prefetch && !o.remote) {\n                $.error(\"one of local, prefetch, or remote is required\");\n            }\n            this.limit = o.limit || 5;\n            this.sorter = getSorter(o.sorter);\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\n            this.local = oParser.local(o);\n            this.prefetch = oParser.prefetch(o);\n            this.remote = oParser.remote(o);\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\n            this.index = new SearchIndex({\n                datumTokenizer: o.datumTokenizer,\n                queryTokenizer: o.queryTokenizer\n            });\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\n        }\n        Bloodhound.noConflict = function noConflict() {\n            root.Bloodhound = old;\n            return Bloodhound;\n        };\n        Bloodhound.tokenizers = tokenizers;\n        _.mixin(Bloodhound.prototype, {\n            _loadPrefetch: function loadPrefetch(o) {\n                var that = this, serialized, deferred;\n                if (serialized = this._readFromStorage(o.thumbprint)) {\n                    this.index.bootstrap(serialized);\n                    deferred = $.Deferred().resolve();\n                } else {\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\n                }\n                return deferred;\n                function handlePrefetchResponse(resp) {\n                    that.clear();\n                    that.add(o.filter ? o.filter(resp) : resp);\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\n                }\n            },\n            _getFromRemote: function getFromRemote(query, cb) {\n                var that = this, url, uriEncodedQuery;\n                query = query || \"\";\n                uriEncodedQuery = encodeURIComponent(query);\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\n                function handleRemoteResponse(err, resp) {\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\n                }\n            },\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\n                if (this.storage) {\n                    this.storage.set(keys.data, data, ttl);\n                    this.storage.set(keys.protocol, location.protocol, ttl);\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\n                }\n            },\n            _readFromStorage: function readFromStorage(thumbprint) {\n                var stored = {}, isExpired;\n                if (this.storage) {\n                    stored.data = this.storage.get(keys.data);\n                    stored.protocol = this.storage.get(keys.protocol);\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\n                }\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\n                return stored.data && !isExpired ? stored.data : null;\n            },\n            _initialize: function initialize() {\n                var that = this, local = this.local, deferred;\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\n                local && deferred.done(addLocalToIndex);\n                this.transport = this.remote ? new Transport(this.remote) : null;\n                return this.initPromise = deferred.promise();\n                function addLocalToIndex() {\n                    that.add(_.isFunction(local) ? local() : local);\n                }\n            },\n            initialize: function initialize(force) {\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\n            },\n            add: function add(data) {\n                this.index.add(data);\n            },\n            get: function get(query, cb) {\n                var that = this, matches = [], cacheHit = false;\n                matches = this.index.get(query);\n                matches = this.sorter(matches).slice(0, this.limit);\n                if (matches.length < this.limit && this.transport) {\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\n                }\n                if (!cacheHit) {\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\n                }\n                function returnRemoteMatches(remoteMatches) {\n                    var matchesWithBackfill = matches.slice(0);\n                    _.each(remoteMatches, function(remoteMatch) {\n                        var isDuplicate;\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\n                            return that.dupDetector(remoteMatch, match);\n                        });\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\n                        return matchesWithBackfill.length < that.limit;\n                    });\n                    cb && cb(that.sorter(matchesWithBackfill));\n                }\n            },\n            clear: function clear() {\n                this.index.reset();\n            },\n            clearPrefetchCache: function clearPrefetchCache() {\n                this.storage && this.storage.clear();\n            },\n            clearRemoteCache: function clearRemoteCache() {\n                this.transport && Transport.resetCache();\n            },\n            ttAdapter: function ttAdapter() {\n                return _.bind(this.get, this);\n            }\n        });\n        return Bloodhound;\n        function getSorter(sortFn) {\n            return _.isFunction(sortFn) ? sort : noSort;\n            function sort(array) {\n                return array.sort(sortFn);\n            }\n            function noSort(array) {\n                return array;\n            }\n        }\n        function ignoreDuplicates() {\n            return false;\n        }\n    })(this);\n    var html = {\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\n        suggestions: '<span class=\"tt-suggestions\"></span>',\n        suggestion: '<div class=\"tt-suggestion\"></div>'\n    };\n    var css = {\n        wrapper: {\n            position: \"relative\",\n            display: \"inline-block\"\n        },\n        hint: {\n            position: \"absolute\",\n            top: \"0\",\n            left: \"0\",\n            borderColor: \"transparent\",\n            boxShadow: \"none\"\n        },\n        input: {\n            position: \"relative\",\n            verticalAlign: \"top\",\n            backgroundColor: \"transparent\"\n        },\n        inputWithNoHint: {\n            position: \"relative\",\n            verticalAlign: \"top\"\n        },\n        dropdown: {\n            position: \"absolute\",\n            top: \"100%\",\n            left: \"0\",\n            zIndex: \"100\",\n            display: \"none\"\n        },\n        suggestions: {\n            display: \"block\"\n        },\n        suggestion: {\n            whiteSpace: \"nowrap\",\n            cursor: \"pointer\"\n        },\n        suggestionChild: {\n            whiteSpace: \"normal\"\n        },\n        ltr: {\n            left: \"0\",\n            right: \"auto\"\n        },\n        rtl: {\n            left: \"auto\",\n            right: \" 0\"\n        }\n    };\n    if (_.isMsie()) {\n        _.mixin(css.input, {\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\n        });\n    }\n    if (_.isMsie() && _.isMsie() <= 7) {\n        _.mixin(css.input, {\n            marginTop: \"-1px\"\n        });\n    }\n    var EventBus = function() {\n        var namespace = \"typeahead:\";\n        function EventBus(o) {\n            if (!o || !o.el) {\n                $.error(\"EventBus initialized without el\");\n            }\n            this.$el = $(o.el);\n        }\n        _.mixin(EventBus.prototype, {\n            trigger: function(type) {\n                var args = [].slice.call(arguments, 1);\n                this.$el.trigger(namespace + type, args);\n            }\n        });\n        return EventBus;\n    }();\n    var EventEmitter = function() {\n        var splitter = /\\s+/, nextTick = getNextTick();\n        return {\n            onSync: onSync,\n            onAsync: onAsync,\n            off: off,\n            trigger: trigger\n        };\n        function on(method, types, cb, context) {\n            var type;\n            if (!cb) {\n                return this;\n            }\n            types = types.split(splitter);\n            cb = context ? bindContext(cb, context) : cb;\n            this._callbacks = this._callbacks || {};\n            while (type = types.shift()) {\n                this._callbacks[type] = this._callbacks[type] || {\n                    sync: [],\n                    async: []\n                };\n                this._callbacks[type][method].push(cb);\n            }\n            return this;\n        }\n        function onAsync(types, cb, context) {\n            return on.call(this, \"async\", types, cb, context);\n        }\n        function onSync(types, cb, context) {\n            return on.call(this, \"sync\", types, cb, context);\n        }\n        function off(types) {\n            var type;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            while (type = types.shift()) {\n                delete this._callbacks[type];\n            }\n            return this;\n        }\n        function trigger(types) {\n            var type, callbacks, args, syncFlush, asyncFlush;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            args = [].slice.call(arguments, 1);\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\n                syncFlush() && nextTick(asyncFlush);\n            }\n            return this;\n        }\n        function getFlush(callbacks, context, args) {\n            return flush;\n            function flush() {\n                var cancelled;\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\n                    cancelled = callbacks[i].apply(context, args) === false;\n                }\n                return !cancelled;\n            }\n        }\n        function getNextTick() {\n            var nextTickFn;\n            if (window.setImmediate) {\n                nextTickFn = function nextTickSetImmediate(fn) {\n                    setImmediate(function() {\n                        fn();\n                    });\n                };\n            } else {\n                nextTickFn = function nextTickSetTimeout(fn) {\n                    setTimeout(function() {\n                        fn();\n                    }, 0);\n                };\n            }\n            return nextTickFn;\n        }\n        function bindContext(fn, context) {\n            return fn.bind ? fn.bind(context) : function() {\n                fn.apply(context, [].slice.call(arguments, 0));\n            };\n        }\n    }();\n    var highlight = function(doc) {\n        var defaults = {\n            node: null,\n            pattern: null,\n            tagName: \"strong\",\n            className: null,\n            wordsOnly: false,\n            caseSensitive: false\n        };\n        return function hightlight(o) {\n            var regex;\n            o = _.mixin({}, defaults, o);\n            if (!o.node || !o.pattern) {\n                return;\n            }\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\n            traverse(o.node, hightlightTextNode);\n            function hightlightTextNode(textNode) {\n                var match, patternNode;\n                if (match = regex.exec(textNode.data)) {\n                    wrapperNode = doc.createElement(o.tagName);\n                    o.className && (wrapperNode.className = o.className);\n                    patternNode = textNode.splitText(match.index);\n                    patternNode.splitText(match[0].length);\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\n                }\n                return !!match;\n            }\n            function traverse(el, hightlightTextNode) {\n                var childNode, TEXT_NODE_TYPE = 3;\n                for (var i = 0; i < el.childNodes.length; i++) {\n                    childNode = el.childNodes[i];\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\n                        i += hightlightTextNode(childNode) ? 1 : 0;\n                    } else {\n                        traverse(childNode, hightlightTextNode);\n                    }\n                }\n            }\n        };\n        function getRegex(patterns, caseSensitive, wordsOnly) {\n            var escapedPatterns = [], regexStr;\n            for (var i = 0; i < patterns.length; i++) {\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\n            }\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\n        }\n    }(window.document);\n    var Input = function() {\n        var specialKeyCodeMap;\n        specialKeyCodeMap = {\n            9: \"tab\",\n            27: \"esc\",\n            37: \"left\",\n            39: \"right\",\n            13: \"enter\",\n            38: \"up\",\n            40: \"down\"\n        };\n        function Input(o) {\n            var that = this, onBlur, onFocus, onKeydown, onInput;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"input is missing\");\n            }\n            onBlur = _.bind(this._onBlur, this);\n            onFocus = _.bind(this._onFocus, this);\n            onKeydown = _.bind(this._onKeydown, this);\n            onInput = _.bind(this._onInput, this);\n            this.$hint = $(o.hint);\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\n            if (this.$hint.length === 0) {\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\n            }\n            if (!_.isMsie()) {\n                this.$input.on(\"input.tt\", onInput);\n            } else {\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\n                        return;\n                    }\n                    _.defer(_.bind(that._onInput, that, $e));\n                });\n            }\n            this.query = this.$input.val();\n            this.$overflowHelper = buildOverflowHelper(this.$input);\n        }\n        Input.normalizeQuery = function(str) {\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\n        };\n        _.mixin(Input.prototype, EventEmitter, {\n            _onBlur: function onBlur() {\n                this.resetInputValue();\n                this.trigger(\"blurred\");\n            },\n            _onFocus: function onFocus() {\n                this.trigger(\"focused\");\n            },\n            _onKeydown: function onKeydown($e) {\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\n                this._managePreventDefault(keyName, $e);\n                if (keyName && this._shouldTrigger(keyName, $e)) {\n                    this.trigger(keyName + \"Keyed\", $e);\n                }\n            },\n            _onInput: function onInput() {\n                this._checkInputValue();\n            },\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\n                var preventDefault, hintValue, inputValue;\n                switch (keyName) {\n                  case \"tab\":\n                    hintValue = this.getHint();\n                    inputValue = this.getInputValue();\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\n                    break;\n\n                  case \"up\":\n                  case \"down\":\n                    preventDefault = !withModifier($e);\n                    break;\n\n                  default:\n                    preventDefault = false;\n                }\n                preventDefault && $e.preventDefault();\n            },\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\n                var trigger;\n                switch (keyName) {\n                  case \"tab\":\n                    trigger = !withModifier($e);\n                    break;\n\n                  default:\n                    trigger = true;\n                }\n                return trigger;\n            },\n            _checkInputValue: function checkInputValue() {\n                var inputValue, areEquivalent, hasDifferentWhitespace;\n                inputValue = this.getInputValue();\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\n                if (!areEquivalent) {\n                    this.trigger(\"queryChanged\", this.query = inputValue);\n                } else if (hasDifferentWhitespace) {\n                    this.trigger(\"whitespaceChanged\", this.query);\n                }\n            },\n            focus: function focus() {\n                this.$input.focus();\n            },\n            blur: function blur() {\n                this.$input.blur();\n            },\n            getQuery: function getQuery() {\n                return this.query;\n            },\n            setQuery: function setQuery(query) {\n                this.query = query;\n            },\n            getInputValue: function getInputValue() {\n                return this.$input.val();\n            },\n            setInputValue: function setInputValue(value, silent) {\n                this.$input.val(value);\n                silent ? this.clearHint() : this._checkInputValue();\n            },\n            resetInputValue: function resetInputValue() {\n                this.setInputValue(this.query, true);\n            },\n            getHint: function getHint() {\n                return this.$hint.val();\n            },\n            setHint: function setHint(value) {\n                this.$hint.val(value);\n            },\n            clearHint: function clearHint() {\n                this.setHint(\"\");\n            },\n            clearHintIfInvalid: function clearHintIfInvalid() {\n                var val, hint, valIsPrefixOfHint, isValid;\n                val = this.getInputValue();\n                hint = this.getHint();\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\n                !isValid && this.clearHint();\n            },\n            getLanguageDirection: function getLanguageDirection() {\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\n            },\n            hasOverflow: function hasOverflow() {\n                var constraint = this.$input.width() - 2;\n                this.$overflowHelper.text(this.getInputValue());\n                return this.$overflowHelper.width() >= constraint;\n            },\n            isCursorAtEnd: function() {\n                var valueLength, selectionStart, range;\n                valueLength = this.$input.val().length;\n                selectionStart = this.$input[0].selectionStart;\n                if (_.isNumber(selectionStart)) {\n                    return selectionStart === valueLength;\n                } else if (document.selection) {\n                    range = document.selection.createRange();\n                    range.moveStart(\"character\", -valueLength);\n                    return valueLength === range.text.length;\n                }\n                return true;\n            },\n            destroy: function destroy() {\n                this.$hint.off(\".tt\");\n                this.$input.off(\".tt\");\n                this.$hint = this.$input = this.$overflowHelper = null;\n            }\n        });\n        return Input;\n        function buildOverflowHelper($input) {\n            return $('<pre aria-hidden=\"true\"></pre>').css({\n                position: \"absolute\",\n                visibility: \"hidden\",\n                whiteSpace: \"pre\",\n                fontFamily: $input.css(\"font-family\"),\n                fontSize: $input.css(\"font-size\"),\n                fontStyle: $input.css(\"font-style\"),\n                fontVariant: $input.css(\"font-variant\"),\n                fontWeight: $input.css(\"font-weight\"),\n                wordSpacing: $input.css(\"word-spacing\"),\n                letterSpacing: $input.css(\"letter-spacing\"),\n                textIndent: $input.css(\"text-indent\"),\n                textRendering: $input.css(\"text-rendering\"),\n                textTransform: $input.css(\"text-transform\")\n            }).insertAfter($input);\n        }\n        function areQueriesEquivalent(a, b) {\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\n        }\n        function withModifier($e) {\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\n        }\n    }();\n    var Dataset = function() {\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\n        function Dataset(o) {\n            o = o || {};\n            o.templates = o.templates || {};\n            if (!o.source) {\n                $.error(\"missing source\");\n            }\n            if (o.name && !isValidName(o.name)) {\n                $.error(\"invalid dataset name: \" + o.name);\n            }\n            this.query = null;\n            this.highlight = !!o.highlight;\n            this.name = o.name || _.getUniqueId();\n            this.source = o.source;\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\n            this.templates = getTemplates(o.templates, this.displayFn);\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\n        }\n        Dataset.extractDatasetName = function extractDatasetName(el) {\n            return $(el).data(datasetKey);\n        };\n        Dataset.extractValue = function extractDatum(el) {\n            return $(el).data(valueKey);\n        };\n        Dataset.extractDatum = function extractDatum(el) {\n            return $(el).data(datumKey);\n        };\n        _.mixin(Dataset.prototype, EventEmitter, {\n            _render: function render(query, suggestions) {\n                if (!this.$el) {\n                    return;\n                }\n                var that = this, hasSuggestions;\n                this.$el.empty();\n                hasSuggestions = suggestions && suggestions.length;\n                if (!hasSuggestions && this.templates.empty) {\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                } else if (hasSuggestions) {\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                }\n                this.trigger(\"rendered\");\n                function getEmptyHtml() {\n                    return that.templates.empty({\n                        query: query,\n                        isEmpty: true\n                    });\n                }\n                function getSuggestionsHtml() {\n                    var $suggestions, nodes;\n                    $suggestions = $(html.suggestions).css(css.suggestions);\n                    nodes = _.map(suggestions, getSuggestionNode);\n                    $suggestions.append.apply($suggestions, nodes);\n                    that.highlight && highlight({\n                        node: $suggestions[0],\n                        pattern: query\n                    });\n                    return $suggestions;\n                    function getSuggestionNode(suggestion) {\n                        var $el;\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\n                        $el.children().each(function() {\n                            $(this).css(css.suggestionChild);\n                        });\n                        return $el;\n                    }\n                }\n                function getHeaderHtml() {\n                    return that.templates.header({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n                function getFooterHtml() {\n                    return that.templates.footer({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n            },\n            getRoot: function getRoot() {\n                return this.$el;\n            },\n            update: function update(query) {\n                var that = this;\n                this.query = query;\n                this.canceled = false;\n                this.source(query, render);\n                function render(suggestions) {\n                    if (!that.canceled && query === that.query) {\n                        that._render(query, suggestions);\n                    }\n                }\n            },\n            cancel: function cancel() {\n                this.canceled = true;\n            },\n            clear: function clear() {\n                this.cancel();\n                this.$el.empty();\n                this.trigger(\"rendered\");\n            },\n            isEmpty: function isEmpty() {\n                return this.$el.is(\":empty\");\n            },\n            destroy: function destroy() {\n                this.$el = null;\n            }\n        });\n        return Dataset;\n        function getDisplayFn(display) {\n            display = display || \"value\";\n            return _.isFunction(display) ? display : displayFn;\n            function displayFn(obj) {\n                return obj[display];\n            }\n        }\n        function getTemplates(templates, displayFn) {\n            return {\n                empty: templates.empty && _.templatify(templates.empty),\n                header: templates.header && _.templatify(templates.header),\n                footer: templates.footer && _.templatify(templates.footer),\n                suggestion: templates.suggestion || suggestionTemplate\n            };\n            function suggestionTemplate(context) {\n                return \"<p>\" + displayFn(context) + \"</p>\";\n            }\n        }\n        function isValidName(str) {\n            return /^[_a-zA-Z0-9-]+$/.test(str);\n        }\n    }();\n    var Dropdown = function() {\n        function Dropdown(o) {\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\n            o = o || {};\n            if (!o.menu) {\n                $.error(\"menu is required\");\n            }\n            this.isOpen = false;\n            this.isEmpty = true;\n            this.datasets = _.map(o.datasets, initializeDataset);\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\n            _.each(this.datasets, function(dataset) {\n                that.$menu.append(dataset.getRoot());\n                dataset.onSync(\"rendered\", that._onRendered, that);\n            });\n        }\n        _.mixin(Dropdown.prototype, EventEmitter, {\n            _onSuggestionClick: function onSuggestionClick($e) {\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\n            },\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\n                this._removeCursor();\n                this._setCursor($($e.currentTarget), true);\n            },\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\n                this._removeCursor();\n            },\n            _onRendered: function onRendered() {\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\n                this.trigger(\"datasetRendered\");\n                function isDatasetEmpty(dataset) {\n                    return dataset.isEmpty();\n                }\n            },\n            _hide: function() {\n                this.$menu.hide();\n            },\n            _show: function() {\n                this.$menu.css(\"display\", \"block\");\n            },\n            _getSuggestions: function getSuggestions() {\n                return this.$menu.find(\".tt-suggestion\");\n            },\n            _getCursor: function getCursor() {\n                return this.$menu.find(\".tt-cursor\").first();\n            },\n            _setCursor: function setCursor($el, silent) {\n                $el.first().addClass(\"tt-cursor\");\n                !silent && this.trigger(\"cursorMoved\");\n            },\n            _removeCursor: function removeCursor() {\n                this._getCursor().removeClass(\"tt-cursor\");\n            },\n            _moveCursor: function moveCursor(increment) {\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\n                if (!this.isOpen) {\n                    return;\n                }\n                $oldCursor = this._getCursor();\n                $suggestions = this._getSuggestions();\n                this._removeCursor();\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\n                if (newCursorIndex === -1) {\n                    this.trigger(\"cursorRemoved\");\n                    return;\n                } else if (newCursorIndex < -1) {\n                    newCursorIndex = $suggestions.length - 1;\n                }\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\n                this._ensureVisible($newCursor);\n            },\n            _ensureVisible: function ensureVisible($el) {\n                var elTop, elBottom, menuScrollTop, menuHeight;\n                elTop = $el.position().top;\n                elBottom = elTop + $el.outerHeight(true);\n                menuScrollTop = this.$menu.scrollTop();\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\n                if (elTop < 0) {\n                    this.$menu.scrollTop(menuScrollTop + elTop);\n                } else if (menuHeight < elBottom) {\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\n                }\n            },\n            close: function close() {\n                if (this.isOpen) {\n                    this.isOpen = false;\n                    this._removeCursor();\n                    this._hide();\n                    this.trigger(\"closed\");\n                }\n            },\n            open: function open() {\n                if (!this.isOpen) {\n                    this.isOpen = true;\n                    !this.isEmpty && this._show();\n                    this.trigger(\"opened\");\n                }\n            },\n            setLanguageDirection: function setLanguageDirection(dir) {\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\n            },\n            moveCursorUp: function moveCursorUp() {\n                this._moveCursor(-1);\n            },\n            moveCursorDown: function moveCursorDown() {\n                this._moveCursor(+1);\n            },\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\n                var datum = null;\n                if ($el.length) {\n                    datum = {\n                        raw: Dataset.extractDatum($el),\n                        value: Dataset.extractValue($el),\n                        datasetName: Dataset.extractDatasetName($el)\n                    };\n                }\n                return datum;\n            },\n            getDatumForCursor: function getDatumForCursor() {\n                return this.getDatumForSuggestion(this._getCursor().first());\n            },\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\n                return this.getDatumForSuggestion(this._getSuggestions().first());\n            },\n            update: function update(query) {\n                _.each(this.datasets, updateDataset);\n                function updateDataset(dataset) {\n                    dataset.update(query);\n                }\n            },\n            empty: function empty() {\n                _.each(this.datasets, clearDataset);\n                this.isEmpty = true;\n                function clearDataset(dataset) {\n                    dataset.clear();\n                }\n            },\n            isVisible: function isVisible() {\n                return this.isOpen && !this.isEmpty;\n            },\n            destroy: function destroy() {\n                this.$menu.off(\".tt\");\n                this.$menu = null;\n                _.each(this.datasets, destroyDataset);\n                function destroyDataset(dataset) {\n                    dataset.destroy();\n                }\n            }\n        });\n        return Dropdown;\n        function initializeDataset(oDataset) {\n            return new Dataset(oDataset);\n        }\n    }();\n    var Typeahead = function() {\n        var attrsKey = \"ttAttrs\";\n        function Typeahead(o) {\n            var $menu, $input, $hint;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"missing input\");\n            }\n            this.isActivated = false;\n            this.autoselect = !!o.autoselect;\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\n            this.$node = buildDomStructure(o.input, o.withHint);\n            $menu = this.$node.find(\".tt-dropdown-menu\");\n            $input = this.$node.find(\".tt-input\");\n            $hint = this.$node.find(\".tt-hint\");\n            $input.on(\"blur.tt\", function($e) {\n                var active, isActive, hasActive;\n                active = document.activeElement;\n                isActive = $menu.is(active);\n                hasActive = $menu.has(active).length > 0;\n                if (_.isMsie() && (isActive || hasActive)) {\n                    $e.preventDefault();\n                    $e.stopImmediatePropagation();\n                    _.defer(function() {\n                        $input.focus();\n                    });\n                }\n            });\n            $menu.on(\"mousedown.tt\", function($e) {\n                $e.preventDefault();\n            });\n            this.eventBus = o.eventBus || new EventBus({\n                el: $input\n            });\n            this.dropdown = new Dropdown({\n                menu: $menu,\n                datasets: o.datasets\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\n            this.input = new Input({\n                input: $input,\n                hint: $hint\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\n            this._setLanguageDirection();\n        }\n        _.mixin(Typeahead.prototype, {\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\n                var datum;\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\n                    this._select(datum);\n                }\n            },\n            _onCursorMoved: function onCursorMoved() {\n                var datum = this.dropdown.getDatumForCursor();\n                this.input.setInputValue(datum.value, true);\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\n            },\n            _onCursorRemoved: function onCursorRemoved() {\n                this.input.resetInputValue();\n                this._updateHint();\n            },\n            _onDatasetRendered: function onDatasetRendered() {\n                this._updateHint();\n            },\n            _onOpened: function onOpened() {\n                this._updateHint();\n                this.eventBus.trigger(\"opened\");\n            },\n            _onClosed: function onClosed() {\n                this.input.clearHint();\n                this.eventBus.trigger(\"closed\");\n            },\n            _onFocused: function onFocused() {\n                this.isActivated = true;\n                this.dropdown.open();\n            },\n            _onBlurred: function onBlurred() {\n                this.isActivated = false;\n                this.dropdown.empty();\n                this.dropdown.close();\n                this.setVal(\"\", true); //LM\n            },\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\n                var cursorDatum, topSuggestionDatum;\n                cursorDatum = this.dropdown.getDatumForCursor();\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\n                if (cursorDatum) {\n                    this._select(cursorDatum);\n                    $e.preventDefault();\n                } else if (this.autoselect && topSuggestionDatum) {\n                    this._select(topSuggestionDatum);\n                    $e.preventDefault();\n                }\n            },\n            _onTabKeyed: function onTabKeyed(type, $e) {\n                var datum;\n                if (datum = this.dropdown.getDatumForCursor()) {\n                    this._select(datum);\n                    $e.preventDefault();\n                } else {\n                    this._autocomplete(true);\n                }\n            },\n            _onEscKeyed: function onEscKeyed() {\n                this.dropdown.close();\n                this.input.resetInputValue();\n            },\n            _onUpKeyed: function onUpKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\n                this.dropdown.open();\n            },\n            _onDownKeyed: function onDownKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\n                this.dropdown.open();\n            },\n            _onLeftKeyed: function onLeftKeyed() {\n                this.dir === \"rtl\" && this._autocomplete();\n            },\n            _onRightKeyed: function onRightKeyed() {\n                this.dir === \"ltr\" && this._autocomplete();\n            },\n            _onQueryChanged: function onQueryChanged(e, query) {\n                this.input.clearHintIfInvalid();\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\n                this.dropdown.open();\n                this._setLanguageDirection();\n            },\n            _onWhitespaceChanged: function onWhitespaceChanged() {\n                this._updateHint();\n                this.dropdown.open();\n            },\n            _setLanguageDirection: function setLanguageDirection() {\n                var dir;\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\n                    this.dir = dir;\n                    this.$node.css(\"direction\", dir);\n                    this.dropdown.setLanguageDirection(dir);\n                }\n            },\n            _updateHint: function updateHint() {\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\n                datum = this.dropdown.getDatumForTopSuggestion();\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\n                    val = this.input.getInputValue();\n                    query = Input.normalizeQuery(val);\n                    escapedQuery = _.escapeRegExChars(query);\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\n                    match = frontMatchRegEx.exec(datum.value);\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\n                } else {\n                    this.input.clearHint();\n                }\n            },\n            _autocomplete: function autocomplete(laxCursor) {\n                var hint, query, isCursorAtEnd, datum;\n                hint = this.input.getHint();\n                query = this.input.getQuery();\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\n                if (hint && query !== hint && isCursorAtEnd) {\n                    datum = this.dropdown.getDatumForTopSuggestion();\n                    datum && this.input.setInputValue(datum.value);\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\n                }\n            },\n            _select: function select(datum) {\n                this.input.setQuery(datum.value);\n                this.input.setInputValue(datum.value, true);\n                this._setLanguageDirection();\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\n                this.dropdown.close();\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\n            },\n            open: function open() {\n                this.dropdown.open();\n            },\n            close: function close() {\n                this.dropdown.close();\n            },\n            setVal: function setVal(val) {\n                if (this.isActivated) {\n                    this.input.setInputValue(val);\n                } else {\n                    this.input.setQuery(val);\n                    this.input.setInputValue(val, true);\n                }\n                this._setLanguageDirection();\n            },\n            getVal: function getVal() {\n                return this.input.getQuery();\n            },\n            destroy: function destroy() {\n                this.input.destroy();\n                this.dropdown.destroy();\n                destroyDomStructure(this.$node);\n                this.$node = null;\n            }\n        });\n        return Typeahead;\n        function buildDomStructure(input, withHint) {\n            var $input, $wrapper, $dropdown, $hint;\n            $input = $(input);\n            $wrapper = $(html.wrapper).css(css.wrapper);\n            $dropdown = $(html.dropdown).css(css.dropdown);\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\n                autocomplete: \"off\",\n                spellcheck: \"false\"\n            });\n            $input.data(attrsKey, {\n                dir: $input.attr(\"dir\"),\n                autocomplete: $input.attr(\"autocomplete\"),\n                spellcheck: $input.attr(\"spellcheck\"),\n                style: $input.attr(\"style\")\n            });\n            $input.addClass(\"tt-input\").attr({\n                autocomplete: \"off\",\n                spellcheck: false\n            }).css(withHint ? css.input : css.inputWithNoHint);\n            try {\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\n            } catch (e) {}\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\n        }\n        function getBackgroundStyles($el) {\n            return {\n                backgroundAttachment: $el.css(\"background-attachment\"),\n                backgroundClip: $el.css(\"background-clip\"),\n                backgroundColor: $el.css(\"background-color\"),\n                backgroundImage: $el.css(\"background-image\"),\n                backgroundOrigin: $el.css(\"background-origin\"),\n                backgroundPosition: $el.css(\"background-position\"),\n                backgroundRepeat: $el.css(\"background-repeat\"),\n                backgroundSize: $el.css(\"background-size\")\n            };\n        }\n        function destroyDomStructure($node) {\n            var $input = $node.find(\".tt-input\");\n            _.each($input.data(attrsKey), function(val, key) {\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\n            });\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\n            $node.remove();\n        }\n    }();\n    (function() {\n        var old, typeaheadKey, methods;\n        old = $.fn.typeahead;\n        typeaheadKey = \"ttTypeahead\";\n        methods = {\n            initialize: function initialize(o, datasets) {\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\n                o = o || {};\n                return this.each(attach);\n                function attach() {\n                    var $input = $(this), eventBus, typeahead;\n                    _.each(datasets, function(d) {\n                        d.highlight = !!o.highlight;\n                    });\n                    typeahead = new Typeahead({\n                        input: $input,\n                        eventBus: eventBus = new EventBus({\n                            el: $input\n                        }),\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\n                        minLength: o.minLength,\n                        autoselect: o.autoselect,\n                        datasets: datasets\n                    });\n                    $input.data(typeaheadKey, typeahead);\n                }\n            },\n            open: function open() {\n                return this.each(openTypeahead);\n                function openTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.open();\n                    }\n                }\n            },\n            close: function close() {\n                return this.each(closeTypeahead);\n                function closeTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.close();\n                    }\n                }\n            },\n            val: function val(newVal) {\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\n                function setVal() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.setVal(newVal);\n                    }\n                }\n                function getVal($input) {\n                    var typeahead, query;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        query = typeahead.getVal();\n                    }\n                    return query;\n                }\n            },\n            destroy: function destroy() {\n                return this.each(unattach);\n                function unattach() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.destroy();\n                        $input.removeData(typeaheadKey);\n                    }\n                }\n            }\n        };\n        $.fn.typeahead = function(method) {\n            if (methods[method]) {\n                return methods[method].apply(this, [].slice.call(arguments, 1));\n            } else {\n                return methods.initialize.apply(this, arguments);\n            }\n        };\n        $.fn.typeahead.noConflict = function noConflict() {\n            $.fn.typeahead = old;\n            return this;\n        };\n    })();\n    \n    \n    \n//})(window.jQuery);\n\n\n});\n",
        -    "define('searchView',[\n  'App',\n  // Templates\n  'text!tpl/search.html',\n  'text!tpl/search_suggestion.html',\n  // Tools\n  'typeahead'\n], function(App, searchTpl, suggestionTpl) {\n\n  var searchView = Backbone.View.extend({\n    el: '#search',\n    /**\n     * Init.\n     */\n    init: function() {\n      var tpl = _.template(searchTpl);\n      var className = 'form-control input-lg';\n      var placeholder = 'Search reference';\n      this.searchHtml = tpl({\n        'placeholder': placeholder,\n        'className': className\n      });\n      this.items = App.classes.concat(App.allItems);\n\n      return this;\n    },\n    /**\n     * Render input field with Typehead activated.\n     */\n    render: function() {\n      // Append the view to the dom\n      this.$el.append(this.searchHtml);\n\n      // Render Typeahead\n      var $searchInput = this.$el.find('input[type=text]');\n      this.typeaheadRender($searchInput);\n      this.typeaheadEvents($searchInput);\n\n      return this;\n    },\n    /**\n     * Apply Twitter Typeahead to the search input field.\n     * @param {jquery} $input\n     */\n    typeaheadRender: function($input) {\n      var self = this;\n      $input.typeahead(null, {\n        'displayKey': 'name',\n        'minLength': 2,\n        //'highlight': true,\n        'source': self.substringMatcher(this.items),\n        'templates': {\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\n          'suggestion': _.template(suggestionTpl)\n        }\n      });\n    },\n    /**\n     * Setup typeahead custom events (item selected).\n     */\n    typeaheadEvents: function($input) {\n      var self = this;\n      $input.on('typeahead:selected', function(e, item, datasetName) {\n        var selectedItem = self.items[item.idx];\n        select(selectedItem);\n      });\n      $input.on('keydown', function(e) {\n        if (e.which === 13) { // enter\n          var txt = $input.val();\n          var f = _.find(self.items, function(it) { return it.name == txt; });\n          if (f) {\n            select(f);\n          }\n        } else if (e.which === 27) {\n          $input.blur();\n        }\n      });\n\n      function select(selectedItem) {\n        var hash = App.router.getHash(selectedItem);//\n        App.router.navigate(hash, {'trigger': true});\n        $('#item').focus();\n      }\n    },\n    /**\n     * substringMatcher function for Typehead (search for strings in an array).\n     * @param {array} array\n     * @returns {Function}\n     */\n    substringMatcher: function(array) {\n      return function findMatches(query, callback) {\n        var matches = [], substrRegex, arrayLength = array.length;\n\n        // regex used to determine if a string contains the substring `query`\n        substrRegex = new RegExp(query, 'i');\n\n        // iterate through the pool of strings and for any string that\n        // contains the substring `query`, add it to the `matches` array\n        for (var i=0; i < arrayLength; i++) {\n          var item = array[i];\n          if (substrRegex.test(item.name)) {\n            // typeahead expects suggestions to be a js object\n            matches.push({\n              'itemtype': item.itemtype,\n              'name': item.name,\n              'className': item.class,\n              'is_constructor': !!item.is_constructor,\n              'final': item.final,\n              'idx': i\n            });\n          }\n        }\n\n        callback(matches);\n      };\n    }\n\n  });\n\n  return searchView;\n\n});\n\n",
        -    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\n  <div class=\"reference-group clearfix main-ref-page\">  \\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\n      <div class=\"reference-subgroup\">\\n        <% if (subgroup.name !== \\'0\\') { %>\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\n        <% } %>\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\n        <% _.each(subgroup.items, function(item) { %>\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\n        <% }); %>\\n        </ul>\\n      </div>\\n    <% }); %>\\n    </div>\\n  </div>\\n<% }); %>\\n';});\n\n",
        -    "define('listView',[\n  'App',\n  // Templates\n  'text!tpl/list.html'\n], function (App, listTpl) {\n  var striptags = function(html) {\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.textContent;\n  };\n\n  var listView = Backbone.View.extend({\n    el: '#list',\n    events: {},\n    /**\n     * Init.\n     */\n    init: function () {\n      this.listTpl = _.template(listTpl);\n\n      return this;\n    },\n    /**\n     * Render the list.\n     */\n    render: function (items, listCollection) {\n      if (items && listCollection) {\n        var self = this;\n\n        // Render items and group them by module\n        // module === group\n        this.groups = {};\n        _.each(items, function (item, i) {\n\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n\n            var group = item.module || '_';\n            var subgroup = item.submodule || '_';\n            if (group === subgroup) {\n              subgroup = '0';\n            }\n            var hash = App.router.getHash(item);\n\n            // Create a group list\n            if (!self.groups[group]) {\n              self.groups[group] = {\n                name: group.replace('_', '&nbsp;'),\n                subgroups: {}\n              };\n            }\n\n            // Create a subgroup list\n            if (!self.groups[group].subgroups[subgroup]) {\n              self.groups[group].subgroups[subgroup] = {\n                name: subgroup.replace('_', '&nbsp;'),\n                items: []\n              };\n            }\n\n            // hide the un-interesting constants\n            if (group === 'Constants' && !item.example)\n              return;\n\n            if (item.class === 'p5') {\n\n              self.groups[group].subgroups[subgroup].items.push(item);\n\n            } else {\n\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\n                function(i){ return i.name == item.class; });\n\n              if (!found) {\n\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\n                var ind = hash.lastIndexOf('/');\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\n                self.groups[group].subgroups[subgroup].items.push({\n                  name: item.class,\n                  hash: hash\n                });\n              }\n\n            }\n          }\n        });\n\n        // Put the <li> items html into the list <ul>\n        var listHtml = self.listTpl({\n          'striptags': striptags,\n          'title': self.capitalizeFirst(listCollection),\n          'groups': self.groups,\n          'listCollection': listCollection\n        });\n\n        // Render the view\n        this.$el.html(listHtml);\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Show a list of items.\n     * @param {array} items Array of item objects.\n     * @returns {object} This view.\n     */\n    show: function (listGroup) {\n      if (App[listGroup]) {\n        this.render(App[listGroup], listGroup);\n      }\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function (str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n\n\n\n  });\n\n  return listView;\n\n});\n\n",
        -    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\n\\n<% if (item.example) { %>\\n<div class=\"example\">\\n  <h3 id=\"reference-example\">Examples</h3>\\n\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\n    <% _.each(item.example, function(example, i){ %>\\n      <%= example %>\\n    <% }); %>\\n  </div>\\n</div>\\n<% } %>\\n\\n<div class=\"description\">\\n    \\n  <h3 id=\"reference-description\">Description</h3>\\n\\n  <% if (item.deprecated) { %>\\n    <p>\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n    </p>\\n  <% } %>\\n      \\n\\n  <span class=\\'description-text\\'><%= item.description %></span>\\n\\n  <% if (item.extends) { %>\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\n  <% } %>\\n\\n  <% if (item.module === \\'p5.sound\\') { %>\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\n    </p>\\n  <% } %>\\n\\n  <% if (item.constRefs) { %>\\n    <p>Used by:\\n  <%\\n      var refs = item.constRefs;\\n      for (var i = 0; i < refs.length; i ++) {\\n        var ref = refs[i];\\n        var name = ref;\\n        if (name.substr(0, 3) === \\'p5.\\') {\\n          name = name.substr(3);\\n        }\\n  if (i !== 0) {\\n          if (i == refs.length - 1) {\\n            %> and <%\\n          } else {\\n            %>, <%\\n          }\\n        }\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\n      }\\n  %>\\n    </p>\\n  <% } %>\\n</div>\\n\\n<% if (isConstructor || !isClass) { %>\\n\\n<div>\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\n  <p>\\n    <% syntaxes.forEach(function(syntax) { %>\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\n    <% }) %>\\n  </p>\\n</div>\\n\\n\\n<% if (item.params) { %>\\n  <div class=\"params\">\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\n    <% for (var i=0; i<item.params.length; i++) { %>\\n      <% var p = item.params[i] %>\\n      <li>\\n        <div class=\\'paramname\\'><%=p.name%></div>\\n        <% if (p.type) { %>\\n          <div class=\\'paramtype\\'>\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\n          <% if (p.optional) { %> (Optional)<% } %>\\n          </div>\\n        <% } %>\\n      </li>\\n    <% } %>\\n    </ul>\\n  </div>\\n<% } %>\\n\\n<% if (item.return && item.return.type) { %>\\n  <div>\\n    <h3 id=\"reference-returns\">Returns</h3>\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\n  </div>\\n<% } %>\\n\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n<div class=\"constructor\">\\n  <!--<h2>Constructor</h2>--> \\n  <%=constructor%>\\n</div>\\n<% } %>\\n\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n  <h4>Fields</h4>\\n  <p>\\n    <% _.each(fields, function(item) { %>\\n      <a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%></a>: <%= item.description %>\\n      <br>\\n    <% }); %>\\n  </p>\\n<% } %>\\n\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n  <h4>Methods</h4>\\n  <p>\\n    <table>\\n    <% _.each(methods, function(item) { %>\\n      <tr>\\n      <td><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></td><td><div class=\"method_description\"><%= item.description %></div></td>\\n      </tr>\\n    <% }); %>\\n    </table>\\n  </p>\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\n<br><br>\\n\\n<div>\\n<% if (item.file && item.line) { %>\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\n<% } %>\\n</div>\\n\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\n<br><br>\\n';});\n\n",
        -    "// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n * <p>\n * For a fairly comprehensive set of languages see the\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n * file that came with this source.  At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n * <p>\n * Usage: <ol>\n * <li> include this source file in an html page via\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\n * <li> define style rules.  See the example page for examples.\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n\ndefine(\"prettify\", function(){});\n\n",
        -    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function(App, itemTpl, classTpl, endTpl) {\n  'use strict';\n\n  var appVersion = App.project.version || 'master';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function() {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) {\n        syntax += 'new ';\n      } else if (cleanItem.static && cleanItem.class) {\n        syntax += cleanItem.class + '.';\n      }\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i = 0; i < cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) {\n              syntax += '[';\n            }\n            syntax += p.name;\n            if (p.optdefault) {\n              syntax += '=' + p.optdefault;\n            }\n            if (p.optional) {\n              syntax += ']';\n            }\n            if (i !== cleanItem.params.length - 1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function(item) {\n      if (item) {\n        var itemHtml = '';\n        var cleanItem = this.clean(item);\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\n        var collectionName = isClass\n            ? 'Constructor'\n            : this.capitalizeFirst(cleanItem.itemtype),\n          isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c) {\n            return c.name === cleanItem.name;\n          });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n        } else {\n          cleanItem.constRefs =\n            item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode(cleanItem.name);\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === 'method') {\n          App.pageView.appendToDocumentTitle(item.name + '()');\n        } else {\n          App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts)\n              .data('alt')\n              .split('\\n');\n\n            var canvases = $('.cnv_div');\n            for (var j = 0; j < alts.length; j++) {\n              if (j < canvases.length) {\n                $(canvases[j]).append(\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\n                );\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function(item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function(item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      $('#item').focus();\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function() {\n      this.$el.html(\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\n      );\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function(str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n});\n\n",
        -    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\n  <br>\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\n</div>\\n\\n<div id=\\'collection-list-categories\\'>\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\n<% var i=0; %>\\n<% var max=Math.floor(groups.length/4); %>\\n<% var rem=groups.length%4; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% var m = rem > 0 ? 1 : 0 %>\\n  <% if (i === 0) { %>\\n    <ul aria-labelledby=\"categories\">\\n    <% } %>\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\n    <% if (i === (max+m-1)) { %>\\n    </ul>\\n  \\t<% rem-- %>\\n  \\t<% i=0 %>\\n  <% } else { %>\\n  \\t<% i++ %>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define('menuView',[\n  'App',\n  'text!tpl/menu.html'\n], function(App, menuTpl) {\n\n  var menuView = Backbone.View.extend({\n    el: '#collection-list-nav',\n    /**\n     * Init.\n     * @returns {object} This view.\n     */\n    init: function() {\n      this.menuTpl = _.template(menuTpl);\n      return this;\n    },\n    /**\n     * Render.\n     * @returns {object} This view.\n     */\n    render: function() {\n\n      var groups = [];\n      _.each(App.modules, function (item, i) {\n        if (!item.is_submodule) {\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n            groups.push(item.name);\n          }\n        }\n        //}\n      });\n\n      // Sort groups by name A-Z\n      groups.sort();\n\n      var menuHtml = this.menuTpl({\n        'groups': groups\n      });\n\n      // Render the view\n      this.$el.html(menuHtml);\n    },\n\n    hide: function() {\n      this.$el.hide();\n    },\n\n    show: function() {\n      this.$el.show();\n    },\n\n    /**\n     * Update the menu.\n     * @param {string} el The name of the current route.\n     */\n    update: function(menuItem) {\n      //console.log(menuItem);\n      // this.$menuItems.removeClass('active');\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\n\n    }\n  });\n\n  return menuView;\n\n});\n\n",
        -    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\n\\n<p><%= module.description %></p>\\n\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\n\\n<% var t = 0; col = 0; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% if (t == 0) { %> \\n    <div class=\"column_<%=col%>\">\\n  <% } %>\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\n    <% if (group.hash) { %> </a> <% } %>\\n  <% } %>\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\n    <% t++; %>\\n  <% }); %>\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\n    </div>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define(\n  'libraryView',[\n    'App',\n    // Templates\n    'text!tpl/library.html'\n  ],\n  function(App, libraryTpl) {\n    var libraryView = Backbone.View.extend({\n      el: '#list',\n      events: {},\n      /**\n       * Init.\n       */\n      init: function() {\n        this.libraryTpl = _.template(libraryTpl);\n\n        return this;\n      },\n      /**\n       * Render the list.\n       */\n      render: function(m, listCollection) {\n        if (m && listCollection) {\n          var self = this;\n\n          // Render items and group them by module\n          // module === group\n          this.groups = {};\n          _.each(m.items, function(item, i) {\n            var module = item.module || '_';\n            var group;\n            // Override default group with a selected category\n            // TODO: Overwriting with the first category might not be the best choice\n            // We might also want to have links for categories\n            if (item.category && item.category[0]) {\n              group = item.category[0];\n              // Populate item.hash\n              App.router.getHash(item);\n\n              // Create a group list without link hash\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: undefined,\n                  items: []\n                };\n              }\n            } else {\n              group = item.class || '_';\n              var hash = App.router.getHash(item);\n\n              var ind = hash.lastIndexOf('/');\n              hash = hash.substring(0, ind);\n\n              // Create a group list\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: hash,\n                  items: []\n                };\n              }\n            }\n\n            self.groups[group].items.push(item);\n          });\n\n          // Sort groups by name A-Z\n          self.groups = _.sortBy(self.groups, this.sortByName);\n\n          // Put the <li> items html into the list <ul>\n          var libraryHtml = self.libraryTpl({\n            title: self.capitalizeFirst(listCollection),\n            module: m.module,\n            totalItems: m.items.length,\n            groups: self.groups\n          });\n\n          // Render the view\n          this.$el.html(libraryHtml);\n        }\n\n        return this;\n      },\n      /**\n       * Show a list of items.\n       * @param {array} items Array of item objects.\n       * @returns {object} This view.\n       */\n      show: function(listGroup) {\n        if (App[listGroup]) {\n          this.render(App[listGroup], listGroup);\n        }\n        App.pageView.hideContentViews();\n\n        this.$el.show();\n\n        return this;\n      },\n      /**\n       * Helper method to capitalize the first letter of a string\n       * @param {string} str\n       * @returns {string} Returns the string.\n       */\n      capitalizeFirst: function(str) {\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\n      },\n      /**\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\n       * @param {string} a\n       * @param {string} b\n       * @returns {Array} Returns an array with elements sorted from A to Z.\n       */\n      sortAZ: function(a, b) {\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\n      },\n\n      sortByName: function(a, b) {\n        if (a.name === 'p5') return -1;\n        else return 0;\n      }\n    });\n\n    return libraryView;\n  }\n);\n\n",
        -    "define('pageView',[\n  'App',\n\n  // Views\n  'searchView',\n  'listView',\n  'itemView',\n  'menuView',\n  'libraryView'\n], function(App, searchView, listView, itemView, menuView, libraryView) {\n\n  // Store the original title parts so we can substitue different endings.\n  var _originalDocumentTitle = window.document.title;\n\n  var pageView = Backbone.View.extend({\n    el: 'body',\n    /**\n     * Init.\n     */\n    init: function() {\n      App.$container = $('#container');\n      App.contentViews = [];\n\n      return this;\n    },\n    /**\n     * Render.\n     */\n    render: function() {\n\n      // Menu view\n      if (!App.menuView) {\n        App.menuView = new menuView();\n        App.menuView.init().render();\n      }\n\n      // Item view\n      if (!App.itemView) {\n        App.itemView = new itemView();\n        App.itemView.init().render();\n        // Add the item view to the views array\n        App.contentViews.push(App.itemView);\n      }\n\n      // List view\n      if (!App.listView) {\n        App.listView = new listView();\n        App.listView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.listView);\n      }\n\n      // Library view\n      if (!App.libraryView) {\n        App.libraryView = new libraryView();\n        App.libraryView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.libraryView);\n      }\n\n      // Search\n      if (!App.searchView) {\n        App.searchView = new searchView();\n        App.searchView.init().render();\n      }\n      return this;\n    },\n    /**\n     * Hide item and list views.\n     * @returns {object} This view.\n     */\n    hideContentViews: function() {\n      _.each(App.contentViews, function(view, i) {\n        view.$el.hide();\n      });\n\n      return this;\n    },\n    /**\n     * Append the supplied name to the first part of original document title.\n     * If no name is supplied, the title will reset to the original one.\n     */\n    appendToDocumentTitle: function(name){\n      if(name){\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\n        window.document.title = [firstTitlePart, name].join(\" | \");\n      } else {\n        window.document.title = _originalDocumentTitle;\n      }\n    }    \n  });\n\n  return pageView;\n\n});\n\n",
        -    "define('router',[\n  'App'\n], function(App) {\n\n  'use strict'; //\n\n  var Router = Backbone.Router.extend({\n\n    routes: {\n      '': 'list',\n      'p5': 'list',\n      'p5/': 'list',\n      'classes': 'list',\n      'search': 'search',\n      'libraries/:lib': 'library',\n      ':searchClass(/:searchItem)': 'get'\n    },\n    /**\n     * Whether the json API data was loaded.\n     */\n    _initialized: false,\n    /**\n     * Initialize the app: load json API data and create searchable arrays.\n     */\n    init: function(callback) {\n      var self = this;\n      require(['pageView'], function(pageView) {\n\n        // If already initialized, move away from here!\n        if (self._initialized) {\n          if (callback)\n            callback();\n          return;\n        }\n\n        // Update initialization state: must be done now to avoid recursive mess\n        self._initialized = true;\n\n        // Render views\n        if (!App.pageView) {\n          App.pageView = new pageView();\n          App.pageView.init().render();\n        }\n\n        // If a callback is set (a route has already been called), run it\n        // otherwise, show the default list\n        if (callback)\n          callback();\n        else\n          self.list();\n      });\n    },\n    /**\n     * Start route. Simply check if initialized.\n     */\n    start: function() {\n      this.init();\n    },\n    /**\n     * Show item details by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     */\n    get: function(searchClass, searchItem) {\n\n      // if looking for a library page, redirect\n      if (searchClass === 'p5.sound' && !searchItem) {\n        window.location.hash = '/libraries/'+searchClass;\n        return;\n      }\n\n      var self = this;\n      this.init(function() {\n        var item = self.getItem(searchClass, searchItem);\n\n        App.menuView.hide();\n\n        if (item) {\n          App.itemView.show(item);\n        } else {\n          //App.itemView.nothingFound();\n\n          self.list();\n        }\n\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Returns one item object by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     * @returns {object} The item found or undefined if nothing was found.\n     */\n    getItem: function(searchClass, searchItem) {\n      var classes = App.classes,\n              items = App.allItems,\n              classesCount = classes.length,\n              itemsCount = items.length,\n              className = searchClass ? searchClass.toLowerCase() : undefined,\n              itemName = searchItem ? searchItem : undefined,\n              found;\n\n      // Only search for a class, if itemName is undefined\n      if (className && !itemName) {\n        for (var i = 0; i < classesCount; i++) {\n          if (classes[i].name.toLowerCase() === className) {\n            found = classes[i];\n            _.each(found.items, function(i, idx) {\n              i.hash = App.router.getHash(i);\n            });\n            break;\n          }\n        }\n        // Search for a class item\n      } else if (className && itemName) {\n        // Search case sensitively\n        for (var i = 0; i < itemsCount; i++) {\n          if (items[i].class.toLowerCase() === className &&\n            items[i].name === itemName) {\n            found = items[i];\n            break;\n          }\n        }\n\n        // If no match was found, fallback to search case insensitively\n        if(!found){\n          for (var i = 0; i < itemsCount; i++) {\n            if(items[i].class.toLowerCase() === className &&\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\n              found = items[i];\n              break;\n            }\n          }\n        }\n      }\n\n      return found;\n    },\n    /**\n     * List items.\n     * @param {string} collection The name of the collection to list.\n     */\n    list: function(collection) {\n\n      collection = 'allItems';\n\n      // Make sure collection is valid\n      if (App.collections.indexOf(collection) < 0) {\n        return;\n      }\n\n      this.init(function() {\n        App.menuView.show(collection);\n        App.menuView.update(collection);\n        App.listView.show(collection);\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Display information for a library.\n     * @param {string} collection The name of the collection to list.\n     */\n    library: function(collection) {\n      this.init(function() {\n        App.menuView.hide();\n        App.libraryView.show(collection.substring(3)); //remove p5.\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Close all content views.\n     */\n    search: function() {\n      this.init(function() {\n        App.menuView.hide();\n        App.pageView.hideContentViews();\n      });\n    },\n\n    /**\n     * Create an hash/url for the item.\n     * @param {Object} item A class, method, property or event object.\n     * @returns {String} The hash string, including the '#'.\n     */\n     getHash: function(item) {\n\n       if (!item.hash) {\n\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\n\n         if (item.class) {\n           var clsFunc = '#/' + item.class + '.' + item.name;\n           var idx = clsFunc.lastIndexOf('.');\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\n         } else {\n          item.hash = '#/' + item.name;\n         }\n       }\n\n       return item.hash;\n    }\n  });\n\n  \n  function styleCodeLinks() {\n    var links = document.getElementsByTagName(\"a\");\n    for (var iLink = 0; iLink < links.length; iLink++) {\n      var link = links[iLink];\n      if (link.hash.startsWith('#/p5')) {\n        link.classList.add('code');\n      }\n    }\n  }\n\n\n  // Get the router\n  App.router = new Router();\n\n  // Start history\n  Backbone.history.start();\n\n  return App.router;\n\n});\n\n",
        -    "/**\n * Define global App.\n */\nvar App = window.App || {};\ndefine('App', [],function() {\n  return App;\n});\n\n/**\n * Load json API data and start the router.\n * @param {module} App\n * @param {module} router\n */\nrequire([\n  'App',\n  './documented-method'], function(App, DocumentedMethod) {\n\n  // Set collections\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];\n\n  // Get json API data\n  $.getJSON('data.min.json', function(data) {\n    App.data = data;\n    App.classes = [];\n    App.methods = [];\n    App.properties = [];\n    App.events = [];\n    App.allItems = [];\n    App.sound = { items: [] };\n    App.dom = { items: [] };\n    App.modules = [];\n    App.project = data.project;\n\n\n    var modules = data.modules;\n\n    // Get class items (methods, properties, events)\n    _.each(modules, function(m, idx, array) {\n      App.modules.push(m);\n      if (m.name == \"p5.sound\") {\n        App.sound.module = m;\n      }\n    });\n\n\n    var items = data.classitems;\n    var classes = data.classes;\n\n    // Get classes\n    _.each(classes, function(c, idx, array) {\n      if (!c.private) {\n        App.classes.push(c);\n      }\n    });\n\n\n    // Get class items (methods, properties, events)\n    _.each(items, function(el, idx, array) {\n      if (el.itemtype) {\n        if (el.itemtype === \"method\") {\n          el = new DocumentedMethod(el);\n          App.methods.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"property\") {\n          App.properties.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"event\") {\n          App.events.push(el);\n          App.allItems.push(el);\n        }\n\n        // libraries\n        if (el.module === \"p5.sound\") {\n          App.sound.items.push(el);\n        }\n      }\n    });\n\n    _.each(App.classes, function(c, idx) {\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\n    });\n\n    require(['router']);\n  });\n});\n\ndefine(\"main\", function(){});\n\n",
        +    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\r\n(function (root, factory) {\r\n  if (typeof define === 'function' && define.amd) {\r\n    define('documented-method',[], factory);\r\n  } else if (typeof module === 'object' && module.exports) {\r\n    module.exports = factory();\r\n  } else {\r\n    root.DocumentedMethod = factory();\r\n  }\r\n}(this, function () {\r\n  function extend(target, src) {\r\n    Object.keys(src).forEach(function(prop) {\r\n      target[prop] = src[prop];\r\n    });\r\n    return target;\r\n  }\r\n\r\n  function DocumentedMethod(classitem) {\r\n    extend(this, classitem);\r\n\r\n    if (this.overloads) {\r\n      // Make each overload inherit properties from their parent\r\n      // classitem.\r\n      this.overloads = this.overloads.map(function(overload) {\r\n        return extend(Object.create(this), overload);\r\n      }, this);\r\n\r\n      if (this.params) {\r\n        throw new Error('params for overloaded methods should be undefined');\r\n      }\r\n\r\n      this.params = this._getMergedParams();\r\n    }\r\n  }\r\n\r\n  DocumentedMethod.prototype = {\r\n    // Merge parameters across all overloaded versions of this item.\r\n    _getMergedParams: function() {\r\n      var paramNames = {};\r\n      var params = [];\r\n\r\n      this.overloads.forEach(function(overload) {\r\n        if (!overload.params) {\r\n          return;\r\n        }\r\n        overload.params.forEach(function(param) {\r\n          if (param.name in paramNames) {\r\n            return;\r\n          }\r\n          paramNames[param.name] = param;\r\n          params.push(param);\r\n        });\r\n      });\r\n\r\n      return params;\r\n    }\r\n  };\r\n\r\n  return DocumentedMethod;\r\n}));\r\n\n",
        +    "/**\r\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\r\n * Available via the MIT or new BSD license.\r\n * see: http://github.com/requirejs/text for details\r\n */\r\n/*jslint regexp: true */\r\n/*global require, XMLHttpRequest, ActiveXObject,\r\n  define, window, process, Packages,\r\n  java, location, Components, FileUtils */\r\n\r\ndefine('text',['module'], function (module) {\r\n    'use strict';\r\n\r\n    var text, fs, Cc, Ci, xpcIsWindows,\r\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\r\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\r\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\r\n        hasLocation = typeof location !== 'undefined' && location.href,\r\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\r\n        defaultHostName = hasLocation && location.hostname,\r\n        defaultPort = hasLocation && (location.port || undefined),\r\n        buildMap = {},\r\n        masterConfig = (module.config && module.config()) || {};\r\n\r\n    text = {\r\n        version: '2.0.10',\r\n\r\n        strip: function (content) {\r\n            //Strips <?xml ...?> declarations so that external SVG and XML\r\n            //documents can be added to a document without worry. Also, if the string\r\n            //is an HTML document, only the part inside the body tag is returned.\r\n            if (content) {\r\n                content = content.replace(xmlRegExp, \"\");\r\n                var matches = content.match(bodyRegExp);\r\n                if (matches) {\r\n                    content = matches[1];\r\n                }\r\n            } else {\r\n                content = \"\";\r\n            }\r\n            return content;\r\n        },\r\n\r\n        jsEscape: function (content) {\r\n            return content.replace(/(['\\\\])/g, '\\\\$1')\r\n                .replace(/[\\f]/g, \"\\\\f\")\r\n                .replace(/[\\b]/g, \"\\\\b\")\r\n                .replace(/[\\n]/g, \"\\\\n\")\r\n                .replace(/[\\t]/g, \"\\\\t\")\r\n                .replace(/[\\r]/g, \"\\\\r\")\r\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\r\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\r\n        },\r\n\r\n        createXhr: masterConfig.createXhr || function () {\r\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\r\n            var xhr, i, progId;\r\n            if (typeof XMLHttpRequest !== \"undefined\") {\r\n                return new XMLHttpRequest();\r\n            } else if (typeof ActiveXObject !== \"undefined\") {\r\n                for (i = 0; i < 3; i += 1) {\r\n                    progId = progIds[i];\r\n                    try {\r\n                        xhr = new ActiveXObject(progId);\r\n                    } catch (e) {}\r\n\r\n                    if (xhr) {\r\n                        progIds = [progId];  // so faster next time\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            return xhr;\r\n        },\r\n\r\n        /**\r\n         * Parses a resource name into its component parts. Resource names\r\n         * look like: module/name.ext!strip, where the !strip part is\r\n         * optional.\r\n         * @param {String} name the resource name\r\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\r\n         * where strip is a boolean.\r\n         */\r\n        parseName: function (name) {\r\n            var modName, ext, temp,\r\n                strip = false,\r\n                index = name.indexOf(\".\"),\r\n                isRelative = name.indexOf('./') === 0 ||\r\n                             name.indexOf('../') === 0;\r\n\r\n            if (index !== -1 && (!isRelative || index > 1)) {\r\n                modName = name.substring(0, index);\r\n                ext = name.substring(index + 1, name.length);\r\n            } else {\r\n                modName = name;\r\n            }\r\n\r\n            temp = ext || modName;\r\n            index = temp.indexOf(\"!\");\r\n            if (index !== -1) {\r\n                //Pull off the strip arg.\r\n                strip = temp.substring(index + 1) === \"strip\";\r\n                temp = temp.substring(0, index);\r\n                if (ext) {\r\n                    ext = temp;\r\n                } else {\r\n                    modName = temp;\r\n                }\r\n            }\r\n\r\n            return {\r\n                moduleName: modName,\r\n                ext: ext,\r\n                strip: strip\r\n            };\r\n        },\r\n\r\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\r\n\r\n        /**\r\n         * Is an URL on another domain. Only works for browser use, returns\r\n         * false in non-browser environments. Only used to know if an\r\n         * optimized .js version of a text resource should be loaded\r\n         * instead.\r\n         * @param {String} url\r\n         * @returns Boolean\r\n         */\r\n        useXhr: function (url, protocol, hostname, port) {\r\n            var uProtocol, uHostName, uPort,\r\n                match = text.xdRegExp.exec(url);\r\n            if (!match) {\r\n                return true;\r\n            }\r\n            uProtocol = match[2];\r\n            uHostName = match[3];\r\n\r\n            uHostName = uHostName.split(':');\r\n            uPort = uHostName[1];\r\n            uHostName = uHostName[0];\r\n\r\n            return (!uProtocol || uProtocol === protocol) &&\r\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\r\n                   ((!uPort && !uHostName) || uPort === port);\r\n        },\r\n\r\n        finishLoad: function (name, strip, content, onLoad) {\r\n            content = strip ? text.strip(content) : content;\r\n            if (masterConfig.isBuild) {\r\n                buildMap[name] = content;\r\n            }\r\n            onLoad(content);\r\n        },\r\n\r\n        load: function (name, req, onLoad, config) {\r\n            //Name has format: some.module.filext!strip\r\n            //The strip part is optional.\r\n            //if strip is present, then that means only get the string contents\r\n            //inside a body tag in an HTML string. For XML/SVG content it means\r\n            //removing the <?xml ...?> declarations so the content can be inserted\r\n            //into the current doc without problems.\r\n\r\n            // Do not bother with the work if a build and text will\r\n            // not be inlined.\r\n            if (config.isBuild && !config.inlineText) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            masterConfig.isBuild = config.isBuild;\r\n\r\n            var parsed = text.parseName(name),\r\n                nonStripName = parsed.moduleName +\r\n                    (parsed.ext ? '.' + parsed.ext : ''),\r\n                url = req.toUrl(nonStripName),\r\n                useXhr = (masterConfig.useXhr) ||\r\n                         text.useXhr;\r\n\r\n            // Do not load if it is an empty: url\r\n            if (url.indexOf('empty:') === 0) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            //Load the text. Use XHR if possible and in a browser.\r\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\r\n                text.get(url, function (content) {\r\n                    text.finishLoad(name, parsed.strip, content, onLoad);\r\n                }, function (err) {\r\n                    if (onLoad.error) {\r\n                        onLoad.error(err);\r\n                    }\r\n                });\r\n            } else {\r\n                //Need to fetch the resource across domains. Assume\r\n                //the resource has been optimized into a JS module. Fetch\r\n                //by the module name + extension, but do not include the\r\n                //!strip part to avoid file system issues.\r\n                req([nonStripName], function (content) {\r\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\r\n                                    parsed.strip, content, onLoad);\r\n                });\r\n            }\r\n        },\r\n\r\n        write: function (pluginName, moduleName, write, config) {\r\n            if (buildMap.hasOwnProperty(moduleName)) {\r\n                var content = text.jsEscape(buildMap[moduleName]);\r\n                write.asModule(pluginName + \"!\" + moduleName,\r\n                               \"define(function () { return '\" +\r\n                                   content +\r\n                               \"';});\\n\");\r\n            }\r\n        },\r\n\r\n        writeFile: function (pluginName, moduleName, req, write, config) {\r\n            var parsed = text.parseName(moduleName),\r\n                extPart = parsed.ext ? '.' + parsed.ext : '',\r\n                nonStripName = parsed.moduleName + extPart,\r\n                //Use a '.js' file name so that it indicates it is a\r\n                //script that can be loaded across domains.\r\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\r\n\r\n            //Leverage own load() method to load plugin value, but only\r\n            //write out values that do not have the strip argument,\r\n            //to avoid any potential issues with ! in file names.\r\n            text.load(nonStripName, req, function (value) {\r\n                //Use own write() method to construct full module value.\r\n                //But need to create shell that translates writeFile's\r\n                //write() to the right interface.\r\n                var textWrite = function (contents) {\r\n                    return write(fileName, contents);\r\n                };\r\n                textWrite.asModule = function (moduleName, contents) {\r\n                    return write.asModule(moduleName, fileName, contents);\r\n                };\r\n\r\n                text.write(pluginName, nonStripName, textWrite, config);\r\n            }, config);\r\n        }\r\n    };\r\n\r\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\r\n            typeof process !== \"undefined\" &&\r\n            process.versions &&\r\n            !!process.versions.node &&\r\n            !process.versions['node-webkit'])) {\r\n        //Using special require.nodeRequire, something added by r.js.\r\n        fs = require.nodeRequire('fs');\r\n\r\n        text.get = function (url, callback, errback) {\r\n            try {\r\n                var file = fs.readFileSync(url, 'utf8');\r\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\r\n                if (file.indexOf('\\uFEFF') === 0) {\r\n                    file = file.substring(1);\r\n                }\r\n                callback(file);\r\n            } catch (e) {\r\n                errback(e);\r\n            }\r\n        };\r\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\r\n            text.createXhr())) {\r\n        text.get = function (url, callback, errback, headers) {\r\n            var xhr = text.createXhr(), header;\r\n            xhr.open('GET', url, true);\r\n\r\n            //Allow plugins direct access to xhr headers\r\n            if (headers) {\r\n                for (header in headers) {\r\n                    if (headers.hasOwnProperty(header)) {\r\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Allow overrides specified in config\r\n            if (masterConfig.onXhr) {\r\n                masterConfig.onXhr(xhr, url);\r\n            }\r\n\r\n            xhr.onreadystatechange = function (evt) {\r\n                var status, err;\r\n                //Do not explicitly handle errors, those should be\r\n                //visible via console output in the browser.\r\n                if (xhr.readyState === 4) {\r\n                    status = xhr.status;\r\n                    if (status > 399 && status < 600) {\r\n                        //An http 4xx or 5xx error. Signal an error.\r\n                        err = new Error(url + ' HTTP status: ' + status);\r\n                        err.xhr = xhr;\r\n                        errback(err);\r\n                    } else {\r\n                        callback(xhr.responseText);\r\n                    }\r\n\r\n                    if (masterConfig.onXhrComplete) {\r\n                        masterConfig.onXhrComplete(xhr, url);\r\n                    }\r\n                }\r\n            };\r\n            xhr.send(null);\r\n        };\r\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\r\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\r\n        //Why Java, why is this so awkward?\r\n        text.get = function (url, callback) {\r\n            var stringBuffer, line,\r\n                encoding = \"utf-8\",\r\n                file = new java.io.File(url),\r\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\r\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\r\n                content = '';\r\n            try {\r\n                stringBuffer = new java.lang.StringBuffer();\r\n                line = input.readLine();\r\n\r\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\r\n                // http://www.unicode.org/faq/utf_bom.html\r\n\r\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\r\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\r\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\r\n                    // Eat the BOM, since we've already found the encoding on this file,\r\n                    // and we plan to concatenating this buffer with others; the BOM should\r\n                    // only appear at the top of a file.\r\n                    line = line.substring(1);\r\n                }\r\n\r\n                if (line !== null) {\r\n                    stringBuffer.append(line);\r\n                }\r\n\r\n                while ((line = input.readLine()) !== null) {\r\n                    stringBuffer.append(lineSeparator);\r\n                    stringBuffer.append(line);\r\n                }\r\n                //Make sure we return a JavaScript string and not a Java string.\r\n                content = String(stringBuffer.toString()); //String\r\n            } finally {\r\n                input.close();\r\n            }\r\n            callback(content);\r\n        };\r\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\r\n            typeof Components !== 'undefined' && Components.classes &&\r\n            Components.interfaces)) {\r\n        //Avert your gaze!\r\n        Cc = Components.classes,\r\n        Ci = Components.interfaces;\r\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\r\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\r\n\r\n        text.get = function (url, callback) {\r\n            var inStream, convertStream, fileObj,\r\n                readData = {};\r\n\r\n            if (xpcIsWindows) {\r\n                url = url.replace(/\\//g, '\\\\');\r\n            }\r\n\r\n            fileObj = new FileUtils.File(url);\r\n\r\n            //XPCOM, you so crazy\r\n            try {\r\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\r\n                           .createInstance(Ci.nsIFileInputStream);\r\n                inStream.init(fileObj, 1, 0, false);\r\n\r\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\r\n                                .createInstance(Ci.nsIConverterInputStream);\r\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\r\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\r\n\r\n                convertStream.readString(inStream.available(), readData);\r\n                convertStream.close();\r\n                inStream.close();\r\n                callback(readData.value);\r\n            } catch (e) {\r\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\r\n            }\r\n        };\r\n    }\r\n    return text;\r\n});\r\n\n",
        +    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\r\\n<form>\\r\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\r\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\r\\n</form>\\r\\n\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\r\\n\\r\\n  <strong><%=name%></strong>\\r\\n\\r\\n  <span class=\"small\">\\r\\n    <% if (final) { %>\\r\\n    constant\\r\\n    <% } else if (itemtype) { %>\\r\\n    <%=itemtype%> \\r\\n    <% } %>\\r\\n\\r\\n    <% if (className) { %>\\r\\n    in <strong><%=className%></strong>\\r\\n    <% } %>\\r\\n\\r\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\r\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\r\\n    <% } %>\\r\\n  </span>\\r\\n\\r\\n</p>';});\n\n",
        +    "/*!\r\n * typeahead.js 0.10.2\r\n * https://github.com/twitter/typeahead.js\r\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\r\n */\r\ndefine('typeahead',[], function() {\r\n\r\n//(function($) {\r\n\r\n\r\n    var _ = {\r\n        isMsie: function() {\r\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\r\n        },\r\n        isBlankString: function(str) {\r\n            return !str || /^\\s*$/.test(str);\r\n        },\r\n        escapeRegExChars: function(str) {\r\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\r\n        },\r\n        isString: function(obj) {\r\n            return typeof obj === \"string\";\r\n        },\r\n        isNumber: function(obj) {\r\n            return typeof obj === \"number\";\r\n        },\r\n        isArray: $.isArray,\r\n        isFunction: $.isFunction,\r\n        isObject: $.isPlainObject,\r\n        isUndefined: function(obj) {\r\n            return typeof obj === \"undefined\";\r\n        },\r\n        bind: $.proxy,\r\n        each: function(collection, cb) {\r\n            $.each(collection, reverseArgs);\r\n            function reverseArgs(index, value) {\r\n                return cb(value, index);\r\n            }\r\n        },\r\n        map: $.map,\r\n        filter: $.grep,\r\n        every: function(obj, test) {\r\n            var result = true;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (!(result = test.call(null, val, key, obj))) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        some: function(obj, test) {\r\n            var result = false;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (result = test.call(null, val, key, obj)) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        mixin: $.extend,\r\n        getUniqueId: function() {\r\n            var counter = 0;\r\n            return function() {\r\n                return counter++;\r\n            };\r\n        }(),\r\n        templatify: function templatify(obj) {\r\n            return $.isFunction(obj) ? obj : template;\r\n            function template() {\r\n                return String(obj);\r\n            }\r\n        },\r\n        defer: function(fn) {\r\n            setTimeout(fn, 0);\r\n        },\r\n        debounce: function(func, wait, immediate) {\r\n            var timeout, result;\r\n            return function() {\r\n                var context = this, args = arguments, later, callNow;\r\n                later = function() {\r\n                    timeout = null;\r\n                    if (!immediate) {\r\n                        result = func.apply(context, args);\r\n                    }\r\n                };\r\n                callNow = immediate && !timeout;\r\n                clearTimeout(timeout);\r\n                timeout = setTimeout(later, wait);\r\n                if (callNow) {\r\n                    result = func.apply(context, args);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        throttle: function(func, wait) {\r\n            var context, args, timeout, result, previous, later;\r\n            previous = 0;\r\n            later = function() {\r\n                previous = new Date();\r\n                timeout = null;\r\n                result = func.apply(context, args);\r\n            };\r\n            return function() {\r\n                var now = new Date(), remaining = wait - (now - previous);\r\n                context = this;\r\n                args = arguments;\r\n                if (remaining <= 0) {\r\n                    clearTimeout(timeout);\r\n                    timeout = null;\r\n                    previous = now;\r\n                    result = func.apply(context, args);\r\n                } else if (!timeout) {\r\n                    timeout = setTimeout(later, remaining);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        noop: function() {}\r\n    };\r\n    var VERSION = \"0.10.2\";\r\n    var tokenizers = function(root) {\r\n        return {\r\n            nonword: nonword,\r\n            whitespace: whitespace,\r\n            obj: {\r\n                nonword: getObjTokenizer(nonword),\r\n                whitespace: getObjTokenizer(whitespace)\r\n            }\r\n        };\r\n        function whitespace(s) {\r\n            return s.split(/\\s+/);\r\n        }\r\n        function nonword(s) {\r\n            return s.split(/\\W+/);\r\n        }\r\n        function getObjTokenizer(tokenizer) {\r\n            return function setKey(key) {\r\n                return function tokenize(o) {\r\n                    return tokenizer(o[key]);\r\n                };\r\n            };\r\n        }\r\n    }();\r\n    var LruCache = function() {\r\n        function LruCache(maxSize) {\r\n            this.maxSize = maxSize || 100;\r\n            this.size = 0;\r\n            this.hash = {};\r\n            this.list = new List();\r\n        }\r\n        _.mixin(LruCache.prototype, {\r\n            set: function set(key, val) {\r\n                var tailItem = this.list.tail, node;\r\n                if (this.size >= this.maxSize) {\r\n                    this.list.remove(tailItem);\r\n                    delete this.hash[tailItem.key];\r\n                }\r\n                if (node = this.hash[key]) {\r\n                    node.val = val;\r\n                    this.list.moveToFront(node);\r\n                } else {\r\n                    node = new Node(key, val);\r\n                    this.list.add(node);\r\n                    this.hash[key] = node;\r\n                    this.size++;\r\n                }\r\n            },\r\n            get: function get(key) {\r\n                var node = this.hash[key];\r\n                if (node) {\r\n                    this.list.moveToFront(node);\r\n                    return node.val;\r\n                }\r\n            }\r\n        });\r\n        function List() {\r\n            this.head = this.tail = null;\r\n        }\r\n        _.mixin(List.prototype, {\r\n            add: function add(node) {\r\n                if (this.head) {\r\n                    node.next = this.head;\r\n                    this.head.prev = node;\r\n                }\r\n                this.head = node;\r\n                this.tail = this.tail || node;\r\n            },\r\n            remove: function remove(node) {\r\n                node.prev ? node.prev.next = node.next : this.head = node.next;\r\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\r\n            },\r\n            moveToFront: function(node) {\r\n                this.remove(node);\r\n                this.add(node);\r\n            }\r\n        });\r\n        function Node(key, val) {\r\n            this.key = key;\r\n            this.val = val;\r\n            this.prev = this.next = null;\r\n        }\r\n        return LruCache;\r\n    }();\r\n    var PersistentStorage = function() {\r\n        var ls, methods;\r\n        try {\r\n            ls = window.localStorage;\r\n            ls.setItem(\"~~~\", \"!\");\r\n            ls.removeItem(\"~~~\");\r\n        } catch (err) {\r\n            ls = null;\r\n        }\r\n        function PersistentStorage(namespace) {\r\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\r\n            this.ttlKey = \"__ttl__\";\r\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\r\n        }\r\n        if (ls && window.JSON) {\r\n            methods = {\r\n                _prefix: function(key) {\r\n                    return this.prefix + key;\r\n                },\r\n                _ttlKey: function(key) {\r\n                    return this._prefix(key) + this.ttlKey;\r\n                },\r\n                get: function(key) {\r\n                    if (this.isExpired(key)) {\r\n                        this.remove(key);\r\n                    }\r\n                    return decode(ls.getItem(this._prefix(key)));\r\n                },\r\n                set: function(key, val, ttl) {\r\n                    if (_.isNumber(ttl)) {\r\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\r\n                    } else {\r\n                        ls.removeItem(this._ttlKey(key));\r\n                    }\r\n                    return ls.setItem(this._prefix(key), encode(val));\r\n                },\r\n                remove: function(key) {\r\n                    ls.removeItem(this._ttlKey(key));\r\n                    ls.removeItem(this._prefix(key));\r\n                    return this;\r\n                },\r\n                clear: function() {\r\n                    var i, key, keys = [], len = ls.length;\r\n                    for (i = 0; i < len; i++) {\r\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\r\n                            keys.push(key.replace(this.keyMatcher, \"\"));\r\n                        }\r\n                    }\r\n                    for (i = keys.length; i--; ) {\r\n                        this.remove(keys[i]);\r\n                    }\r\n                    return this;\r\n                },\r\n                isExpired: function(key) {\r\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\r\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\r\n                }\r\n            };\r\n        } else {\r\n            methods = {\r\n                get: _.noop,\r\n                set: _.noop,\r\n                remove: _.noop,\r\n                clear: _.noop,\r\n                isExpired: _.noop\r\n            };\r\n        }\r\n        _.mixin(PersistentStorage.prototype, methods);\r\n        return PersistentStorage;\r\n        function now() {\r\n            return new Date().getTime();\r\n        }\r\n        function encode(val) {\r\n            return JSON.stringify(_.isUndefined(val) ? null : val);\r\n        }\r\n        function decode(val) {\r\n            return JSON.parse(val);\r\n        }\r\n    }();\r\n    var Transport = function() {\r\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\r\n        function Transport(o) {\r\n            o = o || {};\r\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\r\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\r\n        }\r\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\r\n            maxPendingRequests = num;\r\n        };\r\n        Transport.resetCache = function clearCache() {\r\n            requestCache = new LruCache(10);\r\n        };\r\n        _.mixin(Transport.prototype, {\r\n            _get: function(url, o, cb) {\r\n                var that = this, jqXhr;\r\n                if (jqXhr = pendingRequests[url]) {\r\n                    jqXhr.done(done).fail(fail);\r\n                } else if (pendingRequestsCount < maxPendingRequests) {\r\n                    pendingRequestsCount++;\r\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\r\n                } else {\r\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\r\n                }\r\n                function done(resp) {\r\n                    cb && cb(null, resp);\r\n                    requestCache.set(url, resp);\r\n                }\r\n                function fail() {\r\n                    cb && cb(true);\r\n                }\r\n                function always() {\r\n                    pendingRequestsCount--;\r\n                    delete pendingRequests[url];\r\n                    if (that.onDeckRequestArgs) {\r\n                        that._get.apply(that, that.onDeckRequestArgs);\r\n                        that.onDeckRequestArgs = null;\r\n                    }\r\n                }\r\n            },\r\n            get: function(url, o, cb) {\r\n                var resp;\r\n                if (_.isFunction(o)) {\r\n                    cb = o;\r\n                    o = {};\r\n                }\r\n                if (resp = requestCache.get(url)) {\r\n                    _.defer(function() {\r\n                        cb && cb(null, resp);\r\n                    });\r\n                } else {\r\n                    this._get(url, o, cb);\r\n                }\r\n                return !!resp;\r\n            }\r\n        });\r\n        return Transport;\r\n        function callbackToDeferred(fn) {\r\n            return function customSendWrapper(url, o) {\r\n                var deferred = $.Deferred();\r\n                fn(url, o, onSuccess, onError);\r\n                return deferred;\r\n                function onSuccess(resp) {\r\n                    _.defer(function() {\r\n                        deferred.resolve(resp);\r\n                    });\r\n                }\r\n                function onError(err) {\r\n                    _.defer(function() {\r\n                        deferred.reject(err);\r\n                    });\r\n                }\r\n            };\r\n        }\r\n    }();\r\n    var SearchIndex = function() {\r\n        function SearchIndex(o) {\r\n            o = o || {};\r\n            if (!o.datumTokenizer || !o.queryTokenizer) {\r\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\r\n            }\r\n            this.datumTokenizer = o.datumTokenizer;\r\n            this.queryTokenizer = o.queryTokenizer;\r\n            this.reset();\r\n        }\r\n        _.mixin(SearchIndex.prototype, {\r\n            bootstrap: function bootstrap(o) {\r\n                this.datums = o.datums;\r\n                this.trie = o.trie;\r\n            },\r\n            add: function(data) {\r\n                var that = this;\r\n                data = _.isArray(data) ? data : [ data ];\r\n                _.each(data, function(datum) {\r\n                    var id, tokens;\r\n                    id = that.datums.push(datum) - 1;\r\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\r\n                    _.each(tokens, function(token) {\r\n                        var node, chars, ch;\r\n                        node = that.trie;\r\n                        chars = token.split(\"\");\r\n                        while (ch = chars.shift()) {\r\n                            node = node.children[ch] || (node.children[ch] = newNode());\r\n                            node.ids.push(id);\r\n                        }\r\n                    });\r\n                });\r\n            },\r\n            get: function get(query) {\r\n                var that = this, tokens, matches;\r\n                tokens = normalizeTokens(this.queryTokenizer(query));\r\n                _.each(tokens, function(token) {\r\n                    var node, chars, ch, ids;\r\n                    if (matches && matches.length === 0) {\r\n                        return false;\r\n                    }\r\n                    node = that.trie;\r\n                    chars = token.split(\"\");\r\n                    while (node && (ch = chars.shift())) {\r\n                        node = node.children[ch];\r\n                    }\r\n                    if (node && chars.length === 0) {\r\n                        ids = node.ids.slice(0);\r\n                        matches = matches ? getIntersection(matches, ids) : ids;\r\n                    } else {\r\n                        matches = [];\r\n                        return false;\r\n                    }\r\n                });\r\n                return matches ? _.map(unique(matches), function(id) {\r\n                    return that.datums[id];\r\n                }) : [];\r\n            },\r\n            reset: function reset() {\r\n                this.datums = [];\r\n                this.trie = newNode();\r\n            },\r\n            serialize: function serialize() {\r\n                return {\r\n                    datums: this.datums,\r\n                    trie: this.trie\r\n                };\r\n            }\r\n        });\r\n        return SearchIndex;\r\n        function normalizeTokens(tokens) {\r\n            tokens = _.filter(tokens, function(token) {\r\n                return !!token;\r\n            });\r\n            tokens = _.map(tokens, function(token) {\r\n                return token.toLowerCase();\r\n            });\r\n            return tokens;\r\n        }\r\n        function newNode() {\r\n            return {\r\n                ids: [],\r\n                children: {}\r\n            };\r\n        }\r\n        function unique(array) {\r\n            var seen = {}, uniques = [];\r\n            for (var i = 0; i < array.length; i++) {\r\n                if (!seen[array[i]]) {\r\n                    seen[array[i]] = true;\r\n                    uniques.push(array[i]);\r\n                }\r\n            }\r\n            return uniques;\r\n        }\r\n        function getIntersection(arrayA, arrayB) {\r\n            var ai = 0, bi = 0, intersection = [];\r\n            arrayA = arrayA.sort(compare);\r\n            arrayB = arrayB.sort(compare);\r\n            while (ai < arrayA.length && bi < arrayB.length) {\r\n                if (arrayA[ai] < arrayB[bi]) {\r\n                    ai++;\r\n                } else if (arrayA[ai] > arrayB[bi]) {\r\n                    bi++;\r\n                } else {\r\n                    intersection.push(arrayA[ai]);\r\n                    ai++;\r\n                    bi++;\r\n                }\r\n            }\r\n            return intersection;\r\n            function compare(a, b) {\r\n                return a - b;\r\n            }\r\n        }\r\n    }();\r\n    var oParser = function() {\r\n        return {\r\n            local: getLocal,\r\n            prefetch: getPrefetch,\r\n            remote: getRemote\r\n        };\r\n        function getLocal(o) {\r\n            return o.local || null;\r\n        }\r\n        function getPrefetch(o) {\r\n            var prefetch, defaults;\r\n            defaults = {\r\n                url: null,\r\n                thumbprint: \"\",\r\n                ttl: 24 * 60 * 60 * 1e3,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (prefetch = o.prefetch || null) {\r\n                prefetch = _.isString(prefetch) ? {\r\n                    url: prefetch\r\n                } : prefetch;\r\n                prefetch = _.mixin(defaults, prefetch);\r\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\r\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\r\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\r\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\r\n            }\r\n            return prefetch;\r\n        }\r\n        function getRemote(o) {\r\n            var remote, defaults;\r\n            defaults = {\r\n                url: null,\r\n                wildcard: \"%QUERY\",\r\n                replace: null,\r\n                rateLimitBy: \"debounce\",\r\n                rateLimitWait: 300,\r\n                send: null,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (remote = o.remote || null) {\r\n                remote = _.isString(remote) ? {\r\n                    url: remote\r\n                } : remote;\r\n                remote = _.mixin(defaults, remote);\r\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\r\n                remote.ajax.type = remote.ajax.type || \"GET\";\r\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\r\n                delete remote.rateLimitBy;\r\n                delete remote.rateLimitWait;\r\n                !remote.url && $.error(\"remote requires url to be set\");\r\n            }\r\n            return remote;\r\n            function byDebounce(wait) {\r\n                return function(fn) {\r\n                    return _.debounce(fn, wait);\r\n                };\r\n            }\r\n            function byThrottle(wait) {\r\n                return function(fn) {\r\n                    return _.throttle(fn, wait);\r\n                };\r\n            }\r\n        }\r\n    }();\r\n    (function(root) {\r\n        var old, keys;\r\n        old = root.Bloodhound;\r\n        keys = {\r\n            data: \"data\",\r\n            protocol: \"protocol\",\r\n            thumbprint: \"thumbprint\"\r\n        };\r\n        root.Bloodhound = Bloodhound;\r\n        function Bloodhound(o) {\r\n            if (!o || !o.local && !o.prefetch && !o.remote) {\r\n                $.error(\"one of local, prefetch, or remote is required\");\r\n            }\r\n            this.limit = o.limit || 5;\r\n            this.sorter = getSorter(o.sorter);\r\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\r\n            this.local = oParser.local(o);\r\n            this.prefetch = oParser.prefetch(o);\r\n            this.remote = oParser.remote(o);\r\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\r\n            this.index = new SearchIndex({\r\n                datumTokenizer: o.datumTokenizer,\r\n                queryTokenizer: o.queryTokenizer\r\n            });\r\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\r\n        }\r\n        Bloodhound.noConflict = function noConflict() {\r\n            root.Bloodhound = old;\r\n            return Bloodhound;\r\n        };\r\n        Bloodhound.tokenizers = tokenizers;\r\n        _.mixin(Bloodhound.prototype, {\r\n            _loadPrefetch: function loadPrefetch(o) {\r\n                var that = this, serialized, deferred;\r\n                if (serialized = this._readFromStorage(o.thumbprint)) {\r\n                    this.index.bootstrap(serialized);\r\n                    deferred = $.Deferred().resolve();\r\n                } else {\r\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\r\n                }\r\n                return deferred;\r\n                function handlePrefetchResponse(resp) {\r\n                    that.clear();\r\n                    that.add(o.filter ? o.filter(resp) : resp);\r\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\r\n                }\r\n            },\r\n            _getFromRemote: function getFromRemote(query, cb) {\r\n                var that = this, url, uriEncodedQuery;\r\n                query = query || \"\";\r\n                uriEncodedQuery = encodeURIComponent(query);\r\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\r\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\r\n                function handleRemoteResponse(err, resp) {\r\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\r\n                }\r\n            },\r\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\r\n                if (this.storage) {\r\n                    this.storage.set(keys.data, data, ttl);\r\n                    this.storage.set(keys.protocol, location.protocol, ttl);\r\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\r\n                }\r\n            },\r\n            _readFromStorage: function readFromStorage(thumbprint) {\r\n                var stored = {}, isExpired;\r\n                if (this.storage) {\r\n                    stored.data = this.storage.get(keys.data);\r\n                    stored.protocol = this.storage.get(keys.protocol);\r\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\r\n                }\r\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\r\n                return stored.data && !isExpired ? stored.data : null;\r\n            },\r\n            _initialize: function initialize() {\r\n                var that = this, local = this.local, deferred;\r\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\r\n                local && deferred.done(addLocalToIndex);\r\n                this.transport = this.remote ? new Transport(this.remote) : null;\r\n                return this.initPromise = deferred.promise();\r\n                function addLocalToIndex() {\r\n                    that.add(_.isFunction(local) ? local() : local);\r\n                }\r\n            },\r\n            initialize: function initialize(force) {\r\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\r\n            },\r\n            add: function add(data) {\r\n                this.index.add(data);\r\n            },\r\n            get: function get(query, cb) {\r\n                var that = this, matches = [], cacheHit = false;\r\n                matches = this.index.get(query);\r\n                matches = this.sorter(matches).slice(0, this.limit);\r\n                if (matches.length < this.limit && this.transport) {\r\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\r\n                }\r\n                if (!cacheHit) {\r\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\r\n                }\r\n                function returnRemoteMatches(remoteMatches) {\r\n                    var matchesWithBackfill = matches.slice(0);\r\n                    _.each(remoteMatches, function(remoteMatch) {\r\n                        var isDuplicate;\r\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\r\n                            return that.dupDetector(remoteMatch, match);\r\n                        });\r\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\r\n                        return matchesWithBackfill.length < that.limit;\r\n                    });\r\n                    cb && cb(that.sorter(matchesWithBackfill));\r\n                }\r\n            },\r\n            clear: function clear() {\r\n                this.index.reset();\r\n            },\r\n            clearPrefetchCache: function clearPrefetchCache() {\r\n                this.storage && this.storage.clear();\r\n            },\r\n            clearRemoteCache: function clearRemoteCache() {\r\n                this.transport && Transport.resetCache();\r\n            },\r\n            ttAdapter: function ttAdapter() {\r\n                return _.bind(this.get, this);\r\n            }\r\n        });\r\n        return Bloodhound;\r\n        function getSorter(sortFn) {\r\n            return _.isFunction(sortFn) ? sort : noSort;\r\n            function sort(array) {\r\n                return array.sort(sortFn);\r\n            }\r\n            function noSort(array) {\r\n                return array;\r\n            }\r\n        }\r\n        function ignoreDuplicates() {\r\n            return false;\r\n        }\r\n    })(this);\r\n    var html = {\r\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\r\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\r\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\r\n        suggestions: '<span class=\"tt-suggestions\"></span>',\r\n        suggestion: '<div class=\"tt-suggestion\"></div>'\r\n    };\r\n    var css = {\r\n        wrapper: {\r\n            position: \"relative\",\r\n            display: \"inline-block\"\r\n        },\r\n        hint: {\r\n            position: \"absolute\",\r\n            top: \"0\",\r\n            left: \"0\",\r\n            borderColor: \"transparent\",\r\n            boxShadow: \"none\"\r\n        },\r\n        input: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\",\r\n            backgroundColor: \"transparent\"\r\n        },\r\n        inputWithNoHint: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\"\r\n        },\r\n        dropdown: {\r\n            position: \"absolute\",\r\n            top: \"100%\",\r\n            left: \"0\",\r\n            zIndex: \"100\",\r\n            display: \"none\"\r\n        },\r\n        suggestions: {\r\n            display: \"block\"\r\n        },\r\n        suggestion: {\r\n            whiteSpace: \"nowrap\",\r\n            cursor: \"pointer\"\r\n        },\r\n        suggestionChild: {\r\n            whiteSpace: \"normal\"\r\n        },\r\n        ltr: {\r\n            left: \"0\",\r\n            right: \"auto\"\r\n        },\r\n        rtl: {\r\n            left: \"auto\",\r\n            right: \" 0\"\r\n        }\r\n    };\r\n    if (_.isMsie()) {\r\n        _.mixin(css.input, {\r\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\r\n        });\r\n    }\r\n    if (_.isMsie() && _.isMsie() <= 7) {\r\n        _.mixin(css.input, {\r\n            marginTop: \"-1px\"\r\n        });\r\n    }\r\n    var EventBus = function() {\r\n        var namespace = \"typeahead:\";\r\n        function EventBus(o) {\r\n            if (!o || !o.el) {\r\n                $.error(\"EventBus initialized without el\");\r\n            }\r\n            this.$el = $(o.el);\r\n        }\r\n        _.mixin(EventBus.prototype, {\r\n            trigger: function(type) {\r\n                var args = [].slice.call(arguments, 1);\r\n                this.$el.trigger(namespace + type, args);\r\n            }\r\n        });\r\n        return EventBus;\r\n    }();\r\n    var EventEmitter = function() {\r\n        var splitter = /\\s+/, nextTick = getNextTick();\r\n        return {\r\n            onSync: onSync,\r\n            onAsync: onAsync,\r\n            off: off,\r\n            trigger: trigger\r\n        };\r\n        function on(method, types, cb, context) {\r\n            var type;\r\n            if (!cb) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            cb = context ? bindContext(cb, context) : cb;\r\n            this._callbacks = this._callbacks || {};\r\n            while (type = types.shift()) {\r\n                this._callbacks[type] = this._callbacks[type] || {\r\n                    sync: [],\r\n                    async: []\r\n                };\r\n                this._callbacks[type][method].push(cb);\r\n            }\r\n            return this;\r\n        }\r\n        function onAsync(types, cb, context) {\r\n            return on.call(this, \"async\", types, cb, context);\r\n        }\r\n        function onSync(types, cb, context) {\r\n            return on.call(this, \"sync\", types, cb, context);\r\n        }\r\n        function off(types) {\r\n            var type;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            while (type = types.shift()) {\r\n                delete this._callbacks[type];\r\n            }\r\n            return this;\r\n        }\r\n        function trigger(types) {\r\n            var type, callbacks, args, syncFlush, asyncFlush;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            args = [].slice.call(arguments, 1);\r\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\r\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\r\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\r\n                syncFlush() && nextTick(asyncFlush);\r\n            }\r\n            return this;\r\n        }\r\n        function getFlush(callbacks, context, args) {\r\n            return flush;\r\n            function flush() {\r\n                var cancelled;\r\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\r\n                    cancelled = callbacks[i].apply(context, args) === false;\r\n                }\r\n                return !cancelled;\r\n            }\r\n        }\r\n        function getNextTick() {\r\n            var nextTickFn;\r\n            if (window.setImmediate) {\r\n                nextTickFn = function nextTickSetImmediate(fn) {\r\n                    setImmediate(function() {\r\n                        fn();\r\n                    });\r\n                };\r\n            } else {\r\n                nextTickFn = function nextTickSetTimeout(fn) {\r\n                    setTimeout(function() {\r\n                        fn();\r\n                    }, 0);\r\n                };\r\n            }\r\n            return nextTickFn;\r\n        }\r\n        function bindContext(fn, context) {\r\n            return fn.bind ? fn.bind(context) : function() {\r\n                fn.apply(context, [].slice.call(arguments, 0));\r\n            };\r\n        }\r\n    }();\r\n    var highlight = function(doc) {\r\n        var defaults = {\r\n            node: null,\r\n            pattern: null,\r\n            tagName: \"strong\",\r\n            className: null,\r\n            wordsOnly: false,\r\n            caseSensitive: false\r\n        };\r\n        return function hightlight(o) {\r\n            var regex;\r\n            o = _.mixin({}, defaults, o);\r\n            if (!o.node || !o.pattern) {\r\n                return;\r\n            }\r\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\r\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\r\n            traverse(o.node, hightlightTextNode);\r\n            function hightlightTextNode(textNode) {\r\n                var match, patternNode;\r\n                if (match = regex.exec(textNode.data)) {\r\n                    wrapperNode = doc.createElement(o.tagName);\r\n                    o.className && (wrapperNode.className = o.className);\r\n                    patternNode = textNode.splitText(match.index);\r\n                    patternNode.splitText(match[0].length);\r\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\r\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\r\n                }\r\n                return !!match;\r\n            }\r\n            function traverse(el, hightlightTextNode) {\r\n                var childNode, TEXT_NODE_TYPE = 3;\r\n                for (var i = 0; i < el.childNodes.length; i++) {\r\n                    childNode = el.childNodes[i];\r\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\r\n                        i += hightlightTextNode(childNode) ? 1 : 0;\r\n                    } else {\r\n                        traverse(childNode, hightlightTextNode);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        function getRegex(patterns, caseSensitive, wordsOnly) {\r\n            var escapedPatterns = [], regexStr;\r\n            for (var i = 0; i < patterns.length; i++) {\r\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\r\n            }\r\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\r\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\r\n        }\r\n    }(window.document);\r\n    var Input = function() {\r\n        var specialKeyCodeMap;\r\n        specialKeyCodeMap = {\r\n            9: \"tab\",\r\n            27: \"esc\",\r\n            37: \"left\",\r\n            39: \"right\",\r\n            13: \"enter\",\r\n            38: \"up\",\r\n            40: \"down\"\r\n        };\r\n        function Input(o) {\r\n            var that = this, onBlur, onFocus, onKeydown, onInput;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"input is missing\");\r\n            }\r\n            onBlur = _.bind(this._onBlur, this);\r\n            onFocus = _.bind(this._onFocus, this);\r\n            onKeydown = _.bind(this._onKeydown, this);\r\n            onInput = _.bind(this._onInput, this);\r\n            this.$hint = $(o.hint);\r\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\r\n            if (this.$hint.length === 0) {\r\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\r\n            }\r\n            if (!_.isMsie()) {\r\n                this.$input.on(\"input.tt\", onInput);\r\n            } else {\r\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\r\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\r\n                        return;\r\n                    }\r\n                    _.defer(_.bind(that._onInput, that, $e));\r\n                });\r\n            }\r\n            this.query = this.$input.val();\r\n            this.$overflowHelper = buildOverflowHelper(this.$input);\r\n        }\r\n        Input.normalizeQuery = function(str) {\r\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\r\n        };\r\n        _.mixin(Input.prototype, EventEmitter, {\r\n            _onBlur: function onBlur() {\r\n                this.resetInputValue();\r\n                this.trigger(\"blurred\");\r\n            },\r\n            _onFocus: function onFocus() {\r\n                this.trigger(\"focused\");\r\n            },\r\n            _onKeydown: function onKeydown($e) {\r\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\r\n                this._managePreventDefault(keyName, $e);\r\n                if (keyName && this._shouldTrigger(keyName, $e)) {\r\n                    this.trigger(keyName + \"Keyed\", $e);\r\n                }\r\n            },\r\n            _onInput: function onInput() {\r\n                this._checkInputValue();\r\n            },\r\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\r\n                var preventDefault, hintValue, inputValue;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    hintValue = this.getHint();\r\n                    inputValue = this.getInputValue();\r\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\r\n                    break;\r\n\r\n                  case \"up\":\r\n                  case \"down\":\r\n                    preventDefault = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    preventDefault = false;\r\n                }\r\n                preventDefault && $e.preventDefault();\r\n            },\r\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\r\n                var trigger;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    trigger = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    trigger = true;\r\n                }\r\n                return trigger;\r\n            },\r\n            _checkInputValue: function checkInputValue() {\r\n                var inputValue, areEquivalent, hasDifferentWhitespace;\r\n                inputValue = this.getInputValue();\r\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\r\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\r\n                if (!areEquivalent) {\r\n                    this.trigger(\"queryChanged\", this.query = inputValue);\r\n                } else if (hasDifferentWhitespace) {\r\n                    this.trigger(\"whitespaceChanged\", this.query);\r\n                }\r\n            },\r\n            focus: function focus() {\r\n                this.$input.focus();\r\n            },\r\n            blur: function blur() {\r\n                this.$input.blur();\r\n            },\r\n            getQuery: function getQuery() {\r\n                return this.query;\r\n            },\r\n            setQuery: function setQuery(query) {\r\n                this.query = query;\r\n            },\r\n            getInputValue: function getInputValue() {\r\n                return this.$input.val();\r\n            },\r\n            setInputValue: function setInputValue(value, silent) {\r\n                this.$input.val(value);\r\n                silent ? this.clearHint() : this._checkInputValue();\r\n            },\r\n            resetInputValue: function resetInputValue() {\r\n                this.setInputValue(this.query, true);\r\n            },\r\n            getHint: function getHint() {\r\n                return this.$hint.val();\r\n            },\r\n            setHint: function setHint(value) {\r\n                this.$hint.val(value);\r\n            },\r\n            clearHint: function clearHint() {\r\n                this.setHint(\"\");\r\n            },\r\n            clearHintIfInvalid: function clearHintIfInvalid() {\r\n                var val, hint, valIsPrefixOfHint, isValid;\r\n                val = this.getInputValue();\r\n                hint = this.getHint();\r\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\r\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\r\n                !isValid && this.clearHint();\r\n            },\r\n            getLanguageDirection: function getLanguageDirection() {\r\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\r\n            },\r\n            hasOverflow: function hasOverflow() {\r\n                var constraint = this.$input.width() - 2;\r\n                this.$overflowHelper.text(this.getInputValue());\r\n                return this.$overflowHelper.width() >= constraint;\r\n            },\r\n            isCursorAtEnd: function() {\r\n                var valueLength, selectionStart, range;\r\n                valueLength = this.$input.val().length;\r\n                selectionStart = this.$input[0].selectionStart;\r\n                if (_.isNumber(selectionStart)) {\r\n                    return selectionStart === valueLength;\r\n                } else if (document.selection) {\r\n                    range = document.selection.createRange();\r\n                    range.moveStart(\"character\", -valueLength);\r\n                    return valueLength === range.text.length;\r\n                }\r\n                return true;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$hint.off(\".tt\");\r\n                this.$input.off(\".tt\");\r\n                this.$hint = this.$input = this.$overflowHelper = null;\r\n            }\r\n        });\r\n        return Input;\r\n        function buildOverflowHelper($input) {\r\n            return $('<pre aria-hidden=\"true\"></pre>').css({\r\n                position: \"absolute\",\r\n                visibility: \"hidden\",\r\n                whiteSpace: \"pre\",\r\n                fontFamily: $input.css(\"font-family\"),\r\n                fontSize: $input.css(\"font-size\"),\r\n                fontStyle: $input.css(\"font-style\"),\r\n                fontVariant: $input.css(\"font-variant\"),\r\n                fontWeight: $input.css(\"font-weight\"),\r\n                wordSpacing: $input.css(\"word-spacing\"),\r\n                letterSpacing: $input.css(\"letter-spacing\"),\r\n                textIndent: $input.css(\"text-indent\"),\r\n                textRendering: $input.css(\"text-rendering\"),\r\n                textTransform: $input.css(\"text-transform\")\r\n            }).insertAfter($input);\r\n        }\r\n        function areQueriesEquivalent(a, b) {\r\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\r\n        }\r\n        function withModifier($e) {\r\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\r\n        }\r\n    }();\r\n    var Dataset = function() {\r\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\r\n        function Dataset(o) {\r\n            o = o || {};\r\n            o.templates = o.templates || {};\r\n            if (!o.source) {\r\n                $.error(\"missing source\");\r\n            }\r\n            if (o.name && !isValidName(o.name)) {\r\n                $.error(\"invalid dataset name: \" + o.name);\r\n            }\r\n            this.query = null;\r\n            this.highlight = !!o.highlight;\r\n            this.name = o.name || _.getUniqueId();\r\n            this.source = o.source;\r\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\r\n            this.templates = getTemplates(o.templates, this.displayFn);\r\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\r\n        }\r\n        Dataset.extractDatasetName = function extractDatasetName(el) {\r\n            return $(el).data(datasetKey);\r\n        };\r\n        Dataset.extractValue = function extractDatum(el) {\r\n            return $(el).data(valueKey);\r\n        };\r\n        Dataset.extractDatum = function extractDatum(el) {\r\n            return $(el).data(datumKey);\r\n        };\r\n        _.mixin(Dataset.prototype, EventEmitter, {\r\n            _render: function render(query, suggestions) {\r\n                if (!this.$el) {\r\n                    return;\r\n                }\r\n                var that = this, hasSuggestions;\r\n                this.$el.empty();\r\n                hasSuggestions = suggestions && suggestions.length;\r\n                if (!hasSuggestions && this.templates.empty) {\r\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                } else if (hasSuggestions) {\r\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                }\r\n                this.trigger(\"rendered\");\r\n                function getEmptyHtml() {\r\n                    return that.templates.empty({\r\n                        query: query,\r\n                        isEmpty: true\r\n                    });\r\n                }\r\n                function getSuggestionsHtml() {\r\n                    var $suggestions, nodes;\r\n                    $suggestions = $(html.suggestions).css(css.suggestions);\r\n                    nodes = _.map(suggestions, getSuggestionNode);\r\n                    $suggestions.append.apply($suggestions, nodes);\r\n                    that.highlight && highlight({\r\n                        node: $suggestions[0],\r\n                        pattern: query\r\n                    });\r\n                    return $suggestions;\r\n                    function getSuggestionNode(suggestion) {\r\n                        var $el;\r\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\r\n                        $el.children().each(function() {\r\n                            $(this).css(css.suggestionChild);\r\n                        });\r\n                        return $el;\r\n                    }\r\n                }\r\n                function getHeaderHtml() {\r\n                    return that.templates.header({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n                function getFooterHtml() {\r\n                    return that.templates.footer({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n            },\r\n            getRoot: function getRoot() {\r\n                return this.$el;\r\n            },\r\n            update: function update(query) {\r\n                var that = this;\r\n                this.query = query;\r\n                this.canceled = false;\r\n                this.source(query, render);\r\n                function render(suggestions) {\r\n                    if (!that.canceled && query === that.query) {\r\n                        that._render(query, suggestions);\r\n                    }\r\n                }\r\n            },\r\n            cancel: function cancel() {\r\n                this.canceled = true;\r\n            },\r\n            clear: function clear() {\r\n                this.cancel();\r\n                this.$el.empty();\r\n                this.trigger(\"rendered\");\r\n            },\r\n            isEmpty: function isEmpty() {\r\n                return this.$el.is(\":empty\");\r\n            },\r\n            destroy: function destroy() {\r\n                this.$el = null;\r\n            }\r\n        });\r\n        return Dataset;\r\n        function getDisplayFn(display) {\r\n            display = display || \"value\";\r\n            return _.isFunction(display) ? display : displayFn;\r\n            function displayFn(obj) {\r\n                return obj[display];\r\n            }\r\n        }\r\n        function getTemplates(templates, displayFn) {\r\n            return {\r\n                empty: templates.empty && _.templatify(templates.empty),\r\n                header: templates.header && _.templatify(templates.header),\r\n                footer: templates.footer && _.templatify(templates.footer),\r\n                suggestion: templates.suggestion || suggestionTemplate\r\n            };\r\n            function suggestionTemplate(context) {\r\n                return \"<p>\" + displayFn(context) + \"</p>\";\r\n            }\r\n        }\r\n        function isValidName(str) {\r\n            return /^[_a-zA-Z0-9-]+$/.test(str);\r\n        }\r\n    }();\r\n    var Dropdown = function() {\r\n        function Dropdown(o) {\r\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\r\n            o = o || {};\r\n            if (!o.menu) {\r\n                $.error(\"menu is required\");\r\n            }\r\n            this.isOpen = false;\r\n            this.isEmpty = true;\r\n            this.datasets = _.map(o.datasets, initializeDataset);\r\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\r\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\r\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\r\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\r\n            _.each(this.datasets, function(dataset) {\r\n                that.$menu.append(dataset.getRoot());\r\n                dataset.onSync(\"rendered\", that._onRendered, that);\r\n            });\r\n        }\r\n        _.mixin(Dropdown.prototype, EventEmitter, {\r\n            _onSuggestionClick: function onSuggestionClick($e) {\r\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\r\n            },\r\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\r\n                this._removeCursor();\r\n                this._setCursor($($e.currentTarget), true);\r\n            },\r\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\r\n                this._removeCursor();\r\n            },\r\n            _onRendered: function onRendered() {\r\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\r\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\r\n                this.trigger(\"datasetRendered\");\r\n                function isDatasetEmpty(dataset) {\r\n                    return dataset.isEmpty();\r\n                }\r\n            },\r\n            _hide: function() {\r\n                this.$menu.hide();\r\n            },\r\n            _show: function() {\r\n                this.$menu.css(\"display\", \"block\");\r\n            },\r\n            _getSuggestions: function getSuggestions() {\r\n                return this.$menu.find(\".tt-suggestion\");\r\n            },\r\n            _getCursor: function getCursor() {\r\n                return this.$menu.find(\".tt-cursor\").first();\r\n            },\r\n            _setCursor: function setCursor($el, silent) {\r\n                $el.first().addClass(\"tt-cursor\");\r\n                !silent && this.trigger(\"cursorMoved\");\r\n            },\r\n            _removeCursor: function removeCursor() {\r\n                this._getCursor().removeClass(\"tt-cursor\");\r\n            },\r\n            _moveCursor: function moveCursor(increment) {\r\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\r\n                if (!this.isOpen) {\r\n                    return;\r\n                }\r\n                $oldCursor = this._getCursor();\r\n                $suggestions = this._getSuggestions();\r\n                this._removeCursor();\r\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\r\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\r\n                if (newCursorIndex === -1) {\r\n                    this.trigger(\"cursorRemoved\");\r\n                    return;\r\n                } else if (newCursorIndex < -1) {\r\n                    newCursorIndex = $suggestions.length - 1;\r\n                }\r\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\r\n                this._ensureVisible($newCursor);\r\n            },\r\n            _ensureVisible: function ensureVisible($el) {\r\n                var elTop, elBottom, menuScrollTop, menuHeight;\r\n                elTop = $el.position().top;\r\n                elBottom = elTop + $el.outerHeight(true);\r\n                menuScrollTop = this.$menu.scrollTop();\r\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\r\n                if (elTop < 0) {\r\n                    this.$menu.scrollTop(menuScrollTop + elTop);\r\n                } else if (menuHeight < elBottom) {\r\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\r\n                }\r\n            },\r\n            close: function close() {\r\n                if (this.isOpen) {\r\n                    this.isOpen = false;\r\n                    this._removeCursor();\r\n                    this._hide();\r\n                    this.trigger(\"closed\");\r\n                }\r\n            },\r\n            open: function open() {\r\n                if (!this.isOpen) {\r\n                    this.isOpen = true;\r\n                    !this.isEmpty && this._show();\r\n                    this.trigger(\"opened\");\r\n                }\r\n            },\r\n            setLanguageDirection: function setLanguageDirection(dir) {\r\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\r\n            },\r\n            moveCursorUp: function moveCursorUp() {\r\n                this._moveCursor(-1);\r\n            },\r\n            moveCursorDown: function moveCursorDown() {\r\n                this._moveCursor(+1);\r\n            },\r\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\r\n                var datum = null;\r\n                if ($el.length) {\r\n                    datum = {\r\n                        raw: Dataset.extractDatum($el),\r\n                        value: Dataset.extractValue($el),\r\n                        datasetName: Dataset.extractDatasetName($el)\r\n                    };\r\n                }\r\n                return datum;\r\n            },\r\n            getDatumForCursor: function getDatumForCursor() {\r\n                return this.getDatumForSuggestion(this._getCursor().first());\r\n            },\r\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\r\n                return this.getDatumForSuggestion(this._getSuggestions().first());\r\n            },\r\n            update: function update(query) {\r\n                _.each(this.datasets, updateDataset);\r\n                function updateDataset(dataset) {\r\n                    dataset.update(query);\r\n                }\r\n            },\r\n            empty: function empty() {\r\n                _.each(this.datasets, clearDataset);\r\n                this.isEmpty = true;\r\n                function clearDataset(dataset) {\r\n                    dataset.clear();\r\n                }\r\n            },\r\n            isVisible: function isVisible() {\r\n                return this.isOpen && !this.isEmpty;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$menu.off(\".tt\");\r\n                this.$menu = null;\r\n                _.each(this.datasets, destroyDataset);\r\n                function destroyDataset(dataset) {\r\n                    dataset.destroy();\r\n                }\r\n            }\r\n        });\r\n        return Dropdown;\r\n        function initializeDataset(oDataset) {\r\n            return new Dataset(oDataset);\r\n        }\r\n    }();\r\n    var Typeahead = function() {\r\n        var attrsKey = \"ttAttrs\";\r\n        function Typeahead(o) {\r\n            var $menu, $input, $hint;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"missing input\");\r\n            }\r\n            this.isActivated = false;\r\n            this.autoselect = !!o.autoselect;\r\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\r\n            this.$node = buildDomStructure(o.input, o.withHint);\r\n            $menu = this.$node.find(\".tt-dropdown-menu\");\r\n            $input = this.$node.find(\".tt-input\");\r\n            $hint = this.$node.find(\".tt-hint\");\r\n            $input.on(\"blur.tt\", function($e) {\r\n                var active, isActive, hasActive;\r\n                active = document.activeElement;\r\n                isActive = $menu.is(active);\r\n                hasActive = $menu.has(active).length > 0;\r\n                if (_.isMsie() && (isActive || hasActive)) {\r\n                    $e.preventDefault();\r\n                    $e.stopImmediatePropagation();\r\n                    _.defer(function() {\r\n                        $input.focus();\r\n                    });\r\n                }\r\n            });\r\n            $menu.on(\"mousedown.tt\", function($e) {\r\n                $e.preventDefault();\r\n            });\r\n            this.eventBus = o.eventBus || new EventBus({\r\n                el: $input\r\n            });\r\n            this.dropdown = new Dropdown({\r\n                menu: $menu,\r\n                datasets: o.datasets\r\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\r\n            this.input = new Input({\r\n                input: $input,\r\n                hint: $hint\r\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\r\n            this._setLanguageDirection();\r\n        }\r\n        _.mixin(Typeahead.prototype, {\r\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\r\n                    this._select(datum);\r\n                }\r\n            },\r\n            _onCursorMoved: function onCursorMoved() {\r\n                var datum = this.dropdown.getDatumForCursor();\r\n                this.input.setInputValue(datum.value, true);\r\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\r\n            },\r\n            _onCursorRemoved: function onCursorRemoved() {\r\n                this.input.resetInputValue();\r\n                this._updateHint();\r\n            },\r\n            _onDatasetRendered: function onDatasetRendered() {\r\n                this._updateHint();\r\n            },\r\n            _onOpened: function onOpened() {\r\n                this._updateHint();\r\n                this.eventBus.trigger(\"opened\");\r\n            },\r\n            _onClosed: function onClosed() {\r\n                this.input.clearHint();\r\n                this.eventBus.trigger(\"closed\");\r\n            },\r\n            _onFocused: function onFocused() {\r\n                this.isActivated = true;\r\n                this.dropdown.open();\r\n            },\r\n            _onBlurred: function onBlurred() {\r\n                this.isActivated = false;\r\n                this.dropdown.empty();\r\n                this.dropdown.close();\r\n                this.setVal(\"\", true); //LM\r\n            },\r\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\r\n                var cursorDatum, topSuggestionDatum;\r\n                cursorDatum = this.dropdown.getDatumForCursor();\r\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\r\n                if (cursorDatum) {\r\n                    this._select(cursorDatum);\r\n                    $e.preventDefault();\r\n                } else if (this.autoselect && topSuggestionDatum) {\r\n                    this._select(topSuggestionDatum);\r\n                    $e.preventDefault();\r\n                }\r\n            },\r\n            _onTabKeyed: function onTabKeyed(type, $e) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForCursor()) {\r\n                    this._select(datum);\r\n                    $e.preventDefault();\r\n                } else {\r\n                    this._autocomplete(true);\r\n                }\r\n            },\r\n            _onEscKeyed: function onEscKeyed() {\r\n                this.dropdown.close();\r\n                this.input.resetInputValue();\r\n            },\r\n            _onUpKeyed: function onUpKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\r\n                this.dropdown.open();\r\n            },\r\n            _onDownKeyed: function onDownKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\r\n                this.dropdown.open();\r\n            },\r\n            _onLeftKeyed: function onLeftKeyed() {\r\n                this.dir === \"rtl\" && this._autocomplete();\r\n            },\r\n            _onRightKeyed: function onRightKeyed() {\r\n                this.dir === \"ltr\" && this._autocomplete();\r\n            },\r\n            _onQueryChanged: function onQueryChanged(e, query) {\r\n                this.input.clearHintIfInvalid();\r\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\r\n                this.dropdown.open();\r\n                this._setLanguageDirection();\r\n            },\r\n            _onWhitespaceChanged: function onWhitespaceChanged() {\r\n                this._updateHint();\r\n                this.dropdown.open();\r\n            },\r\n            _setLanguageDirection: function setLanguageDirection() {\r\n                var dir;\r\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\r\n                    this.dir = dir;\r\n                    this.$node.css(\"direction\", dir);\r\n                    this.dropdown.setLanguageDirection(dir);\r\n                }\r\n            },\r\n            _updateHint: function updateHint() {\r\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\r\n                datum = this.dropdown.getDatumForTopSuggestion();\r\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\r\n                    val = this.input.getInputValue();\r\n                    query = Input.normalizeQuery(val);\r\n                    escapedQuery = _.escapeRegExChars(query);\r\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\r\n                    match = frontMatchRegEx.exec(datum.value);\r\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\r\n                } else {\r\n                    this.input.clearHint();\r\n                }\r\n            },\r\n            _autocomplete: function autocomplete(laxCursor) {\r\n                var hint, query, isCursorAtEnd, datum;\r\n                hint = this.input.getHint();\r\n                query = this.input.getQuery();\r\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\r\n                if (hint && query !== hint && isCursorAtEnd) {\r\n                    datum = this.dropdown.getDatumForTopSuggestion();\r\n                    datum && this.input.setInputValue(datum.value);\r\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\r\n                }\r\n            },\r\n            _select: function select(datum) {\r\n                this.input.setQuery(datum.value);\r\n                this.input.setInputValue(datum.value, true);\r\n                this._setLanguageDirection();\r\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\r\n                this.dropdown.close();\r\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\r\n            },\r\n            open: function open() {\r\n                this.dropdown.open();\r\n            },\r\n            close: function close() {\r\n                this.dropdown.close();\r\n            },\r\n            setVal: function setVal(val) {\r\n                if (this.isActivated) {\r\n                    this.input.setInputValue(val);\r\n                } else {\r\n                    this.input.setQuery(val);\r\n                    this.input.setInputValue(val, true);\r\n                }\r\n                this._setLanguageDirection();\r\n            },\r\n            getVal: function getVal() {\r\n                return this.input.getQuery();\r\n            },\r\n            destroy: function destroy() {\r\n                this.input.destroy();\r\n                this.dropdown.destroy();\r\n                destroyDomStructure(this.$node);\r\n                this.$node = null;\r\n            }\r\n        });\r\n        return Typeahead;\r\n        function buildDomStructure(input, withHint) {\r\n            var $input, $wrapper, $dropdown, $hint;\r\n            $input = $(input);\r\n            $wrapper = $(html.wrapper).css(css.wrapper);\r\n            $dropdown = $(html.dropdown).css(css.dropdown);\r\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\r\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: \"false\"\r\n            });\r\n            $input.data(attrsKey, {\r\n                dir: $input.attr(\"dir\"),\r\n                autocomplete: $input.attr(\"autocomplete\"),\r\n                spellcheck: $input.attr(\"spellcheck\"),\r\n                style: $input.attr(\"style\")\r\n            });\r\n            $input.addClass(\"tt-input\").attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: false\r\n            }).css(withHint ? css.input : css.inputWithNoHint);\r\n            try {\r\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\r\n            } catch (e) {}\r\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\r\n        }\r\n        function getBackgroundStyles($el) {\r\n            return {\r\n                backgroundAttachment: $el.css(\"background-attachment\"),\r\n                backgroundClip: $el.css(\"background-clip\"),\r\n                backgroundColor: $el.css(\"background-color\"),\r\n                backgroundImage: $el.css(\"background-image\"),\r\n                backgroundOrigin: $el.css(\"background-origin\"),\r\n                backgroundPosition: $el.css(\"background-position\"),\r\n                backgroundRepeat: $el.css(\"background-repeat\"),\r\n                backgroundSize: $el.css(\"background-size\")\r\n            };\r\n        }\r\n        function destroyDomStructure($node) {\r\n            var $input = $node.find(\".tt-input\");\r\n            _.each($input.data(attrsKey), function(val, key) {\r\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\r\n            });\r\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\r\n            $node.remove();\r\n        }\r\n    }();\r\n    (function() {\r\n        var old, typeaheadKey, methods;\r\n        old = $.fn.typeahead;\r\n        typeaheadKey = \"ttTypeahead\";\r\n        methods = {\r\n            initialize: function initialize(o, datasets) {\r\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\r\n                o = o || {};\r\n                return this.each(attach);\r\n                function attach() {\r\n                    var $input = $(this), eventBus, typeahead;\r\n                    _.each(datasets, function(d) {\r\n                        d.highlight = !!o.highlight;\r\n                    });\r\n                    typeahead = new Typeahead({\r\n                        input: $input,\r\n                        eventBus: eventBus = new EventBus({\r\n                            el: $input\r\n                        }),\r\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\r\n                        minLength: o.minLength,\r\n                        autoselect: o.autoselect,\r\n                        datasets: datasets\r\n                    });\r\n                    $input.data(typeaheadKey, typeahead);\r\n                }\r\n            },\r\n            open: function open() {\r\n                return this.each(openTypeahead);\r\n                function openTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.open();\r\n                    }\r\n                }\r\n            },\r\n            close: function close() {\r\n                return this.each(closeTypeahead);\r\n                function closeTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.close();\r\n                    }\r\n                }\r\n            },\r\n            val: function val(newVal) {\r\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\r\n                function setVal() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.setVal(newVal);\r\n                    }\r\n                }\r\n                function getVal($input) {\r\n                    var typeahead, query;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        query = typeahead.getVal();\r\n                    }\r\n                    return query;\r\n                }\r\n            },\r\n            destroy: function destroy() {\r\n                return this.each(unattach);\r\n                function unattach() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.destroy();\r\n                        $input.removeData(typeaheadKey);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        $.fn.typeahead = function(method) {\r\n            if (methods[method]) {\r\n                return methods[method].apply(this, [].slice.call(arguments, 1));\r\n            } else {\r\n                return methods.initialize.apply(this, arguments);\r\n            }\r\n        };\r\n        $.fn.typeahead.noConflict = function noConflict() {\r\n            $.fn.typeahead = old;\r\n            return this;\r\n        };\r\n    })();\r\n    \r\n    \r\n    \r\n//})(window.jQuery);\r\n\r\n\r\n});\n",
        +    "define('searchView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/search.html',\r\n  'text!tpl/search_suggestion.html',\r\n  // Tools\r\n  'typeahead'\r\n], function(App, searchTpl, suggestionTpl) {\r\n\r\n  var searchView = Backbone.View.extend({\r\n    el: '#search',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      var tpl = _.template(searchTpl);\r\n      var className = 'form-control input-lg';\r\n      var placeholder = 'Search reference';\r\n      this.searchHtml = tpl({\r\n        'placeholder': placeholder,\r\n        'className': className\r\n      });\r\n      this.items = App.classes.concat(App.allItems);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render input field with Typehead activated.\r\n     */\r\n    render: function() {\r\n      // Append the view to the dom\r\n      this.$el.append(this.searchHtml);\r\n\r\n      // Render Typeahead\r\n      var $searchInput = this.$el.find('input[type=text]');\r\n      this.typeaheadRender($searchInput);\r\n      this.typeaheadEvents($searchInput);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Apply Twitter Typeahead to the search input field.\r\n     * @param {jquery} $input\r\n     */\r\n    typeaheadRender: function($input) {\r\n      var self = this;\r\n      $input.typeahead(null, {\r\n        'displayKey': 'name',\r\n        'minLength': 2,\r\n        //'highlight': true,\r\n        'source': self.substringMatcher(this.items),\r\n        'templates': {\r\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\r\n          'suggestion': _.template(suggestionTpl)\r\n        }\r\n      });\r\n    },\r\n    /**\r\n     * Setup typeahead custom events (item selected).\r\n     */\r\n    typeaheadEvents: function($input) {\r\n      var self = this;\r\n      $input.on('typeahead:selected', function(e, item, datasetName) {\r\n        var selectedItem = self.items[item.idx];\r\n        select(selectedItem);\r\n      });\r\n      $input.on('keydown', function(e) {\r\n        if (e.which === 13) { // enter\r\n          var txt = $input.val();\r\n          var f = _.find(self.items, function(it) { return it.name == txt; });\r\n          if (f) {\r\n            select(f);\r\n          }\r\n        } else if (e.which === 27) {\r\n          $input.blur();\r\n        }\r\n      });\r\n\r\n      function select(selectedItem) {\r\n        var hash = App.router.getHash(selectedItem);//\r\n        App.router.navigate(hash, {'trigger': true});\r\n        $('#item').focus();\r\n      }\r\n    },\r\n    /**\r\n     * substringMatcher function for Typehead (search for strings in an array).\r\n     * @param {array} array\r\n     * @returns {Function}\r\n     */\r\n    substringMatcher: function(array) {\r\n      return function findMatches(query, callback) {\r\n        var matches = [], substrRegex, arrayLength = array.length;\r\n\r\n        // regex used to determine if a string contains the substring `query`\r\n        substrRegex = new RegExp(query, 'i');\r\n\r\n        // iterate through the pool of strings and for any string that\r\n        // contains the substring `query`, add it to the `matches` array\r\n        for (var i=0; i < arrayLength; i++) {\r\n          var item = array[i];\r\n          if (substrRegex.test(item.name)) {\r\n            // typeahead expects suggestions to be a js object\r\n            matches.push({\r\n              'itemtype': item.itemtype,\r\n              'name': item.name,\r\n              'className': item.class,\r\n              'is_constructor': !!item.is_constructor,\r\n              'final': item.final,\r\n              'idx': i\r\n            });\r\n          }\r\n        }\r\n\r\n        callback(matches);\r\n      };\r\n    }\r\n\r\n  });\r\n\r\n  return searchView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\r\\n  <div class=\"reference-group clearfix main-ref-page\">  \\r\\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\r\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\r\\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\r\\n      <div class=\"reference-subgroup\">\\r\\n        <% if (subgroup.name !== \\'0\\') { %>\\r\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\r\\n        <% } %>\\r\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\r\\n        <% _.each(subgroup.items, function(item) { %>\\r\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\r\\n        <% }); %>\\r\\n        </ul>\\r\\n      </div>\\r\\n    <% }); %>\\r\\n    </div>\\r\\n  </div>\\r\\n<% }); %>\\r\\n';});\n\n",
        +    "define('listView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/list.html'\r\n], function (App, listTpl) {\r\n  var striptags = function(html) {\r\n    var div = document.createElement('div');\r\n    div.innerHTML = html;\r\n    return div.textContent;\r\n  };\r\n\r\n  var listView = Backbone.View.extend({\r\n    el: '#list',\r\n    events: {},\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function () {\r\n      this.listTpl = _.template(listTpl);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render the list.\r\n     */\r\n    render: function (items, listCollection) {\r\n      if (items && listCollection) {\r\n        var self = this;\r\n\r\n        // Render items and group them by module\r\n        // module === group\r\n        this.groups = {};\r\n        _.each(items, function (item, i) {\r\n\r\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n\r\n            var group = item.module || '_';\r\n            var subgroup = item.submodule || '_';\r\n            if (group === subgroup) {\r\n              subgroup = '0';\r\n            }\r\n            var hash = App.router.getHash(item);\r\n\r\n            // Create a group list\r\n            if (!self.groups[group]) {\r\n              self.groups[group] = {\r\n                name: group.replace('_', '&nbsp;'),\r\n                subgroups: {}\r\n              };\r\n            }\r\n\r\n            // Create a subgroup list\r\n            if (!self.groups[group].subgroups[subgroup]) {\r\n              self.groups[group].subgroups[subgroup] = {\r\n                name: subgroup.replace('_', '&nbsp;'),\r\n                items: []\r\n              };\r\n            }\r\n\r\n            // hide the un-interesting constants\r\n            if (group === 'Constants' && !item.example)\r\n              return;\r\n\r\n            if (item.class === 'p5') {\r\n\r\n              self.groups[group].subgroups[subgroup].items.push(item);\r\n\r\n            } else {\r\n\r\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\r\n                function(i){ return i.name == item.class; });\r\n\r\n              if (!found) {\r\n\r\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\r\n                var ind = hash.lastIndexOf('/');\r\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\r\n                self.groups[group].subgroups[subgroup].items.push({\r\n                  name: item.class,\r\n                  hash: hash\r\n                });\r\n              }\r\n\r\n            }\r\n          }\r\n        });\r\n\r\n        // Put the <li> items html into the list <ul>\r\n        var listHtml = self.listTpl({\r\n          'striptags': striptags,\r\n          'title': self.capitalizeFirst(listCollection),\r\n          'groups': self.groups,\r\n          'listCollection': listCollection\r\n        });\r\n\r\n        // Render the view\r\n        this.$el.html(listHtml);\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a list of items.\r\n     * @param {array} items Array of item objects.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function (listGroup) {\r\n      if (App[listGroup]) {\r\n        this.render(App[listGroup], listGroup);\r\n      }\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function (str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n\r\n\r\n\r\n  });\r\n\r\n  return listView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\r\\n\\r\\n<% if (item.example) { %>\\r\\n<div class=\"example\">\\r\\n  <h3 id=\"reference-example\">Examples</h3>\\r\\n\\r\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\r\\n    <% _.each(item.example, function(example, i){ %>\\r\\n      <%= example %>\\r\\n    <% }); %>\\r\\n  </div>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<div class=\"description\">\\r\\n    \\r\\n  <h3 id=\"reference-description\">Description</h3>\\r\\n\\r\\n  <% if (item.deprecated) { %>\\r\\n    <p>\\r\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n      \\r\\n\\r\\n  <span class=\\'description-text\\'><%= item.description %></span>\\r\\n\\r\\n  <% if (item.extends) { %>\\r\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.module === \\'p5.sound\\') { %>\\r\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\r\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\r\\n    </p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.constRefs) { %>\\r\\n    <p>Used by:\\r\\n  <%\\r\\n      var refs = item.constRefs;\\r\\n      for (var i = 0; i < refs.length; i ++) {\\r\\n        var ref = refs[i];\\r\\n        var name = ref;\\r\\n        if (name.substr(0, 3) === \\'p5.\\') {\\r\\n          name = name.substr(3);\\r\\n        }\\r\\n  if (i !== 0) {\\r\\n          if (i == refs.length - 1) {\\r\\n            %> and <%\\r\\n          } else {\\r\\n            %>, <%\\r\\n          }\\r\\n        }\\r\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\r\\n      }\\r\\n  %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n</div>\\r\\n\\r\\n<% if (isConstructor || !isClass) { %>\\r\\n\\r\\n<div>\\r\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\r\\n  <p>\\r\\n    <% syntaxes.forEach(function(syntax) { %>\\r\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\r\\n    <% }) %>\\r\\n  </p>\\r\\n</div>\\r\\n\\r\\n\\r\\n<% if (item.params) { %>\\r\\n  <div class=\"params\">\\r\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\r\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\r\\n    <% for (var i=0; i<item.params.length; i++) { %>\\r\\n      <% var p = item.params[i] %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><%=p.name%></div>\\r\\n        <% if (p.type) { %>\\r\\n          <div class=\\'paramtype\\'>\\r\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\r\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\r\\n          <% if (p.optional) { %> (Optional)<% } %>\\r\\n          </div>\\r\\n        <% } %>\\r\\n      </li>\\r\\n    <% } %>\\r\\n    </ul>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% if (item.return && item.return.type) { %>\\r\\n  <div>\\r\\n    <h3 id=\"reference-returns\">Returns</h3>\\r\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% } %>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/class.html',[],function () { return '\\r\\n<% if (typeof constructor !== \\'undefined\\') { %>\\r\\n<div class=\"constructor\">\\r\\n  <!--<h2>Constructor</h2>--> \\r\\n  <%=constructor%>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (fields.length > 0) { %>\\r\\n  <h4>Fields</h4>\\r\\n  <p>\\r\\n    <% _.each(fields, function(item) { %>\\r\\n      <a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%></a>: <%= item.description %>\\r\\n      <br>\\r\\n    <% }); %>\\r\\n  </p>\\r\\n<% } %>\\r\\n\\r\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (methods.length > 0) { %>\\r\\n  <h4>Methods</h4>\\r\\n  <p>\\r\\n    <table>\\r\\n    <% _.each(methods, function(item) { %>\\r\\n      <tr>\\r\\n      <td><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></td><td><div class=\"method_description\"><%= item.description %></div></td>\\r\\n      </tr>\\r\\n    <% }); %>\\r\\n    </table>\\r\\n  </p>\\r\\n<% } %>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\r\\n<br><br>\\r\\n\\r\\n<div>\\r\\n<% if (item.file && item.line) { %>\\r\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\r\\n<% } %>\\r\\n</div>\\r\\n\\r\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\r\\n<br><br>\\r\\n';});\n\n",
        +    "// Copyright (C) 2006 Google Inc.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n//      http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview\r\n * some functions for browser-side pretty printing of code contained in html.\r\n *\r\n * <p>\r\n * For a fairly comprehensive set of languages see the\r\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\r\n * file that came with this source.  At a minimum, the lexer should work on a\r\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\r\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\r\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\r\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\r\n * <p>\r\n * Usage: <ol>\r\n * <li> include this source file in an html page via\r\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\r\n * <li> define style rules.  See the example page for examples.\r\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\r\n *    {@code class=prettyprint.}\r\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\r\n *    printer needs to do more substantial DOM manipulations to support that, so\r\n *    some css styles may not be preserved.\r\n * </ol>\r\n * That's it.  I wanted to keep the API as simple as possible, so there's no\r\n * need to specify which language the code is in, but if you wish, you can add\r\n * another class to the {@code <pre>} or {@code <code>} element to specify the\r\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\r\n * starts with \"lang-\" followed by a file extension, specifies the file type.\r\n * See the \"lang-*.js\" files in this directory for code that implements\r\n * per-language file handlers.\r\n * <p>\r\n * Change log:<br>\r\n * cbeust, 2006/08/22\r\n * <blockquote>\r\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\r\n * </blockquote>\r\n * @requires console\r\n */\r\n\r\n// JSLint declarations\r\n/*global console, document, navigator, setTimeout, window, define */\r\n\r\n/** @define {boolean} */\r\nvar IN_GLOBAL_SCOPE = true;\r\n\r\n/**\r\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\r\n * UI events.\r\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\r\n */\r\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\r\n\r\n/**\r\n * Pretty print a chunk of code.\r\n * @param {string} sourceCodeHtml The HTML to pretty print.\r\n * @param {string} opt_langExtension The language name to use.\r\n *     Typically, a filename extension like 'cpp' or 'java'.\r\n * @param {number|boolean} opt_numberLines True to number lines,\r\n *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n * @return {string} code as html, but prettier\r\n */\r\nvar prettyPrintOne;\r\n/**\r\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n * {@code class=prettyprint} and prettify them.\r\n *\r\n * @param {Function} opt_whenDone called when prettifying is done.\r\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n *   containing all the elements to pretty print.\r\n *   Defaults to {@code document.body}.\r\n */\r\nvar prettyPrint;\r\n\r\n\r\n(function () {\r\n  var win = window;\r\n  // Keyword lists for various languages.\r\n  // We use things that coerce to strings to make them compact when minified\r\n  // and to defeat aggressive optimizers that fold large string constants.\r\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\r\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \r\n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\r\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\r\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\r\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\r\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\r\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\r\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\r\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\r\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\r\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\r\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\r\n      \"throws,transient\"];\r\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\r\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\r\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\r\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\r\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\r\n      \"var,virtual,where\"];\r\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\r\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\r\n      \"throw,true,try,unless,until,when,while,yes\";\r\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\r\n      \"Infinity,NaN\"];\r\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\r\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\r\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\r\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\r\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\r\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\r\n      \"False,True,None\"];\r\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\r\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\r\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\r\n      \"BEGIN,END\"];\r\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\r\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\r\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\r\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\r\n      \"function,in,local,set,then,until\"];\r\n  var ALL_KEYWORDS = [\r\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\r\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\r\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\r\n\r\n  // token style names.  correspond to css classes\r\n  /**\r\n   * token style for a string literal\r\n   * @const\r\n   */\r\n  var PR_STRING = 'str';\r\n  /**\r\n   * token style for a keyword\r\n   * @const\r\n   */\r\n  var PR_KEYWORD = 'kwd';\r\n  /**\r\n   * token style for a comment\r\n   * @const\r\n   */\r\n  var PR_COMMENT = 'com';\r\n  /**\r\n   * token style for a type\r\n   * @const\r\n   */\r\n  var PR_TYPE = 'typ';\r\n  /**\r\n   * token style for a literal value.  e.g. 1, null, true.\r\n   * @const\r\n   */\r\n  var PR_LITERAL = 'lit';\r\n  /**\r\n   * token style for a punctuation string.\r\n   * @const\r\n   */\r\n  var PR_PUNCTUATION = 'pun';\r\n  /**\r\n   * token style for plain text.\r\n   * @const\r\n   */\r\n  var PR_PLAIN = 'pln';\r\n\r\n  /**\r\n   * token style for an sgml tag.\r\n   * @const\r\n   */\r\n  var PR_TAG = 'tag';\r\n  /**\r\n   * token style for a markup declaration such as a DOCTYPE.\r\n   * @const\r\n   */\r\n  var PR_DECLARATION = 'dec';\r\n  /**\r\n   * token style for embedded source.\r\n   * @const\r\n   */\r\n  var PR_SOURCE = 'src';\r\n  /**\r\n   * token style for an sgml attribute name.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_NAME = 'atn';\r\n  /**\r\n   * token style for an sgml attribute value.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_VALUE = 'atv';\r\n\r\n  /**\r\n   * A class that indicates a section of markup that is not code, e.g. to allow\r\n   * embedding of line numbers within code listings.\r\n   * @const\r\n   */\r\n  var PR_NOCODE = 'nocode';\r\n\r\n  \r\n  \r\n  /**\r\n   * A set of tokens that can precede a regular expression literal in\r\n   * javascript\r\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\r\n   * has the full list, but I've removed ones that might be problematic when\r\n   * seen in languages that don't support regular expression literals.\r\n   *\r\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\r\n   * literal in a syntactically legal javascript program, and I've removed the\r\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\r\n   * as a count of inches.\r\n   *\r\n   * <p>The link above does not accurately describe EcmaScript rules since\r\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\r\n   * very well in practice.\r\n   *\r\n   * @private\r\n   * @const\r\n   */\r\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\r\n  \r\n  // CAVEAT: this does not properly handle the case where a regular\r\n  // expression immediately follows another since a regular expression may\r\n  // have flags for case-sensitivity and the like.  Having regexp tokens\r\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\r\n  // TODO: maybe style special characters inside a regexp as punctuation.\r\n\r\n  /**\r\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\r\n   * matches the union of the sets of strings matched by the input RegExp.\r\n   * Since it matches globally, if the input strings have a start-of-input\r\n   * anchor (/^.../), it is ignored for the purposes of unioning.\r\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\r\n   * @return {RegExp} a global regex.\r\n   */\r\n  function combinePrefixPatterns(regexs) {\r\n    var capturedGroupIndex = 0;\r\n  \r\n    var needToFoldCase = false;\r\n    var ignoreCase = false;\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.ignoreCase) {\r\n        ignoreCase = true;\r\n      } else if (/[a-z]/i.test(regex.source.replace(\r\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\r\n        needToFoldCase = true;\r\n        ignoreCase = false;\r\n        break;\r\n      }\r\n    }\r\n  \r\n    var escapeCharToCodeUnit = {\r\n      'b': 8,\r\n      't': 9,\r\n      'n': 0xa,\r\n      'v': 0xb,\r\n      'f': 0xc,\r\n      'r': 0xd\r\n    };\r\n  \r\n    function decodeEscape(charsetPart) {\r\n      var cc0 = charsetPart.charCodeAt(0);\r\n      if (cc0 !== 92 /* \\\\ */) {\r\n        return cc0;\r\n      }\r\n      var c1 = charsetPart.charAt(1);\r\n      cc0 = escapeCharToCodeUnit[c1];\r\n      if (cc0) {\r\n        return cc0;\r\n      } else if ('0' <= c1 && c1 <= '7') {\r\n        return parseInt(charsetPart.substring(1), 8);\r\n      } else if (c1 === 'u' || c1 === 'x') {\r\n        return parseInt(charsetPart.substring(2), 16);\r\n      } else {\r\n        return charsetPart.charCodeAt(1);\r\n      }\r\n    }\r\n  \r\n    function encodeEscape(charCode) {\r\n      if (charCode < 0x20) {\r\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\r\n      }\r\n      var ch = String.fromCharCode(charCode);\r\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\r\n          ? \"\\\\\" + ch : ch;\r\n    }\r\n  \r\n    function caseFoldCharset(charSet) {\r\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\r\n          new RegExp(\r\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\r\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\r\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\r\n              + '|\\\\\\\\[0-7]{1,2}'\r\n              + '|\\\\\\\\[\\\\s\\\\S]'\r\n              + '|-'\r\n              + '|[^-\\\\\\\\]',\r\n              'g'));\r\n      var ranges = [];\r\n      var inverse = charsetParts[0] === '^';\r\n  \r\n      var out = ['['];\r\n      if (inverse) { out.push('^'); }\r\n  \r\n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\r\n        var p = charsetParts[i];\r\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\r\n          out.push(p);\r\n        } else {\r\n          var start = decodeEscape(p);\r\n          var end;\r\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\r\n            end = decodeEscape(charsetParts[i + 2]);\r\n            i += 2;\r\n          } else {\r\n            end = start;\r\n          }\r\n          ranges.push([start, end]);\r\n          // If the range might intersect letters, then expand it.\r\n          // This case handling is too simplistic.\r\n          // It does not deal with non-latin case folding.\r\n          // It works for latin source code identifiers though.\r\n          if (!(end < 65 || start > 122)) {\r\n            if (!(end < 65 || start > 90)) {\r\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\r\n            }\r\n            if (!(end < 97 || start > 122)) {\r\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\r\n      // -> [[1, 12], [14, 14], [16, 17]]\r\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\r\n      var consolidatedRanges = [];\r\n      var lastRange = [];\r\n      for (var i = 0; i < ranges.length; ++i) {\r\n        var range = ranges[i];\r\n        if (range[0] <= lastRange[1] + 1) {\r\n          lastRange[1] = Math.max(lastRange[1], range[1]);\r\n        } else {\r\n          consolidatedRanges.push(lastRange = range);\r\n        }\r\n      }\r\n  \r\n      for (var i = 0; i < consolidatedRanges.length; ++i) {\r\n        var range = consolidatedRanges[i];\r\n        out.push(encodeEscape(range[0]));\r\n        if (range[1] > range[0]) {\r\n          if (range[1] + 1 > range[0]) { out.push('-'); }\r\n          out.push(encodeEscape(range[1]));\r\n        }\r\n      }\r\n      out.push(']');\r\n      return out.join('');\r\n    }\r\n  \r\n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\r\n      // Split into character sets, escape sequences, punctuation strings\r\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\r\n      // include any of the above.\r\n      var parts = regex.source.match(\r\n          new RegExp(\r\n              '(?:'\r\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\r\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\r\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\r\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\r\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\r\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\r\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\r\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\r\n              + ')',\r\n              'g'));\r\n      var n = parts.length;\r\n  \r\n      // Maps captured group numbers to the number they will occupy in\r\n      // the output or to -1 if that has not been determined, or to\r\n      // undefined if they need not be capturing in the output.\r\n      var capturedGroups = [];\r\n  \r\n      // Walk over and identify back references to build the capturedGroups\r\n      // mapping.\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          // groups are 1-indexed, so max group index is count of '('\r\n          ++groupIndex;\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue) {\r\n            if (decimalValue <= groupIndex) {\r\n              capturedGroups[decimalValue] = -1;\r\n            } else {\r\n              // Replace with an unambiguous escape sequence so that\r\n              // an octal escape sequence does not turn into a backreference\r\n              // to a capturing group from an earlier regex.\r\n              parts[i] = encodeEscape(decimalValue);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Renumber groups and reduce capturing groups to non-capturing groups\r\n      // where possible.\r\n      for (var i = 1; i < capturedGroups.length; ++i) {\r\n        if (-1 === capturedGroups[i]) {\r\n          capturedGroups[i] = ++capturedGroupIndex;\r\n        }\r\n      }\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          ++groupIndex;\r\n          if (!capturedGroups[groupIndex]) {\r\n            parts[i] = '(?:';\r\n          }\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue && decimalValue <= groupIndex) {\r\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Remove any prefix anchors so that the output will match anywhere.\r\n      // ^^ really does mean an anchored match though.\r\n      for (var i = 0; i < n; ++i) {\r\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\r\n      }\r\n  \r\n      // Expand letters to groups to handle mixing of case-sensitive and\r\n      // case-insensitive patterns if necessary.\r\n      if (regex.ignoreCase && needToFoldCase) {\r\n        for (var i = 0; i < n; ++i) {\r\n          var p = parts[i];\r\n          var ch0 = p.charAt(0);\r\n          if (p.length >= 2 && ch0 === '[') {\r\n            parts[i] = caseFoldCharset(p);\r\n          } else if (ch0 !== '\\\\') {\r\n            // TODO: handle letters in numeric escapes.\r\n            parts[i] = p.replace(\r\n                /[a-zA-Z]/g,\r\n                function (ch) {\r\n                  var cc = ch.charCodeAt(0);\r\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\r\n                });\r\n          }\r\n        }\r\n      }\r\n  \r\n      return parts.join('');\r\n    }\r\n  \r\n    var rewritten = [];\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\r\n      rewritten.push(\r\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\r\n    }\r\n  \r\n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\r\n  }\r\n\r\n  /**\r\n   * Split markup into a string of source code and an array mapping ranges in\r\n   * that string to the text nodes in which they appear.\r\n   *\r\n   * <p>\r\n   * The HTML DOM structure:</p>\r\n   * <pre>\r\n   * (Element   \"p\"\r\n   *   (Element \"b\"\r\n   *     (Text  \"print \"))       ; #1\r\n   *   (Text    \"'Hello '\")      ; #2\r\n   *   (Element \"br\")            ; #3\r\n   *   (Text    \"  + 'World';\")) ; #4\r\n   * </pre>\r\n   * <p>\r\n   * corresponds to the HTML\r\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\r\n   *\r\n   * <p>\r\n   * It will produce the output:</p>\r\n   * <pre>\r\n   * {\r\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\r\n   *   //                     1          2\r\n   *   //           012345678901234 5678901234567\r\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\r\n   * }\r\n   * </pre>\r\n   * <p>\r\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\r\n   * on for the other text nodes.\r\n   * </p>\r\n   *\r\n   * <p>\r\n   * The {@code} spans array is an array of pairs.  Even elements are the start\r\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\r\n   * that contain the text for those substrings.\r\n   * Substrings continue until the next index or the end of the source.\r\n   * </p>\r\n   *\r\n   * @param {Node} node an HTML DOM subtree containing source-code.\r\n   * @param {boolean} isPreformatted true if white-space in text nodes should\r\n   *    be considered significant.\r\n   * @return {Object} source code and the text nodes in which they occur.\r\n   */\r\n  function extractSourceSpans(node, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n  \r\n    var chunks = [];\r\n    var length = 0;\r\n    var spans = [];\r\n    var k = 0;\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1) {  // Element\r\n        if (nocode.test(node.className)) { return; }\r\n        for (var child = node.firstChild; child; child = child.nextSibling) {\r\n          walk(child);\r\n        }\r\n        var nodeName = node.nodeName.toLowerCase();\r\n        if ('br' === nodeName || 'li' === nodeName) {\r\n          chunks[k] = '\\n';\r\n          spans[k << 1] = length++;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      } else if (type == 3 || type == 4) {  // Text\r\n        var text = node.nodeValue;\r\n        if (text.length) {\r\n          if (!isPreformatted) {\r\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\r\n          } else {\r\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\r\n          }\r\n          // TODO: handle tabs here?\r\n          chunks[k] = text;\r\n          spans[k << 1] = length;\r\n          length += text.length;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      }\r\n    }\r\n  \r\n    walk(node);\r\n  \r\n    return {\r\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\r\n      spans: spans\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Apply the given language handler to sourceCode and add the resulting\r\n   * decorations to out.\r\n   * @param {number} basePos the index of sourceCode within the chunk of source\r\n   *    whose decorations are already present on out.\r\n   */\r\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\r\n    if (!sourceCode) { return; }\r\n    var job = {\r\n      sourceCode: sourceCode,\r\n      basePos: basePos\r\n    };\r\n    langHandler(job);\r\n    out.push.apply(out, job.decorations);\r\n  }\r\n\r\n  var notWs = /\\S/;\r\n\r\n  /**\r\n   * Given an element, if it contains only one child element and any text nodes\r\n   * it contains contain only space characters, return the sole child element.\r\n   * Otherwise returns undefined.\r\n   * <p>\r\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\r\n   * there is a single child element that contains all the non-space textual\r\n   * content, but not to return anything where there are multiple child elements\r\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\r\n   * is textual content.\r\n   */\r\n  function childContentWrapper(element) {\r\n    var wrapper = undefined;\r\n    for (var c = element.firstChild; c; c = c.nextSibling) {\r\n      var type = c.nodeType;\r\n      wrapper = (type === 1)  // Element Node\r\n          ? (wrapper ? element : c)\r\n          : (type === 3)  // Text Node\r\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\r\n          : wrapper;\r\n    }\r\n    return wrapper === element ? undefined : wrapper;\r\n  }\r\n\r\n  /** Given triples of [style, pattern, context] returns a lexing function,\r\n    * The lexing function interprets the patterns to find token boundaries and\r\n    * returns a decoration list of the form\r\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\r\n    * where index_n is an index into the sourceCode, and style_n is a style\r\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\r\n    * all characters in sourceCode[index_n-1:index_n].\r\n    *\r\n    * The stylePatterns is a list whose elements have the form\r\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\r\n    *\r\n    * Style is a style constant like PR_PLAIN, or can be a string of the\r\n    * form 'lang-FOO', where FOO is a language extension describing the\r\n    * language of the portion of the token in $1 after pattern executes.\r\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\r\n    * '(hello (world))', then that portion of the token will be passed to the\r\n    * registered lisp handler for formatting.\r\n    * The text before and after group 1 will be restyled using this decorator\r\n    * so decorators should take care that this doesn't result in infinite\r\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\r\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\r\n    * '<script>foo()<\\/script>', which would cause the current decorator to\r\n    * be called with '<script>' which would not match the same rule since\r\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\r\n    * the generic tag rule.  The handler registered for the 'js' extension would\r\n    * then be called with 'foo()', and finally, the current decorator would\r\n    * be called with '<\\/script>' which would not match the original rule and\r\n    * so the generic tag rule would identify it as a tag.\r\n    *\r\n    * Pattern must only match prefixes, and if it matches a prefix, then that\r\n    * match is considered a token with the same style.\r\n    *\r\n    * Context is applied to the last non-whitespace, non-comment token\r\n    * recognized.\r\n    *\r\n    * Shortcut is an optional string of characters, any of which, if the first\r\n    * character, gurantee that this pattern and only this pattern matches.\r\n    *\r\n    * @param {Array} shortcutStylePatterns patterns that always start with\r\n    *   a known character.  Must have a shortcut string.\r\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\r\n    *   order if the shortcut ones fail.  May have shortcuts.\r\n    *\r\n    * @return {function (Object)} a\r\n    *   function that takes source code and returns a list of decorations.\r\n    */\r\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\r\n    var shortcuts = {};\r\n    var tokenizer;\r\n    (function () {\r\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\r\n      var allRegexs = [];\r\n      var regexKeys = {};\r\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\r\n        var patternParts = allPatterns[i];\r\n        var shortcutChars = patternParts[3];\r\n        if (shortcutChars) {\r\n          for (var c = shortcutChars.length; --c >= 0;) {\r\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\r\n          }\r\n        }\r\n        var regex = patternParts[1];\r\n        var k = '' + regex;\r\n        if (!regexKeys.hasOwnProperty(k)) {\r\n          allRegexs.push(regex);\r\n          regexKeys[k] = null;\r\n        }\r\n      }\r\n      allRegexs.push(/[\\0-\\uffff]/);\r\n      tokenizer = combinePrefixPatterns(allRegexs);\r\n    })();\r\n\r\n    var nPatterns = fallthroughStylePatterns.length;\r\n\r\n    /**\r\n     * Lexes job.sourceCode and produces an output array job.decorations of\r\n     * style classes preceded by the position at which they start in\r\n     * job.sourceCode in order.\r\n     *\r\n     * @param {Object} job an object like <pre>{\r\n     *    sourceCode: {string} sourceText plain text,\r\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\r\n     *        sourceCode.\r\n     * }</pre>\r\n     */\r\n    var decorate = function (job) {\r\n      var sourceCode = job.sourceCode, basePos = job.basePos;\r\n      /** Even entries are positions in source in ascending order.  Odd enties\r\n        * are style markers (e.g., PR_COMMENT) that run from that position until\r\n        * the end.\r\n        * @type {Array.<number|string>}\r\n        */\r\n      var decorations = [basePos, PR_PLAIN];\r\n      var pos = 0;  // index into sourceCode\r\n      var tokens = sourceCode.match(tokenizer) || [];\r\n      var styleCache = {};\r\n\r\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\r\n        var token = tokens[ti];\r\n        var style = styleCache[token];\r\n        var match = void 0;\r\n\r\n        var isEmbedded;\r\n        if (typeof style === 'string') {\r\n          isEmbedded = false;\r\n        } else {\r\n          var patternParts = shortcuts[token.charAt(0)];\r\n          if (patternParts) {\r\n            match = token.match(patternParts[1]);\r\n            style = patternParts[0];\r\n          } else {\r\n            for (var i = 0; i < nPatterns; ++i) {\r\n              patternParts = fallthroughStylePatterns[i];\r\n              match = token.match(patternParts[1]);\r\n              if (match) {\r\n                style = patternParts[0];\r\n                break;\r\n              }\r\n            }\r\n\r\n            if (!match) {  // make sure that we make progress\r\n              style = PR_PLAIN;\r\n            }\r\n          }\r\n\r\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\r\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\r\n            isEmbedded = false;\r\n            style = PR_SOURCE;\r\n          }\r\n\r\n          if (!isEmbedded) { styleCache[token] = style; }\r\n        }\r\n\r\n        var tokenStart = pos;\r\n        pos += token.length;\r\n\r\n        if (!isEmbedded) {\r\n          decorations.push(basePos + tokenStart, style);\r\n        } else {  // Treat group 1 as an embedded block of source code.\r\n          var embeddedSource = match[1];\r\n          var embeddedSourceStart = token.indexOf(embeddedSource);\r\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\r\n          if (match[2]) {\r\n            // If embeddedSource can be blank, then it would match at the\r\n            // beginning which would cause us to infinitely recurse on the\r\n            // entire token, so we catch the right context in match[2].\r\n            embeddedSourceEnd = token.length - match[2].length;\r\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\r\n          }\r\n          var lang = style.substring(5);\r\n          // Decorate the left of the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart,\r\n              token.substring(0, embeddedSourceStart),\r\n              decorate, decorations);\r\n          // Decorate the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceStart,\r\n              embeddedSource,\r\n              langHandlerForExtension(lang, embeddedSource),\r\n              decorations);\r\n          // Decorate the right of the embedded section\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceEnd,\r\n              token.substring(embeddedSourceEnd),\r\n              decorate, decorations);\r\n        }\r\n      }\r\n      job.decorations = decorations;\r\n    };\r\n    return decorate;\r\n  }\r\n\r\n  /** returns a function that produces a list of decorations from source text.\r\n    *\r\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\r\n    * escape.  It does not recognize perl's qq() style strings.\r\n    * It has no special handling for double delimiter escapes as in basic, or\r\n    * the tripled delimiters used in python, but should work on those regardless\r\n    * although in those cases a single string literal may be broken up into\r\n    * multiple adjacent string literals.\r\n    *\r\n    * It recognizes C, C++, and shell style comments.\r\n    *\r\n    * @param {Object} options a set of optional parameters.\r\n    * @return {function (Object)} a function that examines the source code\r\n    *     in the input job and builds the decoration list.\r\n    */\r\n  function sourceDecorator(options) {\r\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\r\n    if (options['tripleQuotedStrings']) {\r\n      // '''multi-line-string''', 'single-line-string', and double-quoted\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\r\n           null, '\\'\"']);\r\n    } else if (options['multiLineStrings']) {\r\n      // 'multi-line-string', \"multi-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\r\n           null, '\\'\"`']);\r\n    } else {\r\n      // 'single-line-string', \"single-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,\r\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\r\n           null, '\"\\'']);\r\n    }\r\n    if (options['verbatimStrings']) {\r\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\r\n      fallthroughStylePatterns.push(\r\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\r\n    }\r\n    var hc = options['hashComments'];\r\n    if (hc) {\r\n      if (options['cStyleComments']) {\r\n        if (hc > 1) {  // multiline hash comments\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\r\n        } else {\r\n          // Stop C preprocessor declarations at an unclosed open comment\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\r\n               null, '#']);\r\n        }\r\n        // #include <stdio.h>\r\n        fallthroughStylePatterns.push(\r\n            [PR_STRING,\r\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\r\n             null]);\r\n      } else {\r\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\r\n      }\r\n    }\r\n    if (options['cStyleComments']) {\r\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\r\n      fallthroughStylePatterns.push(\r\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\r\n    }\r\n    var regexLiterals = options['regexLiterals'];\r\n    if (regexLiterals) {\r\n      /**\r\n       * @const\r\n       */\r\n      var regexExcls = regexLiterals > 1\r\n        ? ''  // Multiline regex literals\r\n        : '\\n\\r';\r\n      /**\r\n       * @const\r\n       */\r\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\r\n      /**\r\n       * @const\r\n       */\r\n      var REGEX_LITERAL = (\r\n          // A regular expression literal starts with a slash that is\r\n          // not followed by * or / so that it is not confused with\r\n          // comments.\r\n          '/(?=[^/*' + regexExcls + '])'\r\n          // and then contains any number of raw characters,\r\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\r\n          // escape sequences (\\x5C),\r\n          +    '|\\\\x5C' + regexAny\r\n          // or non-nesting character sets (\\x5B\\x5D);\r\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\r\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\r\n          // finally closed by a /.\r\n          + '/');\r\n      fallthroughStylePatterns.push(\r\n          ['lang-regex',\r\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\r\n           ]);\r\n    }\r\n\r\n    var types = options['types'];\r\n    if (types) {\r\n      fallthroughStylePatterns.push([PR_TYPE, types]);\r\n    }\r\n\r\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\r\n    if (keywords.length) {\r\n      fallthroughStylePatterns.push(\r\n          [PR_KEYWORD,\r\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\r\n           null]);\r\n    }\r\n\r\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\r\n\r\n    var punctuation =\r\n      // The Bash man page says\r\n\r\n      // A word is a sequence of characters considered as a single\r\n      // unit by GRUB. Words are separated by metacharacters,\r\n      // which are the following plus space, tab, and newline: { }\r\n      // | & $ ; < >\r\n      // ...\r\n      \r\n      // A word beginning with # causes that word and all remaining\r\n      // characters on that line to be ignored.\r\n\r\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\r\n      // comment but empirically\r\n      // $ echo {#}\r\n      // {#}\r\n      // $ echo \\$#\r\n      // $#\r\n      // $ echo }#\r\n      // }#\r\n\r\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\r\n\r\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\r\n      // suggests that this definition is compatible with a\r\n      // default mode that tries to use a single token definition\r\n      // to recognize both bash/python style comments and C\r\n      // preprocessor directives.\r\n\r\n      // This definition of punctuation does not include # in the list of\r\n      // follow-on exclusions, so # will not be broken before if preceeded\r\n      // by a punctuation character.  We could try to exclude # after\r\n      // [|&;<>] but that doesn't seem to cause many major problems.\r\n      // If that does turn out to be a problem, we should change the below\r\n      // when hc is truthy to include # in the run of punctuation characters\r\n      // only when not followint [|&;<>].\r\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\r\n    if (options['regexLiterals']) {\r\n      punctuation += '(?!\\s*\\/)';\r\n    }\r\n\r\n    fallthroughStylePatterns.push(\r\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\r\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\r\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_LITERAL,\r\n         new RegExp(\r\n             '^(?:'\r\n             // A hex number\r\n             + '0x[a-f0-9]+'\r\n             // or an octal or decimal number,\r\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\r\n             // possibly in scientific notation\r\n             + '(?:e[+\\\\-]?\\\\d+)?'\r\n             + ')'\r\n             // with an optional modifier like UL for unsigned long\r\n             + '[a-z]*', 'i'),\r\n         null, '0123456789'],\r\n        // Don't treat escaped quotes in bash as starting strings.\r\n        // See issue 144.\r\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\r\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\r\n\r\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\r\n  }\r\n\r\n  var decorateSource = sourceDecorator({\r\n        'keywords': ALL_KEYWORDS,\r\n        'hashComments': true,\r\n        'cStyleComments': true,\r\n        'multiLineStrings': true,\r\n        'regexLiterals': true\r\n      });\r\n\r\n  /**\r\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\r\n   * list item.\r\n   *\r\n   * @param {Node} node modified in place.  Its content is pulled into an\r\n   *     HTMLOListElement, and each line is moved into a separate list item.\r\n   *     This requires cloning elements, so the input might not have unique\r\n   *     IDs after numbering.\r\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\r\n   *     be treated as significant.\r\n   */\r\n  function numberLines(node, opt_startLineNum, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n    var lineBreak = /\\r\\n?|\\n/;\r\n  \r\n    var document = node.ownerDocument;\r\n  \r\n    var li = document.createElement('li');\r\n    while (node.firstChild) {\r\n      li.appendChild(node.firstChild);\r\n    }\r\n    // An array of lines.  We split below, so this is initialized to one\r\n    // un-split line.\r\n    var listItems = [li];\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1 && !nocode.test(node.className)) {  // Element\r\n        if ('br' === node.nodeName) {\r\n          breakAfter(node);\r\n          // Discard the <BR> since it is now flush against a </LI>.\r\n          if (node.parentNode) {\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        } else {\r\n          for (var child = node.firstChild; child; child = child.nextSibling) {\r\n            walk(child);\r\n          }\r\n        }\r\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\r\n        var text = node.nodeValue;\r\n        var match = text.match(lineBreak);\r\n        if (match) {\r\n          var firstLine = text.substring(0, match.index);\r\n          node.nodeValue = firstLine;\r\n          var tail = text.substring(match.index + match[0].length);\r\n          if (tail) {\r\n            var parent = node.parentNode;\r\n            parent.insertBefore(\r\n              document.createTextNode(tail), node.nextSibling);\r\n          }\r\n          breakAfter(node);\r\n          if (!firstLine) {\r\n            // Don't leave blank text nodes in the DOM.\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  \r\n    // Split a line after the given node.\r\n    function breakAfter(lineEndNode) {\r\n      // If there's nothing to the right, then we can skip ending the line\r\n      // here, and move root-wards since splitting just before an end-tag\r\n      // would require us to create a bunch of empty copies.\r\n      while (!lineEndNode.nextSibling) {\r\n        lineEndNode = lineEndNode.parentNode;\r\n        if (!lineEndNode) { return; }\r\n      }\r\n  \r\n      function breakLeftOf(limit, copy) {\r\n        // Clone shallowly if this node needs to be on both sides of the break.\r\n        var rightSide = copy ? limit.cloneNode(false) : limit;\r\n        var parent = limit.parentNode;\r\n        if (parent) {\r\n          // We clone the parent chain.\r\n          // This helps us resurrect important styling elements that cross lines.\r\n          // E.g. in <i>Foo<br>Bar</i>\r\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\r\n          var parentClone = breakLeftOf(parent, 1);\r\n          // Move the clone and everything to the right of the original\r\n          // onto the cloned parent.\r\n          var next = limit.nextSibling;\r\n          parentClone.appendChild(rightSide);\r\n          for (var sibling = next; sibling; sibling = next) {\r\n            next = sibling.nextSibling;\r\n            parentClone.appendChild(sibling);\r\n          }\r\n        }\r\n        return rightSide;\r\n      }\r\n  \r\n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\r\n  \r\n      // Walk the parent chain until we reach an unattached LI.\r\n      for (var parent;\r\n           // Check nodeType since IE invents document fragments.\r\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\r\n        copiedListItem = parent;\r\n      }\r\n      // Put it on the list of lines for later processing.\r\n      listItems.push(copiedListItem);\r\n    }\r\n  \r\n    // Split lines while there are lines left to split.\r\n    for (var i = 0;  // Number of lines that have been split so far.\r\n         i < listItems.length;  // length updated by breakAfter calls.\r\n         ++i) {\r\n      walk(listItems[i]);\r\n    }\r\n  \r\n    // Make sure numeric indices show correctly.\r\n    if (opt_startLineNum === (opt_startLineNum|0)) {\r\n      listItems[0].setAttribute('value', opt_startLineNum);\r\n    }\r\n  \r\n    var ol = document.createElement('ol');\r\n    ol.className = 'linenums';\r\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\r\n    for (var i = 0, n = listItems.length; i < n; ++i) {\r\n      li = listItems[i];\r\n      // Stick a class on the LIs so that stylesheets can\r\n      // color odd/even rows, or any other row pattern that\r\n      // is co-prime with 10.\r\n      li.className = 'L' + ((i + offset) % 10);\r\n      if (!li.firstChild) {\r\n        li.appendChild(document.createTextNode('\\xA0'));\r\n      }\r\n      ol.appendChild(li);\r\n    }\r\n  \r\n    node.appendChild(ol);\r\n  }\r\n  /**\r\n   * Breaks {@code job.sourceCode} around style boundaries in\r\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\r\n   * @param {Object} job like <pre>{\r\n   *    sourceCode: {string} source as plain text,\r\n   *    sourceNode: {HTMLElement} the element containing the source,\r\n   *    spans: {Array.<number|Node>} alternating span start indices into source\r\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\r\n   *       span.\r\n   *    decorations: {Array.<number|string} an array of style classes preceded\r\n   *       by the position at which they start in job.sourceCode in order\r\n   * }</pre>\r\n   * @private\r\n   */\r\n  function recombineTagsAndDecorations(job) {\r\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\r\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\r\n    var newlineRe = /\\n/g;\r\n  \r\n    var source = job.sourceCode;\r\n    var sourceLength = source.length;\r\n    // Index into source after the last code-unit recombined.\r\n    var sourceIndex = 0;\r\n  \r\n    var spans = job.spans;\r\n    var nSpans = spans.length;\r\n    // Index into spans after the last span which ends at or before sourceIndex.\r\n    var spanIndex = 0;\r\n  \r\n    var decorations = job.decorations;\r\n    var nDecorations = decorations.length;\r\n    // Index into decorations after the last decoration which ends at or before\r\n    // sourceIndex.\r\n    var decorationIndex = 0;\r\n  \r\n    // Remove all zero-length decorations.\r\n    decorations[nDecorations] = sourceLength;\r\n    var decPos, i;\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      if (decorations[i] !== decorations[i + 2]) {\r\n        decorations[decPos++] = decorations[i++];\r\n        decorations[decPos++] = decorations[i++];\r\n      } else {\r\n        i += 2;\r\n      }\r\n    }\r\n    nDecorations = decPos;\r\n  \r\n    // Simplify decorations.\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      var startPos = decorations[i];\r\n      // Conflate all adjacent decorations that use the same style.\r\n      var startDec = decorations[i + 1];\r\n      var end = i + 2;\r\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\r\n        end += 2;\r\n      }\r\n      decorations[decPos++] = startPos;\r\n      decorations[decPos++] = startDec;\r\n      i = end;\r\n    }\r\n  \r\n    nDecorations = decorations.length = decPos;\r\n  \r\n    var sourceNode = job.sourceNode;\r\n    var oldDisplay;\r\n    if (sourceNode) {\r\n      oldDisplay = sourceNode.style.display;\r\n      sourceNode.style.display = 'none';\r\n    }\r\n    try {\r\n      var decoration = null;\r\n      while (spanIndex < nSpans) {\r\n        var spanStart = spans[spanIndex];\r\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\r\n  \r\n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\r\n  \r\n        var end = Math.min(spanEnd, decEnd);\r\n  \r\n        var textNode = spans[spanIndex + 1];\r\n        var styledText;\r\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\r\n            // Don't introduce spans around empty text nodes.\r\n            && (styledText = source.substring(sourceIndex, end))) {\r\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\r\n          // code to display with spaces instead of line breaks.\r\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\r\n          // space to appear at the beginning of every line but the first.\r\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\r\n          if (isIE8OrEarlier) {\r\n            styledText = styledText.replace(newlineRe, '\\r');\r\n          }\r\n          textNode.nodeValue = styledText;\r\n          var document = textNode.ownerDocument;\r\n          var span = document.createElement('span');\r\n          span.className = decorations[decorationIndex + 1];\r\n          var parentNode = textNode.parentNode;\r\n          parentNode.replaceChild(span, textNode);\r\n          span.appendChild(textNode);\r\n          if (sourceIndex < spanEnd) {  // Split off a text node.\r\n            spans[spanIndex + 1] = textNode\r\n                // TODO: Possibly optimize by using '' if there's no flicker.\r\n                = document.createTextNode(source.substring(end, spanEnd));\r\n            parentNode.insertBefore(textNode, span.nextSibling);\r\n          }\r\n        }\r\n  \r\n        sourceIndex = end;\r\n  \r\n        if (sourceIndex >= spanEnd) {\r\n          spanIndex += 2;\r\n        }\r\n        if (sourceIndex >= decEnd) {\r\n          decorationIndex += 2;\r\n        }\r\n      }\r\n    } finally {\r\n      if (sourceNode) {\r\n        sourceNode.style.display = oldDisplay;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Maps language-specific file extensions to handlers. */\r\n  var langHandlerRegistry = {};\r\n  /** Register a language handler for the given file extensions.\r\n    * @param {function (Object)} handler a function from source code to a list\r\n    *      of decorations.  Takes a single argument job which describes the\r\n    *      state of the computation.   The single parameter has the form\r\n    *      {@code {\r\n    *        sourceCode: {string} as plain text.\r\n    *        decorations: {Array.<number|string>} an array of style classes\r\n    *                     preceded by the position at which they start in\r\n    *                     job.sourceCode in order.\r\n    *                     The language handler should assigned this field.\r\n    *        basePos: {int} the position of source in the larger source chunk.\r\n    *                 All positions in the output decorations array are relative\r\n    *                 to the larger source chunk.\r\n    *      } }\r\n    * @param {Array.<string>} fileExtensions\r\n    */\r\n  function registerLangHandler(handler, fileExtensions) {\r\n    for (var i = fileExtensions.length; --i >= 0;) {\r\n      var ext = fileExtensions[i];\r\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\r\n        langHandlerRegistry[ext] = handler;\r\n      } else if (win['console']) {\r\n        console['warn']('cannot override language handler %s', ext);\r\n      }\r\n    }\r\n  }\r\n  function langHandlerForExtension(extension, source) {\r\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\r\n      // Treat it as markup if the first non whitespace character is a < and\r\n      // the last non-whitespace character is a >.\r\n      extension = /^\\s*</.test(source)\r\n          ? 'default-markup'\r\n          : 'default-code';\r\n    }\r\n    return langHandlerRegistry[extension];\r\n  }\r\n  registerLangHandler(decorateSource, ['default-code']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [],\r\n          [\r\n           [PR_PLAIN,       /^[^<?]+/],\r\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\r\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\r\n           // Unescaped content in an unknown language\r\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\r\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\r\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\r\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\r\n           // Unescaped content in javascript.  (Or possibly vbscript).\r\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\r\n           // Contains unescaped stylesheet content\r\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\r\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\r\n          ]),\r\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [\r\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\r\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\r\n           ],\r\n          [\r\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\r\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\r\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\r\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\r\n           ]),\r\n      ['in.tag']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CPP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'types': C_TYPES\r\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': 'null,true,false'\r\n        }), ['json']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CSHARP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'verbatimStrings': true,\r\n          'types': C_TYPES\r\n        }), ['cs']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JAVA_KEYWORDS,\r\n          'cStyleComments': true\r\n        }), ['java']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': SH_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true\r\n        }), ['bash', 'bsh', 'csh', 'sh']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PYTHON_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'tripleQuotedStrings': true\r\n        }), ['cv', 'py', 'python']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PERL_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': 2  // multiline regex literals\r\n        }), ['perl', 'pl', 'pm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUBY_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': true\r\n        }), ['rb', 'ruby']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JSCRIPT_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'regexLiterals': true\r\n        }), ['javascript', 'js']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': COFFEE_KEYWORDS,\r\n          'hashComments': 3,  // ### style block comments\r\n          'cStyleComments': true,\r\n          'multilineStrings': true,\r\n          'tripleQuotedStrings': true,\r\n          'regexLiterals': true\r\n        }), ['coffee']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUST_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'multilineStrings': true\r\n        }), ['rc', 'rs', 'rust']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\r\n\r\n  function applyDecorator(job) {\r\n    var opt_langExtension = job.langExtension;\r\n\r\n    try {\r\n      // Extract tags, and convert the source code to plain text.\r\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\r\n      /** Plain text. @type {string} */\r\n      var source = sourceAndSpans.sourceCode;\r\n      job.sourceCode = source;\r\n      job.spans = sourceAndSpans.spans;\r\n      job.basePos = 0;\r\n\r\n      // Apply the appropriate language handler\r\n      langHandlerForExtension(opt_langExtension, source)(job);\r\n\r\n      // Integrate the decorations and tags back into the source code,\r\n      // modifying the sourceNode in place.\r\n      recombineTagsAndDecorations(job);\r\n    } catch (e) {\r\n      if (win['console']) {\r\n        console['log'](e && e['stack'] || e);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Pretty print a chunk of code.\r\n   * @param sourceCodeHtml {string} The HTML to pretty print.\r\n   * @param opt_langExtension {string} The language name to use.\r\n   *     Typically, a filename extension like 'cpp' or 'java'.\r\n   * @param opt_numberLines {number|boolean} True to number lines,\r\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n   */\r\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\r\n    var container = document.createElement('div');\r\n    // This could cause images to load and onload listeners to fire.\r\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\r\n    // We assume that the inner HTML is from a trusted source.\r\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\r\n    // when it is injected into a <pre> tag.\r\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\r\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\r\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\r\n    container = container.firstChild;\r\n    if (opt_numberLines) {\r\n      numberLines(container, opt_numberLines, true);\r\n    }\r\n\r\n    var job = {\r\n      langExtension: opt_langExtension,\r\n      numberLines: opt_numberLines,\r\n      sourceNode: container,\r\n      pre: 1\r\n    };\r\n    applyDecorator(job);\r\n    return container.innerHTML;\r\n  }\r\n\r\n   /**\r\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n    * {@code class=prettyprint} and prettify them.\r\n    *\r\n    * @param {Function} opt_whenDone called when prettifying is done.\r\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n    *   containing all the elements to pretty print.\r\n    *   Defaults to {@code document.body}.\r\n    */\r\n  function $prettyPrint(opt_whenDone, opt_root) {\r\n    var root = opt_root || document.body;\r\n    var doc = root.ownerDocument || document;\r\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\r\n    // fetch a list of nodes to rewrite\r\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\r\n    var elements = [];\r\n    for (var i = 0; i < codeSegments.length; ++i) {\r\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\r\n        elements.push(codeSegments[i][j]);\r\n      }\r\n    }\r\n    codeSegments = null;\r\n\r\n    var clock = Date;\r\n    if (!clock['now']) {\r\n      clock = { 'now': function () { return +(new Date); } };\r\n    }\r\n\r\n    // The loop is broken into a series of continuations to make sure that we\r\n    // don't make the browser unresponsive when rewriting a large page.\r\n    var k = 0;\r\n    var prettyPrintingJob;\r\n\r\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\r\n    var prettyPrintRe = /\\bprettyprint\\b/;\r\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\r\n    var preformattedTagNameRe = /pre|xmp/i;\r\n    var codeRe = /^code$/i;\r\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\r\n    var EMPTY = {};\r\n\r\n    function doWork() {\r\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\r\n                     clock['now']() + 250 /* ms */ :\r\n                     Infinity);\r\n      for (; k < elements.length && clock['now']() < endTime; k++) {\r\n        var cs = elements[k];\r\n\r\n        // Look for a preceding comment like\r\n        // <?prettify lang=\"...\" linenums=\"...\"?>\r\n        var attrs = EMPTY;\r\n        {\r\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\r\n            var nt = preceder.nodeType;\r\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\r\n            // like <!--?foo?-->, but in XML is a processing instruction\r\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\r\n            if (value\r\n                ? !/^\\??prettify\\b/.test(value)\r\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\r\n              // Skip over white-space text nodes but not others.\r\n              break;\r\n            }\r\n            if (value) {\r\n              attrs = {};\r\n              value.replace(\r\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\r\n                function (_, name, value) { attrs[name] = value; });\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        var className = cs.className;\r\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\r\n            // Don't redo this if we've already done it.\r\n            // This allows recalling pretty print to just prettyprint elements\r\n            // that have been added to the page since last call.\r\n            && !prettyPrintedRe.test(className)) {\r\n\r\n          // make sure this is not nested in an already prettified element\r\n          var nested = false;\r\n          for (var p = cs.parentNode; p; p = p.parentNode) {\r\n            var tn = p.tagName;\r\n            if (preCodeXmpRe.test(tn)\r\n                && p.className && prettyPrintRe.test(p.className)) {\r\n              nested = true;\r\n              break;\r\n            }\r\n          }\r\n          if (!nested) {\r\n            // Mark done.  If we fail to prettyprint for whatever reason,\r\n            // we shouldn't try again.\r\n            cs.className += ' prettyprinted';\r\n\r\n            // If the classes includes a language extensions, use it.\r\n            // Language extensions can be specified like\r\n            //     <pre class=\"prettyprint lang-cpp\">\r\n            // the language extension \"cpp\" is used to find a language handler\r\n            // as passed to PR.registerLangHandler.\r\n            // HTML5 recommends that a language be specified using \"language-\"\r\n            // as the prefix instead.  Google Code Prettify supports both.\r\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\r\n            var langExtension = attrs['lang'];\r\n            if (!langExtension) {\r\n              langExtension = className.match(langExtensionRe);\r\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\r\n              var wrapper;\r\n              if (!langExtension && (wrapper = childContentWrapper(cs))\r\n                  && codeRe.test(wrapper.tagName)) {\r\n                langExtension = wrapper.className.match(langExtensionRe);\r\n              }\r\n\r\n              if (langExtension) { langExtension = langExtension[1]; }\r\n            }\r\n\r\n            var preformatted;\r\n            if (preformattedTagNameRe.test(cs.tagName)) {\r\n              preformatted = 1;\r\n            } else {\r\n              var currentStyle = cs['currentStyle'];\r\n              var defaultView = doc.defaultView;\r\n              var whitespace = (\r\n                  currentStyle\r\n                  ? currentStyle['whiteSpace']\r\n                  : (defaultView\r\n                     && defaultView.getComputedStyle)\r\n                  ? defaultView.getComputedStyle(cs, null)\r\n                  .getPropertyValue('white-space')\r\n                  : 0);\r\n              preformatted = whitespace\r\n                  && 'pre' === whitespace.substring(0, 3);\r\n            }\r\n\r\n            // Look for a class like linenums or linenums:<n> where <n> is the\r\n            // 1-indexed number of the first line.\r\n            var lineNums = attrs['linenums'];\r\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\r\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\r\n              lineNums =\r\n                lineNums\r\n                ? lineNums[1] && lineNums[1].length\r\n                  ? +lineNums[1] : true\r\n                : false;\r\n            }\r\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\r\n\r\n            // do the pretty printing\r\n            prettyPrintingJob = {\r\n              langExtension: langExtension,\r\n              sourceNode: cs,\r\n              numberLines: lineNums,\r\n              pre: preformatted\r\n            };\r\n            applyDecorator(prettyPrintingJob);\r\n          }\r\n        }\r\n      }\r\n      if (k < elements.length) {\r\n        // finish up in a continuation\r\n        setTimeout(doWork, 250);\r\n      } else if ('function' === typeof opt_whenDone) {\r\n        opt_whenDone();\r\n      }\r\n    }\r\n\r\n    doWork();\r\n  }\r\n\r\n  /**\r\n   * Contains functions for creating and registering new language handlers.\r\n   * @type {Object}\r\n   */\r\n  var PR = win['PR'] = {\r\n        'createSimpleLexer': createSimpleLexer,\r\n        'registerLangHandler': registerLangHandler,\r\n        'sourceDecorator': sourceDecorator,\r\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\r\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\r\n        'PR_COMMENT': PR_COMMENT,\r\n        'PR_DECLARATION': PR_DECLARATION,\r\n        'PR_KEYWORD': PR_KEYWORD,\r\n        'PR_LITERAL': PR_LITERAL,\r\n        'PR_NOCODE': PR_NOCODE,\r\n        'PR_PLAIN': PR_PLAIN,\r\n        'PR_PUNCTUATION': PR_PUNCTUATION,\r\n        'PR_SOURCE': PR_SOURCE,\r\n        'PR_STRING': PR_STRING,\r\n        'PR_TAG': PR_TAG,\r\n        'PR_TYPE': PR_TYPE,\r\n        'prettyPrintOne':\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\r\n             : (prettyPrintOne = $prettyPrintOne),\r\n        'prettyPrint': prettyPrint =\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrint'] = $prettyPrint)\r\n             : (prettyPrint = $prettyPrint)\r\n      };\r\n\r\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\r\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\r\n  // The Asynchronous Module Definition (AMD) API specifies a\r\n  // mechanism for defining modules such that the module and its\r\n  // dependencies can be asynchronously loaded.\r\n  // ...\r\n  // To allow a clear indicator that a global define function (as\r\n  // needed for script src browser loading) conforms to the AMD API,\r\n  // any global define function SHOULD have a property called \"amd\"\r\n  // whose value is an object. This helps avoid conflict with any\r\n  // other existing JavaScript code that could have defined a define()\r\n  // function that does not conform to the AMD API.\r\n  if (typeof define === \"function\" && define['amd']) {\r\n    define(\"google-code-prettify\", [], function () {\r\n      return PR; \r\n    });\r\n  }\r\n})();\r\n\ndefine(\"prettify\", function(){});\n\n",
        +    "define('itemView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/item.html',\r\n  'text!tpl/class.html',\r\n  'text!tpl/itemEnd.html',\r\n  // Tools\r\n  'prettify'\r\n], function(App, itemTpl, classTpl, endTpl) {\r\n  'use strict';\r\n\r\n  var appVersion = App.project.version || 'master';\r\n\r\n  var itemView = Backbone.View.extend({\r\n    el: '#item',\r\n    init: function() {\r\n      this.$html = $('html');\r\n      this.$body = $('body');\r\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\r\n\r\n      this.tpl = _.template(itemTpl);\r\n      this.classTpl = _.template(classTpl);\r\n      this.endTpl = _.template(endTpl);\r\n\r\n      return this;\r\n    },\r\n    getSyntax: function(isMethod, cleanItem) {\r\n      var isConstructor = cleanItem.is_constructor;\r\n      var syntax = '';\r\n      if (isConstructor) {\r\n        syntax += 'new ';\r\n      } else if (cleanItem.static && cleanItem.class) {\r\n        syntax += cleanItem.class + '.';\r\n      }\r\n      syntax += cleanItem.name;\r\n\r\n      if (isMethod || isConstructor) {\r\n        syntax += '(';\r\n        if (cleanItem.params) {\r\n          for (var i = 0; i < cleanItem.params.length; i++) {\r\n            var p = cleanItem.params[i];\r\n            if (p.optional) {\r\n              syntax += '[';\r\n            }\r\n            syntax += p.name;\r\n            if (p.optdefault) {\r\n              syntax += '=' + p.optdefault;\r\n            }\r\n            if (p.optional) {\r\n              syntax += ']';\r\n            }\r\n            if (i !== cleanItem.params.length - 1) {\r\n              syntax += ', ';\r\n            }\r\n          }\r\n        }\r\n        syntax += ')';\r\n      }\r\n\r\n      return syntax;\r\n    },\r\n    // Return a list of valid syntaxes across all overloaded versions of\r\n    // this item.\r\n    //\r\n    // For reference, we ultimately want to replicate something like this:\r\n    //\r\n    // https://processing.org/reference/color_.html\r\n    getSyntaxes: function(isMethod, cleanItem) {\r\n      var overloads = cleanItem.overloads || [cleanItem];\r\n      return overloads.map(this.getSyntax.bind(this, isMethod));\r\n    },\r\n    render: function(item) {\r\n      if (item) {\r\n        var itemHtml = '';\r\n        var cleanItem = this.clean(item);\r\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\r\n        var collectionName = isClass\r\n            ? 'Constructor'\r\n            : this.capitalizeFirst(cleanItem.itemtype),\r\n          isConstructor = cleanItem.is_constructor;\r\n        cleanItem.isMethod = collectionName === 'Method';\r\n\r\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\r\n\r\n        // Set the item header (title)\r\n\r\n        // Set item contents\r\n        if (isClass) {\r\n          var constructor = this.tpl({\r\n            item: cleanItem,\r\n            isClass: true,\r\n            isConstructor: isConstructor,\r\n            syntaxes: syntaxes\r\n          });\r\n          cleanItem.constructor = constructor;\r\n\r\n          var contents = _.find(App.classes, function(c) {\r\n            return c.name === cleanItem.name;\r\n          });\r\n          cleanItem.things = contents.items;\r\n\r\n          itemHtml = this.classTpl(cleanItem);\r\n        } else {\r\n          cleanItem.constRefs =\r\n            item.module === 'Constants' && App.data.consts[item.name];\r\n\r\n          itemHtml = this.tpl({\r\n            item: cleanItem,\r\n            isClass: false,\r\n            isConstructor: false,\r\n            syntaxes: syntaxes\r\n          });\r\n        }\r\n\r\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\r\n\r\n        // Insert the view in the dom\r\n        this.$el.html(itemHtml);\r\n\r\n        renderCode(cleanItem.name);\r\n\r\n        // Set the document title based on the item name.\r\n        // If it is a method, add parentheses to the name\r\n        if (item.itemtype === 'method') {\r\n          App.pageView.appendToDocumentTitle(item.name + '()');\r\n        } else {\r\n          App.pageView.appendToDocumentTitle(item.name);\r\n        }\r\n\r\n        // Hook up alt-text for examples\r\n        setTimeout(function() {\r\n          var alts = $('.example-content')[0];\r\n          if (alts) {\r\n            alts = $(alts)\r\n              .data('alt')\r\n              .split('\\n');\r\n\r\n            var canvases = $('.cnv_div');\r\n            for (var j = 0; j < alts.length; j++) {\r\n              if (j < canvases.length) {\r\n                $(canvases[j]).append(\r\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\r\n                );\r\n              }\r\n            }\r\n          }\r\n        }, 1000);\r\n        Prism.highlightAll();\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Clean item properties: url encode properties containing paths.\r\n     * @param {object} item The item object.\r\n     * @returns {object} Returns the same item object with urlencoded paths.\r\n     */\r\n    clean: function(item) {\r\n      var cleanItem = item;\r\n\r\n      if (cleanItem.hasOwnProperty('file')) {\r\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\r\n      }\r\n      return cleanItem;\r\n    },\r\n    /**\r\n     * Show a single item.\r\n     * @param {object} item Item object.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function(item) {\r\n      if (item) {\r\n        this.render(item);\r\n      }\r\n\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      this.scrollTop();\r\n      $('#item').focus();\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a message if no item is found.\r\n     * @returns {object} This view.\r\n     */\r\n    nothingFound: function() {\r\n      this.$el.html(\r\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\r\n      );\r\n      App.pageView.hideContentViews();\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Scroll to the top of the window with an animation.\r\n     */\r\n    scrollTop: function() {\r\n      // Hack for Chrome/Firefox scroll animation\r\n      // Chrome scrolls 'body', Firefox scrolls 'html'\r\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\r\n      if (scroll) {\r\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\r\n      }\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function(str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n  });\r\n\r\n  return itemView;\r\n});\r\n\n",
        +    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\r\\n  <br>\\r\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\r\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\r\\n</div>\\r\\n\\r\\n<div id=\\'collection-list-categories\\'>\\r\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\r\\n<% var i=0; %>\\r\\n<% var max=Math.floor(groups.length/4); %>\\r\\n<% var rem=groups.length%4; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% var m = rem > 0 ? 1 : 0 %>\\r\\n  <% if (i === 0) { %>\\r\\n    <ul aria-labelledby=\"categories\">\\r\\n    <% } %>\\r\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\r\\n    <% if (i === (max+m-1)) { %>\\r\\n    </ul>\\r\\n  \\t<% rem-- %>\\r\\n  \\t<% i=0 %>\\r\\n  <% } else { %>\\r\\n  \\t<% i++ %>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        +    "define('menuView',[\r\n  'App',\r\n  'text!tpl/menu.html'\r\n], function(App, menuTpl) {\r\n\r\n  var menuView = Backbone.View.extend({\r\n    el: '#collection-list-nav',\r\n    /**\r\n     * Init.\r\n     * @returns {object} This view.\r\n     */\r\n    init: function() {\r\n      this.menuTpl = _.template(menuTpl);\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     * @returns {object} This view.\r\n     */\r\n    render: function() {\r\n\r\n      var groups = [];\r\n      _.each(App.modules, function (item, i) {\r\n        if (!item.is_submodule) {\r\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n            groups.push(item.name);\r\n          }\r\n        }\r\n        //}\r\n      });\r\n\r\n      // Sort groups by name A-Z\r\n      groups.sort();\r\n\r\n      var menuHtml = this.menuTpl({\r\n        'groups': groups\r\n      });\r\n\r\n      // Render the view\r\n      this.$el.html(menuHtml);\r\n    },\r\n\r\n    hide: function() {\r\n      this.$el.hide();\r\n    },\r\n\r\n    show: function() {\r\n      this.$el.show();\r\n    },\r\n\r\n    /**\r\n     * Update the menu.\r\n     * @param {string} el The name of the current route.\r\n     */\r\n    update: function(menuItem) {\r\n      //console.log(menuItem);\r\n      // this.$menuItems.removeClass('active');\r\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\r\n\r\n    }\r\n  });\r\n\r\n  return menuView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\r\\n\\r\\n<p><%= module.description %></p>\\r\\n\\r\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\r\\n\\r\\n<% var t = 0; col = 0; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% if (t == 0) { %> \\r\\n    <div class=\"column_<%=col%>\">\\r\\n  <% } %>\\r\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\r\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\r\\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\r\\n    <% if (group.hash) { %> </a> <% } %>\\r\\n  <% } %>\\r\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\r\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\r\\n    <% t++; %>\\r\\n  <% }); %>\\r\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\r\\n    </div>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        +    "define(\r\n  'libraryView',[\r\n    'App',\r\n    // Templates\r\n    'text!tpl/library.html'\r\n  ],\r\n  function(App, libraryTpl) {\r\n    var libraryView = Backbone.View.extend({\r\n      el: '#list',\r\n      events: {},\r\n      /**\r\n       * Init.\r\n       */\r\n      init: function() {\r\n        this.libraryTpl = _.template(libraryTpl);\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Render the list.\r\n       */\r\n      render: function(m, listCollection) {\r\n        if (m && listCollection) {\r\n          var self = this;\r\n\r\n          // Render items and group them by module\r\n          // module === group\r\n          this.groups = {};\r\n          _.each(m.items, function(item, i) {\r\n            var module = item.module || '_';\r\n            var group;\r\n            // Override default group with a selected category\r\n            // TODO: Overwriting with the first category might not be the best choice\r\n            // We might also want to have links for categories\r\n            if (item.category && item.category[0]) {\r\n              group = item.category[0];\r\n              // Populate item.hash\r\n              App.router.getHash(item);\r\n\r\n              // Create a group list without link hash\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: undefined,\r\n                  items: []\r\n                };\r\n              }\r\n            } else {\r\n              group = item.class || '_';\r\n              var hash = App.router.getHash(item);\r\n\r\n              var ind = hash.lastIndexOf('/');\r\n              hash = hash.substring(0, ind);\r\n\r\n              // Create a group list\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: hash,\r\n                  items: []\r\n                };\r\n              }\r\n            }\r\n\r\n            self.groups[group].items.push(item);\r\n          });\r\n\r\n          // Sort groups by name A-Z\r\n          self.groups = _.sortBy(self.groups, this.sortByName);\r\n\r\n          // Put the <li> items html into the list <ul>\r\n          var libraryHtml = self.libraryTpl({\r\n            title: self.capitalizeFirst(listCollection),\r\n            module: m.module,\r\n            totalItems: m.items.length,\r\n            groups: self.groups\r\n          });\r\n\r\n          // Render the view\r\n          this.$el.html(libraryHtml);\r\n        }\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Show a list of items.\r\n       * @param {array} items Array of item objects.\r\n       * @returns {object} This view.\r\n       */\r\n      show: function(listGroup) {\r\n        if (App[listGroup]) {\r\n          this.render(App[listGroup], listGroup);\r\n        }\r\n        App.pageView.hideContentViews();\r\n\r\n        this.$el.show();\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Helper method to capitalize the first letter of a string\r\n       * @param {string} str\r\n       * @returns {string} Returns the string.\r\n       */\r\n      capitalizeFirst: function(str) {\r\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n      },\r\n      /**\r\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\r\n       * @param {string} a\r\n       * @param {string} b\r\n       * @returns {Array} Returns an array with elements sorted from A to Z.\r\n       */\r\n      sortAZ: function(a, b) {\r\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\r\n      },\r\n\r\n      sortByName: function(a, b) {\r\n        if (a.name === 'p5') return -1;\r\n        else return 0;\r\n      }\r\n    });\r\n\r\n    return libraryView;\r\n  }\r\n);\r\n\n",
        +    "define('pageView',[\r\n  'App',\r\n\r\n  // Views\r\n  'searchView',\r\n  'listView',\r\n  'itemView',\r\n  'menuView',\r\n  'libraryView'\r\n], function(App, searchView, listView, itemView, menuView, libraryView) {\r\n\r\n  // Store the original title parts so we can substitue different endings.\r\n  var _originalDocumentTitle = window.document.title;\r\n\r\n  var pageView = Backbone.View.extend({\r\n    el: 'body',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      App.$container = $('#container');\r\n      App.contentViews = [];\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     */\r\n    render: function() {\r\n\r\n      // Menu view\r\n      if (!App.menuView) {\r\n        App.menuView = new menuView();\r\n        App.menuView.init().render();\r\n      }\r\n\r\n      // Item view\r\n      if (!App.itemView) {\r\n        App.itemView = new itemView();\r\n        App.itemView.init().render();\r\n        // Add the item view to the views array\r\n        App.contentViews.push(App.itemView);\r\n      }\r\n\r\n      // List view\r\n      if (!App.listView) {\r\n        App.listView = new listView();\r\n        App.listView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.listView);\r\n      }\r\n\r\n      // Library view\r\n      if (!App.libraryView) {\r\n        App.libraryView = new libraryView();\r\n        App.libraryView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.libraryView);\r\n      }\r\n\r\n      // Search\r\n      if (!App.searchView) {\r\n        App.searchView = new searchView();\r\n        App.searchView.init().render();\r\n      }\r\n      return this;\r\n    },\r\n    /**\r\n     * Hide item and list views.\r\n     * @returns {object} This view.\r\n     */\r\n    hideContentViews: function() {\r\n      _.each(App.contentViews, function(view, i) {\r\n        view.$el.hide();\r\n      });\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Append the supplied name to the first part of original document title.\r\n     * If no name is supplied, the title will reset to the original one.\r\n     */\r\n    appendToDocumentTitle: function(name){\r\n      if(name){\r\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\r\n        window.document.title = [firstTitlePart, name].join(\" | \");\r\n      } else {\r\n        window.document.title = _originalDocumentTitle;\r\n      }\r\n    }    \r\n  });\r\n\r\n  return pageView;\r\n\r\n});\r\n\n",
        +    "define('router',[\r\n  'App'\r\n], function(App) {\r\n\r\n  'use strict'; //\r\n\r\n  var Router = Backbone.Router.extend({\r\n\r\n    routes: {\r\n      '': 'list',\r\n      'p5': 'list',\r\n      'p5/': 'list',\r\n      'classes': 'list',\r\n      'search': 'search',\r\n      'libraries/:lib': 'library',\r\n      ':searchClass(/:searchItem)': 'get'\r\n    },\r\n    /**\r\n     * Whether the json API data was loaded.\r\n     */\r\n    _initialized: false,\r\n    /**\r\n     * Initialize the app: load json API data and create searchable arrays.\r\n     */\r\n    init: function(callback) {\r\n      var self = this;\r\n      require(['pageView'], function(pageView) {\r\n\r\n        // If already initialized, move away from here!\r\n        if (self._initialized) {\r\n          if (callback)\r\n            callback();\r\n          return;\r\n        }\r\n\r\n        // Update initialization state: must be done now to avoid recursive mess\r\n        self._initialized = true;\r\n\r\n        // Render views\r\n        if (!App.pageView) {\r\n          App.pageView = new pageView();\r\n          App.pageView.init().render();\r\n        }\r\n\r\n        // If a callback is set (a route has already been called), run it\r\n        // otherwise, show the default list\r\n        if (callback)\r\n          callback();\r\n        else\r\n          self.list();\r\n      });\r\n    },\r\n    /**\r\n     * Start route. Simply check if initialized.\r\n     */\r\n    start: function() {\r\n      this.init();\r\n    },\r\n    /**\r\n     * Show item details by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     */\r\n    get: function(searchClass, searchItem) {\r\n\r\n      // if looking for a library page, redirect\r\n      if (searchClass === 'p5.sound' && !searchItem) {\r\n        window.location.hash = '/libraries/'+searchClass;\r\n        return;\r\n      }\r\n\r\n      var self = this;\r\n      this.init(function() {\r\n        var item = self.getItem(searchClass, searchItem);\r\n\r\n        App.menuView.hide();\r\n\r\n        if (item) {\r\n          App.itemView.show(item);\r\n        } else {\r\n          //App.itemView.nothingFound();\r\n\r\n          self.list();\r\n        }\r\n\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Returns one item object by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     * @returns {object} The item found or undefined if nothing was found.\r\n     */\r\n    getItem: function(searchClass, searchItem) {\r\n      var classes = App.classes,\r\n              items = App.allItems,\r\n              classesCount = classes.length,\r\n              itemsCount = items.length,\r\n              className = searchClass ? searchClass.toLowerCase() : undefined,\r\n              itemName = searchItem ? searchItem : undefined,\r\n              found;\r\n\r\n      // Only search for a class, if itemName is undefined\r\n      if (className && !itemName) {\r\n        for (var i = 0; i < classesCount; i++) {\r\n          if (classes[i].name.toLowerCase() === className) {\r\n            found = classes[i];\r\n            _.each(found.items, function(i, idx) {\r\n              i.hash = App.router.getHash(i);\r\n            });\r\n            break;\r\n          }\r\n        }\r\n        // Search for a class item\r\n      } else if (className && itemName) {\r\n        // Search case sensitively\r\n        for (var i = 0; i < itemsCount; i++) {\r\n          if (items[i].class.toLowerCase() === className &&\r\n            items[i].name === itemName) {\r\n            found = items[i];\r\n            break;\r\n          }\r\n        }\r\n\r\n        // If no match was found, fallback to search case insensitively\r\n        if(!found){\r\n          for (var i = 0; i < itemsCount; i++) {\r\n            if(items[i].class.toLowerCase() === className &&\r\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\r\n              found = items[i];\r\n              break;\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      return found;\r\n    },\r\n    /**\r\n     * List items.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    list: function(collection) {\r\n\r\n      collection = 'allItems';\r\n\r\n      // Make sure collection is valid\r\n      if (App.collections.indexOf(collection) < 0) {\r\n        return;\r\n      }\r\n\r\n      this.init(function() {\r\n        App.menuView.show(collection);\r\n        App.menuView.update(collection);\r\n        App.listView.show(collection);\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Display information for a library.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    library: function(collection) {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.libraryView.show(collection.substring(3)); //remove p5.\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Close all content views.\r\n     */\r\n    search: function() {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.pageView.hideContentViews();\r\n      });\r\n    },\r\n\r\n    /**\r\n     * Create an hash/url for the item.\r\n     * @param {Object} item A class, method, property or event object.\r\n     * @returns {String} The hash string, including the '#'.\r\n     */\r\n     getHash: function(item) {\r\n\r\n       if (!item.hash) {\r\n\r\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\r\n\r\n         if (item.class) {\r\n           var clsFunc = '#/' + item.class + '.' + item.name;\r\n           var idx = clsFunc.lastIndexOf('.');\r\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\r\n         } else {\r\n          item.hash = '#/' + item.name;\r\n         }\r\n       }\r\n\r\n       return item.hash;\r\n    }\r\n  });\r\n\r\n  \r\n  function styleCodeLinks() {\r\n    var links = document.getElementsByTagName(\"a\");\r\n    for (var iLink = 0; iLink < links.length; iLink++) {\r\n      var link = links[iLink];\r\n      if (link.hash.startsWith('#/p5')) {\r\n        link.classList.add('code');\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n  // Get the router\r\n  App.router = new Router();\r\n\r\n  // Start history\r\n  Backbone.history.start();\r\n\r\n  return App.router;\r\n\r\n});\r\n\n",
        +    "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
             "}());"
           ]
         }
        \ No newline at end of file
        diff --git a/src/templates/partials/i18n.hbs b/src/templates/partials/i18n.hbs
        index 7f4d7bfafa..8f7138ae7d 100644
        --- a/src/templates/partials/i18n.hbs
        +++ b/src/templates/partials/i18n.hbs
        @@ -7,7 +7,7 @@ titne: language buttons
           <ul id="i18n-buttons" aria-labelledby="i18n-settings">
             <li><a href='#' lang='en' data-lang='en'>English</a></li>
             <li><a href='#' lang='es' data-lang='es'>Español</a></li>
        -    <li><a href='#' lang='ko' data-lang='ko'>한국어</a></li>
             <li><a href='#' lang='zh-Hans' data-lang='zh-Hans'>简体中文</a></li>
        +    <li><a href='#' lang='ko' data-lang='ko'>한국어</a></li>
           </ul>
         </div>
        \ No newline at end of file
        
        From 26096ec10f7b86a92eb3155902eb883b813e1bbf Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Thu, 9 Apr 2020 13:54:15 +0900
        Subject: [PATCH 09/36] second push for Korean translation - examples
        
        ---
         Gruntfile.js                                  |    2 +-
         i18n-tracking.yml                             | 1248 +++++++++++++----
         package-lock.json                             |  135 +-
         package.json                                  |    1 +
         .../ko/00_Structure/00_Coordinates.js         |   34 +
         .../ko/00_Structure/01_Width_and_Height.js    |   19 +
         .../ko/00_Structure/02_Setup_and_Draw.js      |   25 +
         .../examples/ko/00_Structure/03_No_Loop.js    |   28 +
         src/data/examples/ko/00_Structure/04_Loop.js  |   24 +
         .../examples/ko/00_Structure/05_Redraw.js     |   31 +
         .../examples/ko/00_Structure/06_Functions.js  |   27 +
         .../examples/ko/00_Structure/07_Recursion.js  |   27 +
         .../ko/00_Structure/08_Create_Graphics.js     |   29 +
         .../ko/01_Form/00_Points_and_Lines.js         |   36 +
         .../ko/01_Form/01_Shape_Primitives.js         |   31 +
         src/data/examples/ko/01_Form/02_Pie_Chart.js  |   33 +
         .../examples/ko/01_Form/03_Regular_Polygon.js |   42 +
         src/data/examples/ko/01_Form/04_Star.js       |   45 +
         .../examples/ko/01_Form/05_Triangle_Strip.js  |   38 +
         src/data/examples/ko/01_Form/06_Bezier.js     |   26 +
         .../examples/ko/01_Form/07_3D_Primitives.js   |   30 +
         src/data/examples/ko/02_Data/00_Variables.js  |   36 +
         .../examples/ko/02_Data/01_True_and_False.js  |   30 +
         .../examples/ko/02_Data/03_Variable_Scope.js  |   44 +
         src/data/examples/ko/02_Data/04_Numbers.js    |   30 +
         src/data/examples/ko/03_Arrays/00_Array.js    |   42 +
         src/data/examples/ko/03_Arrays/01_Array_2d.js |   37 +
         .../examples/ko/03_Arrays/02_Array_Objects.js |   71 +
         .../examples/ko/04_Control/00_Iteration.js    |   41 +
         .../ko/04_Control/01_Embedded_Iteration.js    |   21 +
         .../ko/04_Control/02_Conditionals_1.js        |   24 +
         .../ko/04_Control/03_Conditionals_2.js        |   27 +
         .../ko/04_Control/04_Logical_Operators.js     |   43 +
         .../ko/05_Image/00_Load_and_Display_Image.js  |   19 +
         .../ko/05_Image/01_Background_Image.js        |   30 +
         .../examples/ko/05_Image/02_Transparency.js   |   23 +
         .../examples/ko/05_Image/03_Alpha_Mask.js     |   26 +
         .../examples/ko/05_Image/04_Create_Image.js   |   25 +
         .../examples/ko/05_Image/05_Pointillism.js    |   32 +
         src/data/examples/ko/07_Color/00_Hue.js       |   25 +
         .../examples/ko/07_Color/01_Saturation.js     |   24 +
         .../examples/ko/07_Color/02_Brightness.js     |   46 +
         .../ko/07_Color/03_Color_Variables.js         |   40 +
         .../examples/ko/07_Color/04_Relativity.js     |   34 +
         .../ko/07_Color/05_Linear_Gradient.js         |   51 +
         .../ko/07_Color/06_Radial_Gradient.js         |   32 +
         .../examples/ko/07_Color/07_Lerp_Color.js     |   49 +
         .../ko/08_Math/00_incrementdecrement.js       |   42 +
         .../ko/08_Math/01_operatorprecedence.js       |   51 +
         src/data/examples/ko/08_Math/02_distance1d.js |   64 +
         src/data/examples/ko/08_Math/03_distance2d.js |   24 +
         src/data/examples/ko/08_Math/04_sine.js       |   27 +
         src/data/examples/ko/08_Math/05_sincosine.js  |   43 +
         src/data/examples/ko/08_Math/06_sinewave.js   |   47 +
         .../examples/ko/08_Math/07_additivewave.js    |   67 +
         .../ko/08_Math/08_polartocartesian.js         |   44 +
         src/data/examples/ko/08_Math/09_arctangent.js |   45 +
         .../examples/ko/08_Math/10_Interpolate.js     |   32 +
         .../examples/ko/08_Math/11_doubleRandom.js    |   24 +
         src/data/examples/ko/08_Math/12_random.js     |   19 +
         src/data/examples/ko/08_Math/13_noise1D.js    |   31 +
         src/data/examples/ko/08_Math/14_noisewave.js  |   42 +
         src/data/examples/ko/08_Math/15_Noise2D.js    |   42 +
         src/data/examples/ko/08_Math/16_Noise3D.js    |   48 +
         .../examples/ko/08_Math/17_Randomchords.js    |   35 +
         src/data/examples/ko/08_Math/18_Map.js        |   21 +
         src/data/examples/ko/09_Simulate/00_Forces.js |  147 ++
         .../ko/09_Simulate/01_ParticleSystem.js       |   69 +
         .../examples/ko/09_Simulate/02_Flocking.js    |  229 +++
         .../examples/ko/09_Simulate/03_WolframCA.js   |   73 +
         .../examples/ko/09_Simulate/04_GameOfLife.js  |   95 ++
         .../09_Simulate/05_MultipleParticleSystems.js |  137 ++
         .../examples/ko/09_Simulate/06_Spirograph.js  |   73 +
         .../examples/ko/09_Simulate/07_LSystems.js    |  105 ++
         src/data/examples/ko/09_Simulate/08_Spring.js |   92 ++
         .../examples/ko/09_Simulate/09_Springs.js     |  147 ++
         .../examples/ko/09_Simulate/10_SoftBody.js    |  110 ++
         .../ko/09_Simulate/11_SmokeParticleSystem.js  |  181 +++
         .../ko/09_Simulate/12_BrownianMotion.js       |   46 +
         src/data/examples/ko/09_Simulate/13_Chain.js  |   56 +
         .../09_Simulate/14_SnowflakeParticleSystem.js |   63 +
         .../ko/09_Simulate/15_penrose_tiles.js        |  125 ++
         .../ko/09_Simulate/16_Recursive_Tree.js       |   55 +
         .../examples/ko/09_Simulate/17_Mandelbrot.js  |   86 ++
         .../examples/ko/10_Interaction/10_Tickle.js   |   48 +
         .../examples/ko/10_Interaction/20_Follow1.js  |   37 +
         .../examples/ko/10_Interaction/21_Follow2.js  |   39 +
         .../examples/ko/10_Interaction/22_Follow3.js  |   47 +
         .../examples/ko/10_Interaction/23_snake.js    |  172 +++
         .../ko/10_Interaction/24_Wavemaker.js         |   38 +
         .../examples/ko/10_Interaction/25_reach1.js   |   57 +
         .../examples/ko/10_Interaction/26_reach2.js   |   65 +
         .../examples/ko/10_Interaction/27_reach3.js   |   81 ++
         src/data/examples/ko/11_Objects/01_Objects.js |   39 +
         .../ko/11_Objects/02_Multiple_Objects.js      |   50 +
         .../ko/11_Objects/03_Objects_Array.js         |   42 +
         .../03_Objects_Optional_Arguments.js          |   65 +
         .../examples/ko/11_Objects/04_Inheritance.js  |   71 +
         .../examples/ko/12_Lights/02_Directional.js   |   28 +
         src/data/examples/ko/12_Lights/05_Mixture.js  |   26 +
         .../13_Motion/01_non_orthogonal_reflection.js |  110 ++
         .../examples/ko/13_Motion/02_Linear_Motion.js |   24 +
         src/data/examples/ko/13_Motion/03_Bounce.js   |   44 +
         .../ko/13_Motion/04_Bouncy_Bubbles.js         |   95 ++
         src/data/examples/ko/13_Motion/05_Morph.js    |   92 ++
         .../ko/13_Motion/06_Moving_On_Curves.js       |   47 +
         .../ko/15_Instance_Mode/01_Instantiating.js   |   35 +
         .../15_Instance_Mode/02_Instance_Container.js |   92 ++
         .../examples/ko/16_Dom/03_Input_Button.js     |   41 +
         src/data/examples/ko/16_Dom/04_Slider.js      |   33 +
         src/data/examples/ko/16_Dom/07_Modify_DOM.js  |   55 +
         src/data/examples/ko/16_Dom/08_Video.js       |   29 +
         .../examples/ko/16_Dom/09_Video_Canvas.js     |   27 +
         .../examples/ko/16_Dom/10_Video_Pixels.js     |   33 +
         src/data/examples/ko/16_Dom/11_Capture.js     |   25 +
         src/data/examples/ko/16_Dom/12_Drop.js        |   36 +
         .../ko/17_Drawing/00_Continuous_Lines.js      |   15 +
         src/data/examples/ko/17_Drawing/01_Pattern.js |   26 +
         src/data/examples/ko/17_Drawing/02_Pulses.js  |   30 +
         .../examples/ko/18_Transform/00_Translate.js  |   39 +
         src/data/examples/ko/18_Transform/01_Scale.js |   45 +
         .../examples/ko/18_Transform/02_Rotate.js     |   42 +
         src/data/examples/ko/18_Transform/03_Arm.js   |   47 +
         .../examples/ko/19_Typography/00_Letters.js   |   64 +
         .../examples/ko/19_Typography/01_Words.js     |   58 +
         src/data/examples/ko/20_3D/00_geometries.js   |   60 +
         .../examples/ko/20_3D/01_sine_cosine_in_3D.js |   28 +
         .../examples/ko/20_3D/02_multiple_lights.js   |   30 +
         src/data/examples/ko/20_3D/03_materials.js    |   65 +
         src/data/examples/ko/20_3D/04_textures.js     |   40 +
         .../examples/ko/20_3D/07_orbit_control.js     |   36 +
         src/data/examples/ko/21_Input/00_Clock.js     |   62 +
         src/data/examples/ko/21_Input/01_Constrain.js |   36 +
         src/data/examples/ko/21_Input/02_Easing.js    |   28 +
         src/data/examples/ko/21_Input/03_Keyboard.js  |   38 +
         src/data/examples/ko/21_Input/04_Mouse1D.js   |   23 +
         src/data/examples/ko/21_Input/05_Mouse2D.js   |   19 +
         .../examples/ko/21_Input/06_MouseIsPressed.js |   20 +
         .../ko/21_Input/07_Mouse_Functions.js         |   66 +
         .../examples/ko/21_Input/08_Mouse_Signals.js  |   51 +
         .../examples/ko/21_Input/09_Storing_Input.js  |   36 +
         .../ko/22_Advanced_Data/00_Load_Saved_JSON.js |  104 ++
         .../ko/33_Sound/00_Load_and_Play_Sound.js     |   25 +
         .../examples/ko/33_Sound/01_Preload_Sound.js  |   35 +
         .../examples/ko/33_Sound/02_soundFormats.js   |   50 +
         src/data/examples/ko/33_Sound/03_Play_Mode.js |   42 +
         .../examples/ko/33_Sound/04_Pan_SoundFile.js  |   34 +
         .../examples/ko/33_Sound/05_Sound_Effect.js   |   68 +
         .../ko/33_Sound/06_Manipulate_Sound.js        |   48 +
         .../ko/33_Sound/07_Amplitude_Analysis.js      |   47 +
         .../examples/ko/33_Sound/08_Noise_Envelope.js |   50 +
         .../examples/ko/33_Sound/09_Note_Envelope.js  |   59 +
         .../ko/33_Sound/10_Oscillator_Waveform.js     |   39 +
         .../examples/ko/33_Sound/11_Live_Input.js     |   33 +
         .../examples/ko/33_Sound/12_FFT_Spectrum.js   |   30 +
         .../examples/ko/33_Sound/13_Mic_Threshold.js  |   48 +
         .../examples/ko/33_Sound/14_Filter_LowPass.js |   60 +
         .../ko/33_Sound/15_Filter_BandPass.js         |   49 +
         src/data/examples/ko/33_Sound/16_Delay.js     |   56 +
         src/data/examples/ko/33_Sound/17_Reverb.js    |   36 +
         .../ko/33_Sound/18_Convolution_Reverb.js      |   84 ++
         .../examples/ko/33_Sound/19_Record_Save.js    |   57 +
         .../examples/ko/33_Sound/21_FreqModulation.js |  143 ++
         .../ko/33_Sound/22_AmplitudeModulation.js     |   91 ++
         .../35_Mobile/00_Acceleration_Ball_Bounce.js  |   58 +
         .../examples/ko/35_Mobile/01_Simple_Draw.js   |   15 +
         .../ko/35_Mobile/02_Acceleration_Color.js     |   24 +
         .../ko/35_Mobile/03_Shake_Ball_Bounce.js      |  116 ++
         .../examples/ko/35_Mobile/04_Tilted_3D_Box.js |   15 +
         src/data/examples/ko/90_Hello_P5/01_shapes.js |   28 +
         .../ko/90_Hello_P5/02_interactivity.js        |   40 +
         .../ko/90_Hello_P5/03_interactivity.js        |   29 +
         .../examples/ko/90_Hello_P5/04_animate.js     |   33 +
         .../examples/ko/90_Hello_P5/04_flocking.js    |  186 +++
         .../examples/ko/90_Hello_P5/05_weather.js     |   73 +
         .../examples/ko/90_Hello_P5/06_drawing.js     |  132 ++
         src/data/examples/ko/90_Hello_P5/07_song.js   |  119 ++
         src/data/ko.yml                               |  669 +++++++++
         src/data/reference/ko.json                    |  280 ++++
         .../pages/reference/assets/index.html         |    2 +-
         .../pages/reference/assets/js/reference.js    |   16 +-
         .../reference/assets/js/reference.js.map      |   40 +-
         src/templates/pages/reference/index.html      |  278 ++++
         src/templates/partials/i18n.hbs               |    3 +-
         184 files changed, 11238 insertions(+), 383 deletions(-)
         create mode 100644 src/data/examples/ko/00_Structure/00_Coordinates.js
         create mode 100644 src/data/examples/ko/00_Structure/01_Width_and_Height.js
         create mode 100644 src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
         create mode 100644 src/data/examples/ko/00_Structure/03_No_Loop.js
         create mode 100644 src/data/examples/ko/00_Structure/04_Loop.js
         create mode 100644 src/data/examples/ko/00_Structure/05_Redraw.js
         create mode 100644 src/data/examples/ko/00_Structure/06_Functions.js
         create mode 100644 src/data/examples/ko/00_Structure/07_Recursion.js
         create mode 100644 src/data/examples/ko/00_Structure/08_Create_Graphics.js
         create mode 100644 src/data/examples/ko/01_Form/00_Points_and_Lines.js
         create mode 100644 src/data/examples/ko/01_Form/01_Shape_Primitives.js
         create mode 100644 src/data/examples/ko/01_Form/02_Pie_Chart.js
         create mode 100644 src/data/examples/ko/01_Form/03_Regular_Polygon.js
         create mode 100644 src/data/examples/ko/01_Form/04_Star.js
         create mode 100644 src/data/examples/ko/01_Form/05_Triangle_Strip.js
         create mode 100644 src/data/examples/ko/01_Form/06_Bezier.js
         create mode 100644 src/data/examples/ko/01_Form/07_3D_Primitives.js
         create mode 100644 src/data/examples/ko/02_Data/00_Variables.js
         create mode 100644 src/data/examples/ko/02_Data/01_True_and_False.js
         create mode 100644 src/data/examples/ko/02_Data/03_Variable_Scope.js
         create mode 100644 src/data/examples/ko/02_Data/04_Numbers.js
         create mode 100644 src/data/examples/ko/03_Arrays/00_Array.js
         create mode 100644 src/data/examples/ko/03_Arrays/01_Array_2d.js
         create mode 100644 src/data/examples/ko/03_Arrays/02_Array_Objects.js
         create mode 100644 src/data/examples/ko/04_Control/00_Iteration.js
         create mode 100644 src/data/examples/ko/04_Control/01_Embedded_Iteration.js
         create mode 100644 src/data/examples/ko/04_Control/02_Conditionals_1.js
         create mode 100644 src/data/examples/ko/04_Control/03_Conditionals_2.js
         create mode 100644 src/data/examples/ko/04_Control/04_Logical_Operators.js
         create mode 100644 src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
         create mode 100644 src/data/examples/ko/05_Image/01_Background_Image.js
         create mode 100644 src/data/examples/ko/05_Image/02_Transparency.js
         create mode 100644 src/data/examples/ko/05_Image/03_Alpha_Mask.js
         create mode 100644 src/data/examples/ko/05_Image/04_Create_Image.js
         create mode 100644 src/data/examples/ko/05_Image/05_Pointillism.js
         create mode 100644 src/data/examples/ko/07_Color/00_Hue.js
         create mode 100644 src/data/examples/ko/07_Color/01_Saturation.js
         create mode 100644 src/data/examples/ko/07_Color/02_Brightness.js
         create mode 100644 src/data/examples/ko/07_Color/03_Color_Variables.js
         create mode 100644 src/data/examples/ko/07_Color/04_Relativity.js
         create mode 100644 src/data/examples/ko/07_Color/05_Linear_Gradient.js
         create mode 100644 src/data/examples/ko/07_Color/06_Radial_Gradient.js
         create mode 100644 src/data/examples/ko/07_Color/07_Lerp_Color.js
         create mode 100644 src/data/examples/ko/08_Math/00_incrementdecrement.js
         create mode 100644 src/data/examples/ko/08_Math/01_operatorprecedence.js
         create mode 100644 src/data/examples/ko/08_Math/02_distance1d.js
         create mode 100644 src/data/examples/ko/08_Math/03_distance2d.js
         create mode 100644 src/data/examples/ko/08_Math/04_sine.js
         create mode 100644 src/data/examples/ko/08_Math/05_sincosine.js
         create mode 100644 src/data/examples/ko/08_Math/06_sinewave.js
         create mode 100644 src/data/examples/ko/08_Math/07_additivewave.js
         create mode 100644 src/data/examples/ko/08_Math/08_polartocartesian.js
         create mode 100644 src/data/examples/ko/08_Math/09_arctangent.js
         create mode 100644 src/data/examples/ko/08_Math/10_Interpolate.js
         create mode 100644 src/data/examples/ko/08_Math/11_doubleRandom.js
         create mode 100644 src/data/examples/ko/08_Math/12_random.js
         create mode 100644 src/data/examples/ko/08_Math/13_noise1D.js
         create mode 100644 src/data/examples/ko/08_Math/14_noisewave.js
         create mode 100644 src/data/examples/ko/08_Math/15_Noise2D.js
         create mode 100644 src/data/examples/ko/08_Math/16_Noise3D.js
         create mode 100644 src/data/examples/ko/08_Math/17_Randomchords.js
         create mode 100644 src/data/examples/ko/08_Math/18_Map.js
         create mode 100644 src/data/examples/ko/09_Simulate/00_Forces.js
         create mode 100644 src/data/examples/ko/09_Simulate/01_ParticleSystem.js
         create mode 100644 src/data/examples/ko/09_Simulate/02_Flocking.js
         create mode 100644 src/data/examples/ko/09_Simulate/03_WolframCA.js
         create mode 100644 src/data/examples/ko/09_Simulate/04_GameOfLife.js
         create mode 100644 src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
         create mode 100644 src/data/examples/ko/09_Simulate/06_Spirograph.js
         create mode 100644 src/data/examples/ko/09_Simulate/07_LSystems.js
         create mode 100644 src/data/examples/ko/09_Simulate/08_Spring.js
         create mode 100644 src/data/examples/ko/09_Simulate/09_Springs.js
         create mode 100644 src/data/examples/ko/09_Simulate/10_SoftBody.js
         create mode 100644 src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
         create mode 100644 src/data/examples/ko/09_Simulate/12_BrownianMotion.js
         create mode 100644 src/data/examples/ko/09_Simulate/13_Chain.js
         create mode 100644 src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
         create mode 100644 src/data/examples/ko/09_Simulate/15_penrose_tiles.js
         create mode 100644 src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
         create mode 100644 src/data/examples/ko/09_Simulate/17_Mandelbrot.js
         create mode 100644 src/data/examples/ko/10_Interaction/10_Tickle.js
         create mode 100644 src/data/examples/ko/10_Interaction/20_Follow1.js
         create mode 100644 src/data/examples/ko/10_Interaction/21_Follow2.js
         create mode 100644 src/data/examples/ko/10_Interaction/22_Follow3.js
         create mode 100644 src/data/examples/ko/10_Interaction/23_snake.js
         create mode 100644 src/data/examples/ko/10_Interaction/24_Wavemaker.js
         create mode 100644 src/data/examples/ko/10_Interaction/25_reach1.js
         create mode 100644 src/data/examples/ko/10_Interaction/26_reach2.js
         create mode 100644 src/data/examples/ko/10_Interaction/27_reach3.js
         create mode 100644 src/data/examples/ko/11_Objects/01_Objects.js
         create mode 100644 src/data/examples/ko/11_Objects/02_Multiple_Objects.js
         create mode 100644 src/data/examples/ko/11_Objects/03_Objects_Array.js
         create mode 100644 src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
         create mode 100644 src/data/examples/ko/11_Objects/04_Inheritance.js
         create mode 100644 src/data/examples/ko/12_Lights/02_Directional.js
         create mode 100644 src/data/examples/ko/12_Lights/05_Mixture.js
         create mode 100644 src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
         create mode 100644 src/data/examples/ko/13_Motion/02_Linear_Motion.js
         create mode 100644 src/data/examples/ko/13_Motion/03_Bounce.js
         create mode 100644 src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
         create mode 100644 src/data/examples/ko/13_Motion/05_Morph.js
         create mode 100644 src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
         create mode 100644 src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
         create mode 100644 src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
         create mode 100644 src/data/examples/ko/16_Dom/03_Input_Button.js
         create mode 100644 src/data/examples/ko/16_Dom/04_Slider.js
         create mode 100644 src/data/examples/ko/16_Dom/07_Modify_DOM.js
         create mode 100644 src/data/examples/ko/16_Dom/08_Video.js
         create mode 100644 src/data/examples/ko/16_Dom/09_Video_Canvas.js
         create mode 100644 src/data/examples/ko/16_Dom/10_Video_Pixels.js
         create mode 100644 src/data/examples/ko/16_Dom/11_Capture.js
         create mode 100644 src/data/examples/ko/16_Dom/12_Drop.js
         create mode 100644 src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
         create mode 100644 src/data/examples/ko/17_Drawing/01_Pattern.js
         create mode 100644 src/data/examples/ko/17_Drawing/02_Pulses.js
         create mode 100644 src/data/examples/ko/18_Transform/00_Translate.js
         create mode 100644 src/data/examples/ko/18_Transform/01_Scale.js
         create mode 100644 src/data/examples/ko/18_Transform/02_Rotate.js
         create mode 100644 src/data/examples/ko/18_Transform/03_Arm.js
         create mode 100644 src/data/examples/ko/19_Typography/00_Letters.js
         create mode 100644 src/data/examples/ko/19_Typography/01_Words.js
         create mode 100644 src/data/examples/ko/20_3D/00_geometries.js
         create mode 100644 src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
         create mode 100644 src/data/examples/ko/20_3D/02_multiple_lights.js
         create mode 100644 src/data/examples/ko/20_3D/03_materials.js
         create mode 100644 src/data/examples/ko/20_3D/04_textures.js
         create mode 100644 src/data/examples/ko/20_3D/07_orbit_control.js
         create mode 100644 src/data/examples/ko/21_Input/00_Clock.js
         create mode 100644 src/data/examples/ko/21_Input/01_Constrain.js
         create mode 100644 src/data/examples/ko/21_Input/02_Easing.js
         create mode 100644 src/data/examples/ko/21_Input/03_Keyboard.js
         create mode 100644 src/data/examples/ko/21_Input/04_Mouse1D.js
         create mode 100644 src/data/examples/ko/21_Input/05_Mouse2D.js
         create mode 100644 src/data/examples/ko/21_Input/06_MouseIsPressed.js
         create mode 100644 src/data/examples/ko/21_Input/07_Mouse_Functions.js
         create mode 100644 src/data/examples/ko/21_Input/08_Mouse_Signals.js
         create mode 100644 src/data/examples/ko/21_Input/09_Storing_Input.js
         create mode 100644 src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
         create mode 100644 src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
         create mode 100644 src/data/examples/ko/33_Sound/01_Preload_Sound.js
         create mode 100644 src/data/examples/ko/33_Sound/02_soundFormats.js
         create mode 100644 src/data/examples/ko/33_Sound/03_Play_Mode.js
         create mode 100644 src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
         create mode 100644 src/data/examples/ko/33_Sound/05_Sound_Effect.js
         create mode 100644 src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
         create mode 100644 src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
         create mode 100644 src/data/examples/ko/33_Sound/08_Noise_Envelope.js
         create mode 100644 src/data/examples/ko/33_Sound/09_Note_Envelope.js
         create mode 100644 src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
         create mode 100644 src/data/examples/ko/33_Sound/11_Live_Input.js
         create mode 100644 src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
         create mode 100644 src/data/examples/ko/33_Sound/13_Mic_Threshold.js
         create mode 100644 src/data/examples/ko/33_Sound/14_Filter_LowPass.js
         create mode 100644 src/data/examples/ko/33_Sound/15_Filter_BandPass.js
         create mode 100644 src/data/examples/ko/33_Sound/16_Delay.js
         create mode 100644 src/data/examples/ko/33_Sound/17_Reverb.js
         create mode 100644 src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
         create mode 100644 src/data/examples/ko/33_Sound/19_Record_Save.js
         create mode 100644 src/data/examples/ko/33_Sound/21_FreqModulation.js
         create mode 100644 src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
         create mode 100644 src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
         create mode 100644 src/data/examples/ko/35_Mobile/01_Simple_Draw.js
         create mode 100644 src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
         create mode 100644 src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
         create mode 100644 src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/01_shapes.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/02_interactivity.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/03_interactivity.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/04_animate.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/04_flocking.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/05_weather.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/06_drawing.js
         create mode 100644 src/data/examples/ko/90_Hello_P5/07_song.js
         create mode 100644 src/data/ko.yml
         create mode 100644 src/data/reference/ko.json
         create mode 100644 src/templates/pages/reference/index.html
        
        diff --git a/Gruntfile.js b/Gruntfile.js
        index 9a7d4e6eff..e7975899fb 100644
        --- a/Gruntfile.js
        +++ b/Gruntfile.js
        @@ -420,4 +420,4 @@ module.exports = function(grunt) {
         
           // runs with just grunt command
           grunt.registerTask('default', ['build']);
        -};
        +};
        \ No newline at end of file
        diff --git a/i18n-tracking.yml b/i18n-tracking.yml
        index 0570b7eda6..92288aaa11 100644
        --- a/i18n-tracking.yml
        +++ b/i18n-tracking.yml
        @@ -1,65 +1,300 @@
         es:
           src/data/en.yml:
        -    line 44: '  description-roni'
        -    line 45: '  project-phuong'
        -    line 17: Showcase
        -    line 25: ''
        -    line 26: showcase
        -    line 27: '  showcase-title'
        -    line 28: '  showcase-intro1'
        -    line 29: '  showcase-intro2'
        -    line 30: '  showcase-intro3'
        -    line 31: '  showcase-featuring'
        -    line 32: '  project-tag-art'
        -    line 33: '  project-tag-design'
        -    line 34: '  project-tag-code'
        -    line 35: '  project-tag-curriculum'
        -    line 36: '  project-tag-documentation'
        -    line 37: '  project-tag-game'
        -    line 38: '  project-tag-library'
        -    line 39: '  project-tag-organizing'
        -    line 40: '  project-tag-tool'
        -    line 41: '  project-tag-tutorial'
        -    line 42: '  project-roni'
        -    line 43: '  credit-roni'
        -    line 46: '  credit-phuong'
        -    line 47: '  description-phuong'
        -    line 48: '  project-daein'
        -    line 49: '  credit-daein'
        -    line 50: '  description-daein'
        -    line 51: '  project-qianqian'
        -    line 52: '  credit-qianqian'
        -    line 53: '  description-qianqian'
        -    line 54: '  project-casey-louise'
        -    line 55: '  credit-casey-louise'
        -    line 56: '  description-casey-louise'
        -    line 57: '  project-moon-xin'
        -    line 58: '  credit-moon-xin'
        -    line 59: '  description-moon-xin'
        -    line 516: '  showcase-intro3'
        -    line 517: '  showcase-featuring'
        -    line 518: '  project-tag-art'
        -    line 519: '  project-tag-design'
        -    line 520: '  project-tag-code'
        -    line 521: '  project-tag-curriculum'
        -    line 522: '  project-tag-documentation'
        -    line 523: '  project-tag-game'
        -    line 524: '  project-tag-library'
        -    line 525: '  project-tag-organizing'
        -    line 526: '  project-tag-tool'
        -    line 527: '  project-tag-tutorial'
        -    line 531: '  description-roni'
        -    line 358: '  p5.ble'
        -    line 364: '  p5.createloop'
        -    line 368: '  p5.experience'
        -    line 377: '  vida'
        -    line 380: '  p5.3D'
        -    line 363: '  p5.experience'
        -    line 329: '  coordinate-system-simple-shapes-p2x1'
        -    line 341: '  coordinate-system-simple-shapes-p9x1'
        -    line 274: '  color-description1'
        -    line 275: '  color-description2'
        -    line 276: '  color-title'
        +    line 49: '  RotatingKnobs'
        +    line 94: '  project-phuong'
        +    line 95: '  credit-phuong'
        +    line 98: '  credit-daein'
        +    line 107: '  credit-moon-xin'
        +    line 84: '  project-tag-curriculum'
        +    line 105: '  description-casey-louise'
        +    line 106: '  project-moon-xin'
        +    line 66: '  2015cc_5'
        +    line 75: showcase
        +    line 99: '  description-daein'
        +    line 108: '  description-moon-xin'
        +    line 89: '  project-tag-tool'
        +    line 90: '  project-tag-tutorial'
        +    line 91: '  project-roni'
        +    line 92: '  credit-roni'
        +    line 93: '  description-roni'
        +    line 96: '  description-phuong'
        +    line 97: '  project-daein'
        +    line 85: '  project-tag-documentation'
        +    line 86: '  project-tag-game'
        +    line 87: '  project-tag-library'
        +    line 15: Showcase
        +    line 74: ''
        +    line 76: '  showcase-title'
        +    line 88: '  project-tag-organizing'
        +    line 100: '  project-qianqian'
        +    line 101: '  credit-qianqian'
        +    line 102: '  description-qianqian'
        +    line 103: '  project-casey-louise'
        +    line 104: '  credit-casey-louise'
        +    line 7: Donate
        +    line 31: '  p5js-wiki-title'
        +    line 32: '  p5js-wiki'
        +    line 77: '  showcase-intro1'
        +    line 78: '  showcase-intro2'
        +    line 79: '  showcase-intro3'
        +    line 80: '  showcase-featuring'
        +    line 81: '  project-tag-art'
        +    line 82: '  project-tag-design'
        +    line 83: '  project-tag-code'
        +    line 52: '  p3xh2'
        +    line 44: '  p2x1'
        +    line 45: '  p2x2'
        +    line 48: '  p2x5'
        +    line 55: '  p3xp3'
        +    line 56: '  p3xp4'
        +    line 57: '  p3xp5'
        +    line 5: Editor
        +    line 46: '  p2x3'
        +    line 47: '  p2x4'
        +    line 50: '  p2x7'
        +    line 51: ''
        +    line 53: '  p3xp1'
        +    line 54: '  p3xp2'
        +    line 58: '  p3xp6'
        +    line 63: '  p4xp3'
        +    line 43: '  p2xh2'
        +    line 380: '  2019cc_18'
        +    line 373: '  2019cc_11'
        +    line 381: '  2019cc_19'
        +    line 371: '  2019cc_9'
        +    line 358: '  output11'
        +    line 364: '  2019cc_2'
        +    line 368: '  2019cc_6'
        +    line 377: '  2019cc_15'
        +    line 363: '  2019cc_1'
        +    line 329: '  2015cc_9'
        +    line 341: '  2019contributors-conference4'
        +    line 274: '  sharing2'
        +    line 275: '  sharing3'
        +    line 276: ''
        +    line 290: '  contributors-conference-title'
        +    line 291: '  contributors-conference1'
        +    line 292: '  contributors-conference2'
        +    line 293: '  participants-title'
        +    line 294: '  support-title'
        +    line 295: '  support1'
        +    line 296: '  support2'
        +    line 297: '  support3'
        +    line 298: '  support4'
        +    line 299: '  support5'
        +    line 300: '  support6'
        +    line 305: ''
        +    line 306: '  2015contributors-conference-title'
        +    line 307: '  2015contributors-conference-date'
        +    line 308: '  2015contributors-conference1'
        +    line 309: '  2015contributors-conference2'
        +    line 310: '  2015contributors-conference3'
        +    line 311: '  2015contributors-conference-diversity-title'
        +    line 312: '  2015contributors-conference-diversity1'
        +    line 313: '  2015contributors-conference-diversity2'
        +    line 314: '  2015contributors-conference-diversity3'
        +    line 315: '  2015contributors-conference-diversity4'
        +    line 316: '  2015contributors-conference-diversity5'
        +    line 317: '  2015contributors-conference-diversity6'
        +    line 318: '  2015contributors-conference-diversity7'
        +    line 319: '  2015contributors-conference-diversity8'
        +    line 320: '  2015contributors-conference-diversity9'
        +    line 321: '  2015cc_1'
        +    line 322: '  2015cc_2'
        +    line 323: '  2015cc_3'
        +    line 324: '  2015cc_4'
        +    line 325: '  2015cc_5'
        +    line 326: '  2015cc_6'
        +    line 327: '  2015cc_7'
        +    line 328: '  2015cc_8'
        +    line 330: '  2015cc_10'
        +    line 331: '  2015cc_11'
        +    line 332: '  2015cc_12'
        +    line 333: '  2015cc_13'
        +    line 334: '  2015cc_14'
        +    line 335: '  2015cc_15'
        +    line 336: '  2019contributors-conference-title'
        +    line 337: '  2019contributors-conference-date'
        +    line 338: '  2019contributors-conference1'
        +    line 339: '  2019contributors-conference2'
        +    line 340: '  2019contributors-conference3'
        +    line 342: '  outputs'
        +    line 343: '  output1'
        +    line 344: '  output2'
        +    line 345: '  output3'
        +    line 346: '  output3-1'
        +    line 347: '  output4'
        +    line 348: '  output5'
        +    line 386: '  2019cc_24'
        +    line 359: '  output12'
        +    line 362: '  output15'
        +    line 374: '  2019cc_12'
        +    line 376: '  2019cc_14'
        +    line 379: '  2019cc_17'
        +    line 382: '  2019cc_20'
        +    line 355: '  output9'
        +    line 356: '  output9-1'
        +    line 360: '  output13'
        +    line 357: '  output10'
        +    line 361: '  output14'
        +    line 1: Skip-To-Content
        +    line 39: '  start-creating'
        +    line 40: '  p1xh1'
        +    line 41: '  p1x1'
        +    line 42: '  p1x2'
        +    line 59: ''
        +    line 60: '  p4xh2'
        +    line 61: '  p4xp1'
        +    line 62: '  p4xp2'
        +    line 64: '  p4xp4'
        +    line 65: '  p4xp5'
        +    line 2: Language-Settings
        +    line 3: Sidebar-Title
        +    line 67: ''
        +    line 370: '  2019cc_8'
        +    line 372: '  2019cc_10'
        +    line 383: '  2019cc_21'
        +    line 151: '  report-bugs'
        +    line 168: '  support-23'
        +    line 72: '  sketch_info_link'
        +    line 8: Start
        +    line 16: footerxh1
        +    line 71: '  sketch_info'
        +    line 117: '  book1'
        +    line 121: '  download-intro'
        +    line 122: '  editor-title'
        +    line 123: '  p5.js-editor'
        +    line 124: '  p5.js-editor-intro'
        +    line 125: '  editor-includes'
        +    line 127: '  complete-library-intro1'
        +    line 128: '  complete-library-intro2'
        +    line 129: '  complete-library-intro3'
        +    line 133: '  includes-2'
        +    line 136: '  single-files-intro'
        +    line 148: '  etc-title'
        +    line 149: '  older-releases'
        +    line 150: '  github-repository'
        +    line 153: ''
        +    line 155: '  support-options'
        +    line 164: '  support-20'
        +    line 176: '  support-17-alt'
        +    line 177: '  support-18-alt'
        +    line 178: '  support-19-alt'
        +    line 179: '  support-20-alt'
        +    line 180: '  support-21-alt'
        +    line 181: '  support-22-alt'
        +    line 182: '  support-23-alt'
        +    line 183: '  support-24-alt'
        +    line 184: '  support-25-alt'
        +    line 185: '  support-26-alt'
        +    line 186: '  support-27-alt'
        +    line 187: '  support-28-alt'
        +    line 188: '  support-29-alt'
        +    line 189: '  support-30-alt'
        +    line 190: '  support-30-alt'
        +    line 191: '  support-31-alt'
        +    line 200: '  core-libraries'
        +    line 201: '  community-libraries'
        +    line 202: '  libraries-created-by'
        +    line 213: '  asciiart'
        +    line 214: '  p5.ble'
        +    line 215: '  blizard.js'
        +    line 222: '  p5.clickable'
        +    line 223: '  p5.cmyk.js'
        +    line 224: '  p5.collide2D'
        +    line 225: '  p5.createloop'
        +    line 226: '  p5.dimensions'
        +    line 227: '  p5.EasyCam'
        +    line 228: '  p5.experience'
        +    line 229: '  p5.func'
        +    line 230: '  p5.geolocation'
        +    line 231: '  p5.gibber'
        +    line 232: '  grafica.js'
        +    line 233: '  p5.gui'
        +    line 234: '  p5.localmessage'
        +    line 235: '  marching'
        +    line 236: '  mappa'
        +    line 237: '  ml5.js'
        +    line 238: '  p5.play'
        +    line 239: '  p5.particle'
        +    line 240: '  p5.Riso'
        +    line 241: '  rita.js'
        +    line 242: '  Rotating Knobs'
        +    line 243: '  p5.scenemanager'
        +    line 244: '  p5.screenPosition'
        +    line 254: '  p5.serial'
        +    line 255: '  Shape5'
        +    line 256: '  p5.shape.js'
        +    line 257: '  p5.speech'
        +    line 258: '  p5.start2d.js'
        +    line 259: '  p5.tiledmap'
        +    line 260: '  p5.touchgui'
        +    line 261: '  tramontana'
        +    line 262: '  vida'
        +    line 263: '  p5.voronoi'
        +    line 264: '  p5.3D'
        +    line 272: '  sharing-title'
        +    line 273: '  sharing1'
        +    line 349: '  output6'
        +    line 350: '  output6-1'
        +    line 351: '  output6-2'
        +    line 352: '  output7'
        +    line 353: '  output8'
        +    line 354: '  output8-1'
        +    line 365: '  2019cc_3'
        +    line 366: '  2019cc_4'
        +    line 367: '  2019cc_5'
        +    line 369: '  2019cc_7'
        +    line 375: '  2019cc_13'
        +    line 378: '  2019cc_16'
        +    line 384: '  2019cc_22'
        +    line 385: '  2019cc_23'
        +    line 387: '  2019cc_25'
        +    line 559: '  output3-1'
        +    line 568: '  output9'
        +    line 569: '  output9-1'
        +    line 555: '  output1'
        +    line 565: '  output8'
        +    line 566: '  output8-1'
        +    line 572: '  output14'
        +    line 554: '  outputs'
        +    line 556: '  output2'
        +    line 557: '  output3'
        +    line 558: '  output3-1'
        +    line 560: '  output5'
        +    line 561: '  output6'
        +    line 562: '  output6-1'
        +    line 563: '  output6-2'
        +    line 564: '  output7'
        +    line 567: '  output9'
        +    line 570: '  output12'
        +    line 571: '  output13'
        +    line 581: '  2019cc_25'
        +    line 413: '  p5.EasyCam'
        +    line 552: '  2019contributors-conference2'
        +    line 412: '  p5.EasyCam'
        +    line 425: '  p5.touchgui'
        +    line 13: '  start-creating'
        +    line 109: '  2019cc_21'
        +    line 110: '  2019cc_22'
        +    line 111: '  2019cc_23'
        +    line 545: '  2019contributors-conference-date'
        +    line 504: '  participants-title'
        +    line 505: '  support-title'
        +    line 506: '  support1'
        +    line 507: '  support2'
        +    line 508: '  support3'
        +    line 509: '  support4'
        +    line 510: '  support5'
        +    line 511: '  support6'
        +    line 34: '  p2xh2'
        +    line 391: '  p5.localmessage'
        +    line 399: '  Rotating Knobs'
        +    line 401: '  p5.screenPosition'
        +    line 404: '  Shape5'
        +    line 406: '  p5.start.js'
        +    line 407: '  p5.start2d.js'
        +    line 409: '  tramontana'
             line 277: '  color-p1x1'
             line 278: '  color-p2x1'
             line 279: '  color-p2x2'
        @@ -73,199 +308,716 @@ es:
             line 287: '  color-p3x5'
             line 288: '  color-p4x1'
             line 289: '  color-rgb-title'
        -    line 290: '  color-rgb-p1x1'
        -    line 291: '  color-rgb-li1'
        -    line 292: '  color-rgb-li2'
        -    line 293: '  color-rgb-li3'
        -    line 294: '  color-rgb-li4'
        -    line 295: '  color-rgb-li5'
        -    line 296: '  color-rgb-p2x1'
        -    line 297: '  color-transparency-title'
        -    line 298: '  color-transparency-p1x1'
        -    line 299: '  color-transparency-p2x1'
        -    line 300: '  color-transparency-p3x1'
             line 301: '  color-custom-ranges-title'
             line 302: '  color-custom-ranges-p1x1'
             line 303: '  color-custom-ranges-p2x1'
             line 304: '  color-custom-ranges-p3x1'
        -    line 305: '  color-custom-ranges-p4x1'
        -    line 306: '  color-custom-ranges-p5x1'
        -    line 307: '  color-custom-ranges-li1x1'
        -    line 308: '  color-custom-ranges-li1x2'
        -    line 309: '  color-custom-ranges-li2x1'
        -    line 310: '  color-custom-ranges-li2x2'
        -    line 311: '  color-custom-ranges-li3x1'
        -    line 312: '  color-custom-ranges-li3x2'
        -    line 313: '  color-custom-ranges-p6x1'
        -    line 314: '  color-custom-ranges-p6x2'
        -    line 315: '  coordinate-system-description1'
        -    line 316: '  coordinate-system-description2'
        -    line 317: '  coordinate-system-description3'
        -    line 318: '  coordinate-system-description4'
        -    line 319: '  coordinate-system-description5'
        -    line 320: '  coordinate-system-description-title'
        -    line 321: '  coordinate-system-description-p1x1'
        -    line 322: '  coordinate-system-description-p2x1'
        -    line 323: '  coordinate-system-description-p3x1'
        -    line 324: '  coordinate-system-description-p4x1'
        -    line 325: '  coordinate-system-description-p5x1'
        -    line 326: '  coordinate-system-simple-shapes-title'
        -    line 327: '  coordinate-system-simple-shapes-p1x1'
        -    line 328: '  coordinate-system-simple-shapes-p2x1'
        -    line 330: '  coordinate-system-simple-shapes-p3x2'
        -    line 331: '  coordinate-system-simple-shapes-p4x1'
        -    line 332: '  coordinate-system-simple-shapes-p4x2'
        -    line 333: '  coordinate-system-simple-shapes-p5x1'
        -    line 334: '  coordinate-system-simple-shapes-p5x2'
        -    line 335: '  coordinate-system-simple-shapes-p6x1'
        -    line 336: '  coordinate-system-simple-shapes-p6x2'
        -    line 337: '  coordinate-system-simple-shapes-p7x1'
        -    line 338: '  coordinate-system-simple-shapes-p7x2'
        -    line 339: '  coordinate-system-simple-shapes-p8x1'
        -    line 340: '  coordinate-system-simple-shapes-p8x2'
        -    line 342: '  coordinate-system-simple-shapes-p8x4'
        -    line 343: '  coordinate-system-simple-shapes-p8x5'
        -    line 344: '  coordinate-system-simple-shapes-p8x6'
        -    line 345: '  coordinate-system-simple-shapes-p9x1'
        -    line 346: '  coordinate-system-simple-shapes-p9x2'
        -    line 347: '  coordinate-system-simple-shapes-p9x3'
        -    line 348: '  coordinate-system-simple-shapes-p10x1'
        -    line 99: '  your-first-sketch12'
        -    line 108: '  coordinate-system-simple-shapes-p2x1'
             line 120: '  coordinate-system-simple-shapes-p9x1'
        -    line 386: '  create-your-own4'
        -    line 359: '  p5.clickable'
        -    line 362: '  p5.dimensions1'
        -    line 373: '  mappa'
        -    line 374: '  p5.play'
        -    line 376: '  rita.js'
        -    line 379: '  p5.serial1'
        -    line 381: '  p5.serial3'
        -    line 382: '  p5.speech'
        -    line 391: '  p5.3D'
        -    line 355: '  asciiart'
        -    line 356: '  p5.ble'
        -    line 360: '  p5.createloop'
        -    line 371: '  vida'
        -    line 357: '  asciiart'
        -    line 361: '  p5.clickable'
        -    line 12: Showcase
        -    line 20: ''
        -    line 21: showcase
        -    line 22: '  Showcase'
        -    line 23: '  test'
        -    line 515: '  showcase-title'
        -    line 528: '  project-qianqian'
        -    line 529: '  credit-qianqian'
        -    line 530: '  description-qianqian'
        -    line 532: '  credit-conchinha-lessel'
        -    line 533: '  description-conchinha-lessel'
        -    line 535: '  description-phuong'
        -    line 539: '  description-daein'
        -    line 546: '  description-qianqian'
        -    line 547: '  project-casey-louise'
        -    line 548: '  credit-casey-louise'
        -    line 549: '  description-casey-louise'
        -    line 550: '  project-moon-xin'
        -    line 551: '  credit-moon-xin'
        -    line 552: '  description-moon-xin'
        -    line 669: '  credit-moon-xin'
        +    line 38: '  p1xh1'
        +    line 4: Sidebar-Title
        +    line 400: '  p5.collide2D'
        +    line 402: '  p5.dimensions'
        +    line 403: '  p5.experience'
        +    line 405: '  p5.geolocation'
        +    line 408: '  p5.gui'
        +    line 410: '  p5.play'
        +    line 411: '  p5.particle'
        +    line 424: '  p5.serial'
        +    line 426: '  p5.tiledmap'
        +    line 427: '  vida'
        +    line 428: '  p5.voronoi'
        +    line 429: '  p5.3D'
        +    line 156: '  etc-title'
        +    line 157: '  older-releases'
        +    line 158: '  github-repository'
        +    line 159: '  report-bugs'
        +    line 392: '  marching'
        +    line 394: '  ml5.js'
        +    line 397: '  p5.Riso'
        +    line 476: '  contributors-conference-title'
        +    line 477: '  contributors-conference1'
        +    line 478: '  contributors-conference2'
        +    line 479: '  contributors-conference3'
        +    line 480: '  contributors-conference4'
        +    line 485: ''
        +    line 486: '  2015contributors-conference-title'
        +    line 487: '  2015contributors-conference-date'
        +    line 488: '  2015contributors-conference1'
        +    line 489: '  2015contributors-conference2'
        +    line 490: '  2015contributors-conference3'
        +    line 491: '  2015contributors-conference-participants-title'
        +    line 492: '  2015contributors-conference-diversity-title'
        +    line 493: '  2015contributors-conference-diversity1'
        +    line 494: '  2015contributors-conference-diversity2'
        +    line 495: '  2015contributors-conference-diversity3'
        +    line 496: '  2015contributors-conference-diversity4'
        +    line 497: '  2015contributors-conference-diversity5'
        +    line 498: '  2015contributors-conference-diversity6'
        +    line 499: '  2015contributors-conference-diversity7'
        +    line 500: '  2015contributors-conference-diversity8'
        +    line 501: '  2015contributors-conference-diversity9'
        +    line 502: '  2015contributors-conference-support-title'
        +    line 503: '  2015contributors-conference-support1'
        +    line 512: '  2015cc_4'
        +    line 513: '  2015cc_5'
        +    line 514: '  2015cc_6'
        +    line 515: '  2015cc_7'
        +    line 516: '  2015cc_8'
        +    line 517: '  2015cc_9'
        +    line 518: '  2015cc_10'
        +    line 519: '  2015cc_11'
        +    line 520: '  2015cc_12'
        +    line 521: '  2015cc_13'
        +    line 522: '  2015cc_14'
        +    line 523: '  2015cc_15'
        +    line 139: '  download-intro'
        +    line 140: '  editor-title'
        +    line 141: '  p5.js-editor'
        +    line 142: '  p5.js-editor-intro'
        +    line 143: '  editor-includes'
        +    line 145: '  complete-library-intro1'
        +    line 146: '  complete-library-intro2'
        +    line 147: '  complete-library-intro3'
        +    line 154: '  single-files-intro'
        +    line 541: '  2019contributors-conference-title'
        +    line 542: '  2019contributors-conference-date'
        +    line 546: '  2019contributors-conference2'
        +    line 547: '  2019contributors-conference3'
        +    line 548: '  2019contributors-conference4'
        +    line 549: '  2019cc_1'
        +    line 550: '  2019cc_2'
        +    line 551: '  2019cc_3'
        +    line 553: '  2019cc_5'
        +    line 21: '  support-options'
        +    line 112: '  2019cc_24'
        +    line 420: '  p5.shape.js'
        +    line 573: '  output15'
        +ko:
        +  src/data/en.yml:
        +    line 49: '  RotatingKnobs'
        +    line 66: '  2015cc_5'
        +    line 75: showcase
        +    line 84: '  project-tag-curriculum'
        +    line 94: '  project-phuong'
        +    line 95: '  credit-phuong'
        +    line 98: '  credit-daein'
        +    line 105: '  description-casey-louise'
        +    line 106: '  project-moon-xin'
        +    line 107: '  credit-moon-xin'
        +    line 7: Donate
        +    line 15: Showcase
        +    line 31: '  p5js-wiki-title'
        +    line 32: '  p5js-wiki'
        +    line 74: ''
        +    line 76: '  showcase-title'
        +    line 77: '  showcase-intro1'
        +    line 78: '  showcase-intro2'
        +    line 79: '  showcase-intro3'
        +    line 80: '  showcase-featuring'
        +    line 81: '  project-tag-art'
        +    line 82: '  project-tag-design'
        +    line 83: '  project-tag-code'
        +    line 85: '  project-tag-documentation'
        +    line 86: '  project-tag-game'
        +    line 87: '  project-tag-library'
        +    line 88: '  project-tag-organizing'
        +    line 89: '  project-tag-tool'
        +    line 90: '  project-tag-tutorial'
        +    line 91: '  project-roni'
        +    line 92: '  credit-roni'
        +    line 93: '  description-roni'
        +    line 96: '  description-phuong'
        +    line 97: '  project-daein'
        +    line 99: '  description-daein'
        +    line 100: '  project-qianqian'
        +    line 101: '  credit-qianqian'
        +    line 102: '  description-qianqian'
        +    line 103: '  project-casey-louise'
        +    line 104: '  credit-casey-louise'
        +    line 108: '  description-moon-xin'
        +    line 1: Skip-To-Content
        +    line 2: Language-Settings
        +    line 3: Sidebar-Title
        +    line 5: Editor
        +    line 8: Start
        +    line 16: footerxh1
        +    line 39: '  start-creating'
        +    line 40: '  p1xh1'
        +    line 41: '  p1x1'
        +    line 42: '  p1x2'
        +    line 43: '  p2xh2'
        +    line 44: '  p2x1'
        +    line 45: '  p2x2'
        +    line 46: '  p2x3'
        +    line 47: '  p2x4'
        +    line 48: '  p2x5'
        +    line 50: '  p2x7'
        +    line 51: ''
        +    line 52: '  p3xh2'
        +    line 53: '  p3xp1'
        +    line 54: '  p3xp2'
        +    line 55: '  p3xp3'
        +    line 56: '  p3xp4'
        +    line 57: '  p3xp5'
        +    line 58: '  p3xp6'
        +    line 59: ''
        +    line 60: '  p4xh2'
        +    line 61: '  p4xp1'
        +    line 62: '  p4xp2'
        +    line 63: '  p4xp3'
        +    line 64: '  p4xp4'
        +    line 65: '  p4xp5'
        +    line 67: ''
        +    line 71: '  sketch_info'
        +    line 72: '  sketch_info_link'
        +    line 117: '  book1'
        +    line 121: '  download-intro'
        +    line 122: '  editor-title'
        +    line 123: '  p5.js-editor'
        +    line 124: '  p5.js-editor-intro'
        +    line 125: '  editor-includes'
        +    line 127: '  complete-library-intro1'
        +    line 128: '  complete-library-intro2'
        +    line 129: '  complete-library-intro3'
        +    line 133: '  includes-2'
        +    line 136: '  single-files-intro'
        +    line 148: '  etc-title'
        +    line 149: '  older-releases'
        +    line 150: '  github-repository'
        +    line 151: '  report-bugs'
        +    line 153: ''
        +    line 155: '  support-options'
        +    line 164: '  support-20'
        +    line 168: '  support-23'
        +    line 176: '  support-17-alt'
        +    line 177: '  support-18-alt'
        +    line 178: '  support-19-alt'
        +    line 179: '  support-20-alt'
        +    line 180: '  support-21-alt'
        +    line 181: '  support-22-alt'
        +    line 182: '  support-23-alt'
        +    line 183: '  support-24-alt'
        +    line 184: '  support-25-alt'
        +    line 185: '  support-26-alt'
        +    line 186: '  support-27-alt'
        +    line 187: '  support-28-alt'
        +    line 188: '  support-29-alt'
        +    line 189: '  support-30-alt'
        +    line 190: '  support-30-alt'
        +    line 191: '  support-31-alt'
        +    line 200: '  core-libraries'
        +    line 201: '  community-libraries'
        +    line 202: '  libraries-created-by'
        +    line 213: '  asciiart'
        +    line 214: '  p5.ble'
        +    line 215: '  blizard.js'
        +    line 222: '  p5.clickable'
        +    line 223: '  p5.cmyk.js'
        +    line 224: '  p5.collide2D'
        +    line 225: '  p5.createloop'
        +    line 226: '  p5.dimensions'
        +    line 227: '  p5.EasyCam'
        +    line 228: '  p5.experience'
        +    line 229: '  p5.func'
        +    line 230: '  p5.geolocation'
        +    line 231: '  p5.gibber'
        +    line 232: '  grafica.js'
        +    line 233: '  p5.gui'
        +    line 234: '  p5.localmessage'
        +    line 235: '  marching'
        +    line 236: '  mappa'
        +    line 237: '  ml5.js'
        +    line 238: '  p5.play'
        +    line 239: '  p5.particle'
        +    line 240: '  p5.Riso'
        +    line 241: '  rita.js'
        +    line 242: '  Rotating Knobs'
        +    line 243: '  p5.scenemanager'
        +    line 244: '  p5.screenPosition'
        +    line 254: '  p5.serial'
        +    line 255: '  Shape5'
        +    line 256: '  p5.shape.js'
        +    line 257: '  p5.speech'
        +    line 258: '  p5.start2d.js'
        +    line 259: '  p5.tiledmap'
        +    line 260: '  p5.touchgui'
        +    line 261: '  tramontana'
        +    line 262: '  vida'
        +    line 263: '  p5.voronoi'
        +    line 264: '  p5.3D'
        +    line 272: '  sharing-title'
        +    line 273: '  sharing1'
        +    line 274: '  sharing2'
        +    line 275: '  sharing3'
        +    line 276: ''
        +    line 290: '  contributors-conference-title'
        +    line 291: '  contributors-conference1'
        +    line 292: '  contributors-conference2'
        +    line 293: '  participants-title'
        +    line 294: '  support-title'
        +    line 295: '  support1'
        +    line 296: '  support2'
        +    line 297: '  support3'
        +    line 298: '  support4'
        +    line 299: '  support5'
        +    line 300: '  support6'
        +    line 305: ''
        +    line 306: '  2015contributors-conference-title'
        +    line 307: '  2015contributors-conference-date'
        +    line 308: '  2015contributors-conference1'
        +    line 309: '  2015contributors-conference2'
        +    line 310: '  2015contributors-conference3'
        +    line 311: '  2015contributors-conference-diversity-title'
        +    line 312: '  2015contributors-conference-diversity1'
        +    line 313: '  2015contributors-conference-diversity2'
        +    line 314: '  2015contributors-conference-diversity3'
        +    line 315: '  2015contributors-conference-diversity4'
        +    line 316: '  2015contributors-conference-diversity5'
        +    line 317: '  2015contributors-conference-diversity6'
        +    line 318: '  2015contributors-conference-diversity7'
        +    line 319: '  2015contributors-conference-diversity8'
        +    line 320: '  2015contributors-conference-diversity9'
        +    line 321: '  2015cc_1'
        +    line 322: '  2015cc_2'
        +    line 323: '  2015cc_3'
        +    line 324: '  2015cc_4'
        +    line 325: '  2015cc_5'
        +    line 326: '  2015cc_6'
        +    line 327: '  2015cc_7'
        +    line 328: '  2015cc_8'
        +    line 329: '  2015cc_9'
        +    line 330: '  2015cc_10'
        +    line 331: '  2015cc_11'
        +    line 332: '  2015cc_12'
        +    line 333: '  2015cc_13'
        +    line 334: '  2015cc_14'
        +    line 335: '  2015cc_15'
        +    line 336: '  2019contributors-conference-title'
        +    line 337: '  2019contributors-conference-date'
        +    line 338: '  2019contributors-conference1'
        +    line 339: '  2019contributors-conference2'
        +    line 340: '  2019contributors-conference3'
        +    line 341: '  2019contributors-conference4'
        +    line 342: '  outputs'
        +    line 343: '  output1'
        +    line 344: '  output2'
        +    line 345: '  output3'
        +    line 346: '  output3-1'
        +    line 347: '  output4'
        +    line 348: '  output5'
        +    line 349: '  output6'
        +    line 350: '  output6-1'
        +    line 351: '  output6-2'
        +    line 352: '  output7'
        +    line 353: '  output8'
        +    line 354: '  output8-1'
        +    line 355: '  output9'
        +    line 356: '  output9-1'
        +    line 357: '  output10'
        +    line 358: '  output11'
        +    line 359: '  output12'
        +    line 360: '  output13'
        +    line 361: '  output14'
        +    line 362: '  output15'
        +    line 363: '  2019cc_1'
        +    line 364: '  2019cc_2'
        +    line 365: '  2019cc_3'
        +    line 366: '  2019cc_4'
        +    line 367: '  2019cc_5'
        +    line 368: '  2019cc_6'
        +    line 369: '  2019cc_7'
        +    line 370: '  2019cc_8'
        +    line 371: '  2019cc_9'
        +    line 372: '  2019cc_10'
        +    line 373: '  2019cc_11'
        +    line 374: '  2019cc_12'
        +    line 375: '  2019cc_13'
        +    line 376: '  2019cc_14'
        +    line 377: '  2019cc_15'
        +    line 378: '  2019cc_16'
        +    line 379: '  2019cc_17'
        +    line 380: '  2019cc_18'
        +    line 381: '  2019cc_19'
        +    line 382: '  2019cc_20'
        +    line 383: '  2019cc_21'
        +    line 384: '  2019cc_22'
        +    line 385: '  2019cc_23'
        +    line 386: '  2019cc_24'
        +    line 387: '  2019cc_25'
         zh-Hans:
           src/data/en.yml:
        -    line 44: '  description-roni'
        -    line 45: '  project-phuong'
        -    line 17: Showcase
        -    line 25: ''
        -    line 26: showcase
        -    line 27: '  showcase-title'
        -    line 28: '  showcase-intro1'
        -    line 29: '  showcase-intro2'
        -    line 30: '  showcase-intro3'
        -    line 31: '  showcase-featuring'
        -    line 32: '  project-tag-art'
        -    line 33: '  project-tag-design'
        -    line 34: '  project-tag-code'
        -    line 35: '  project-tag-curriculum'
        -    line 36: '  project-tag-documentation'
        -    line 37: '  project-tag-game'
        -    line 38: '  project-tag-library'
        -    line 39: '  project-tag-organizing'
        -    line 40: '  project-tag-tool'
        -    line 41: '  project-tag-tutorial'
        -    line 42: '  project-roni'
        -    line 43: '  credit-roni'
        -    line 46: '  credit-phuong'
        -    line 47: '  description-phuong'
        -    line 48: '  project-daein'
        -    line 49: '  credit-daein'
        -    line 50: '  description-daein'
        -    line 51: '  project-qianqian'
        -    line 52: '  credit-qianqian'
        -    line 53: '  description-qianqian'
        -    line 54: '  project-casey-louise'
        -    line 55: '  credit-casey-louise'
        -    line 56: '  description-casey-louise'
        -    line 57: '  project-moon-xin'
        -    line 58: '  credit-moon-xin'
        -    line 59: '  description-moon-xin'
        -    line 516: '  showcase-intro3'
        -    line 517: '  showcase-featuring'
        -    line 518: '  project-tag-art'
        -    line 519: '  project-tag-design'
        -    line 520: '  project-tag-code'
        -    line 521: '  project-tag-curriculum'
        -    line 522: '  project-tag-documentation'
        -    line 523: '  project-tag-game'
        -    line 524: '  project-tag-library'
        -    line 525: '  project-tag-organizing'
        -    line 526: '  project-tag-tool'
        -    line 527: '  project-tag-tutorial'
        -    line 531: '  description-roni'
        -    line 358: '  p5.ble'
        -    line 364: '  p5.createloop'
        -    line 368: '  p5.experience'
        -    line 377: '  vida'
        -    line 380: '  p5.3D'
        -    line 363: '  p5.experience'
        -    line 329: '  coordinate-system-simple-shapes-p2x1'
        -    line 341: '  coordinate-system-simple-shapes-p9x1'
        -    line 99: '  your-first-sketch12'
        -    line 108: '  coordinate-system-simple-shapes-p2x1'
        +    line 49: '  RotatingKnobs'
        +    line 94: '  project-phuong'
        +    line 95: '  credit-phuong'
        +    line 98: '  credit-daein'
        +    line 107: '  credit-moon-xin'
        +    line 84: '  project-tag-curriculum'
        +    line 105: '  description-casey-louise'
        +    line 106: '  project-moon-xin'
        +    line 66: '  2015cc_5'
        +    line 75: showcase
        +    line 99: '  description-daein'
        +    line 108: '  description-moon-xin'
        +    line 89: '  project-tag-tool'
        +    line 90: '  project-tag-tutorial'
        +    line 91: '  project-roni'
        +    line 92: '  credit-roni'
        +    line 93: '  description-roni'
        +    line 96: '  description-phuong'
        +    line 97: '  project-daein'
        +    line 85: '  project-tag-documentation'
        +    line 86: '  project-tag-game'
        +    line 87: '  project-tag-library'
        +    line 15: Showcase
        +    line 74: ''
        +    line 76: '  showcase-title'
        +    line 88: '  project-tag-organizing'
        +    line 100: '  project-qianqian'
        +    line 101: '  credit-qianqian'
        +    line 102: '  description-qianqian'
        +    line 103: '  project-casey-louise'
        +    line 104: '  credit-casey-louise'
        +    line 7: Donate
        +    line 31: '  p5js-wiki-title'
        +    line 32: '  p5js-wiki'
        +    line 77: '  showcase-intro1'
        +    line 78: '  showcase-intro2'
        +    line 79: '  showcase-intro3'
        +    line 80: '  showcase-featuring'
        +    line 81: '  project-tag-art'
        +    line 82: '  project-tag-design'
        +    line 83: '  project-tag-code'
        +    line 52: '  p3xh2'
        +    line 44: '  p2x1'
        +    line 45: '  p2x2'
        +    line 48: '  p2x5'
        +    line 55: '  p3xp3'
        +    line 56: '  p3xp4'
        +    line 57: '  p3xp5'
        +    line 5: Editor
        +    line 46: '  p2x3'
        +    line 47: '  p2x4'
        +    line 50: '  p2x7'
        +    line 51: ''
        +    line 53: '  p3xp1'
        +    line 54: '  p3xp2'
        +    line 58: '  p3xp6'
        +    line 63: '  p4xp3'
        +    line 43: '  p2xh2'
        +    line 380: '  2019cc_18'
        +    line 373: '  2019cc_11'
        +    line 381: '  2019cc_19'
        +    line 371: '  2019cc_9'
        +    line 358: '  output11'
        +    line 364: '  2019cc_2'
        +    line 368: '  2019cc_6'
        +    line 377: '  2019cc_15'
        +    line 363: '  2019cc_1'
        +    line 329: '  2015cc_9'
        +    line 341: '  2019contributors-conference4'
        +    line 386: '  2019cc_24'
        +    line 359: '  output12'
        +    line 362: '  output15'
        +    line 374: '  2019cc_12'
        +    line 376: '  2019cc_14'
        +    line 379: '  2019cc_17'
        +    line 382: '  2019cc_20'
        +    line 355: '  output9'
        +    line 356: '  output9-1'
        +    line 360: '  output13'
        +    line 357: '  output10'
        +    line 361: '  output14'
        +    line 1: Skip-To-Content
        +    line 39: '  start-creating'
        +    line 40: '  p1xh1'
        +    line 41: '  p1x1'
        +    line 42: '  p1x2'
        +    line 59: ''
        +    line 60: '  p4xh2'
        +    line 61: '  p4xp1'
        +    line 62: '  p4xp2'
        +    line 64: '  p4xp4'
        +    line 65: '  p4xp5'
        +    line 2: Language-Settings
        +    line 3: Sidebar-Title
        +    line 67: ''
        +    line 370: '  2019cc_8'
        +    line 372: '  2019cc_10'
        +    line 383: '  2019cc_21'
        +    line 151: '  report-bugs'
        +    line 168: '  support-23'
        +    line 72: '  sketch_info_link'
        +    line 8: Start
        +    line 16: footerxh1
        +    line 71: '  sketch_info'
        +    line 117: '  book1'
        +    line 121: '  download-intro'
        +    line 122: '  editor-title'
        +    line 123: '  p5.js-editor'
        +    line 124: '  p5.js-editor-intro'
        +    line 125: '  editor-includes'
        +    line 127: '  complete-library-intro1'
        +    line 128: '  complete-library-intro2'
        +    line 129: '  complete-library-intro3'
        +    line 133: '  includes-2'
        +    line 136: '  single-files-intro'
        +    line 148: '  etc-title'
        +    line 149: '  older-releases'
        +    line 150: '  github-repository'
        +    line 153: ''
        +    line 155: '  support-options'
        +    line 164: '  support-20'
        +    line 176: '  support-17-alt'
        +    line 177: '  support-18-alt'
        +    line 178: '  support-19-alt'
        +    line 179: '  support-20-alt'
        +    line 180: '  support-21-alt'
        +    line 181: '  support-22-alt'
        +    line 182: '  support-23-alt'
        +    line 183: '  support-24-alt'
        +    line 184: '  support-25-alt'
        +    line 185: '  support-26-alt'
        +    line 186: '  support-27-alt'
        +    line 187: '  support-28-alt'
        +    line 188: '  support-29-alt'
        +    line 189: '  support-30-alt'
        +    line 190: '  support-30-alt'
        +    line 191: '  support-31-alt'
        +    line 200: '  core-libraries'
        +    line 201: '  community-libraries'
        +    line 202: '  libraries-created-by'
        +    line 213: '  asciiart'
        +    line 214: '  p5.ble'
        +    line 215: '  blizard.js'
        +    line 222: '  p5.clickable'
        +    line 223: '  p5.cmyk.js'
        +    line 224: '  p5.collide2D'
        +    line 225: '  p5.createloop'
        +    line 226: '  p5.dimensions'
        +    line 227: '  p5.EasyCam'
        +    line 228: '  p5.experience'
        +    line 229: '  p5.func'
        +    line 230: '  p5.geolocation'
        +    line 231: '  p5.gibber'
        +    line 232: '  grafica.js'
        +    line 233: '  p5.gui'
        +    line 234: '  p5.localmessage'
        +    line 235: '  marching'
        +    line 236: '  mappa'
        +    line 237: '  ml5.js'
        +    line 238: '  p5.play'
        +    line 239: '  p5.particle'
        +    line 240: '  p5.Riso'
        +    line 241: '  rita.js'
        +    line 242: '  Rotating Knobs'
        +    line 243: '  p5.scenemanager'
        +    line 244: '  p5.screenPosition'
        +    line 254: '  p5.serial'
        +    line 255: '  Shape5'
        +    line 256: '  p5.shape.js'
        +    line 257: '  p5.speech'
        +    line 258: '  p5.start2d.js'
        +    line 259: '  p5.tiledmap'
        +    line 260: '  p5.touchgui'
        +    line 261: '  tramontana'
        +    line 262: '  vida'
        +    line 263: '  p5.voronoi'
        +    line 264: '  p5.3D'
        +    line 272: '  sharing-title'
        +    line 273: '  sharing1'
        +    line 274: '  sharing2'
        +    line 275: '  sharing3'
        +    line 276: ''
        +    line 290: '  contributors-conference-title'
        +    line 291: '  contributors-conference1'
        +    line 292: '  contributors-conference2'
        +    line 293: '  participants-title'
        +    line 294: '  support-title'
        +    line 295: '  support1'
        +    line 296: '  support2'
        +    line 297: '  support3'
        +    line 298: '  support4'
        +    line 299: '  support5'
        +    line 300: '  support6'
        +    line 305: ''
        +    line 306: '  2015contributors-conference-title'
        +    line 307: '  2015contributors-conference-date'
        +    line 308: '  2015contributors-conference1'
        +    line 309: '  2015contributors-conference2'
        +    line 310: '  2015contributors-conference3'
        +    line 311: '  2015contributors-conference-diversity-title'
        +    line 312: '  2015contributors-conference-diversity1'
        +    line 313: '  2015contributors-conference-diversity2'
        +    line 314: '  2015contributors-conference-diversity3'
        +    line 315: '  2015contributors-conference-diversity4'
        +    line 316: '  2015contributors-conference-diversity5'
        +    line 317: '  2015contributors-conference-diversity6'
        +    line 318: '  2015contributors-conference-diversity7'
        +    line 319: '  2015contributors-conference-diversity8'
        +    line 320: '  2015contributors-conference-diversity9'
        +    line 321: '  2015cc_1'
        +    line 322: '  2015cc_2'
        +    line 323: '  2015cc_3'
        +    line 324: '  2015cc_4'
        +    line 325: '  2015cc_5'
        +    line 326: '  2015cc_6'
        +    line 327: '  2015cc_7'
        +    line 328: '  2015cc_8'
        +    line 330: '  2015cc_10'
        +    line 331: '  2015cc_11'
        +    line 332: '  2015cc_12'
        +    line 333: '  2015cc_13'
        +    line 334: '  2015cc_14'
        +    line 335: '  2015cc_15'
        +    line 336: '  2019contributors-conference-title'
        +    line 337: '  2019contributors-conference-date'
        +    line 338: '  2019contributors-conference1'
        +    line 339: '  2019contributors-conference2'
        +    line 340: '  2019contributors-conference3'
        +    line 342: '  outputs'
        +    line 343: '  output1'
        +    line 344: '  output2'
        +    line 345: '  output3'
        +    line 346: '  output3-1'
        +    line 347: '  output4'
        +    line 348: '  output5'
        +    line 349: '  output6'
        +    line 350: '  output6-1'
        +    line 351: '  output6-2'
        +    line 352: '  output7'
        +    line 353: '  output8'
        +    line 354: '  output8-1'
        +    line 365: '  2019cc_3'
        +    line 366: '  2019cc_4'
        +    line 367: '  2019cc_5'
        +    line 369: '  2019cc_7'
        +    line 375: '  2019cc_13'
        +    line 378: '  2019cc_16'
        +    line 384: '  2019cc_22'
        +    line 385: '  2019cc_23'
        +    line 387: '  2019cc_25'
        +    line 559: '  output3-1'
        +    line 568: '  output9'
        +    line 569: '  output9-1'
        +    line 555: '  output1'
        +    line 565: '  output8'
        +    line 566: '  output8-1'
        +    line 572: '  output14'
        +    line 554: '  outputs'
        +    line 556: '  output2'
        +    line 557: '  output3'
        +    line 558: '  output3-1'
        +    line 560: '  output5'
        +    line 561: '  output6'
        +    line 562: '  output6-1'
        +    line 563: '  output6-2'
        +    line 564: '  output7'
        +    line 567: '  output9'
        +    line 570: '  output12'
        +    line 571: '  output13'
        +    line 581: '  2019cc_25'
        +    line 413: '  p5.EasyCam'
        +    line 552: '  2019contributors-conference2'
        +    line 412: '  p5.EasyCam'
        +    line 425: '  p5.touchgui'
        +    line 13: '  start-creating'
        +    line 109: '  2019cc_21'
        +    line 110: '  2019cc_22'
        +    line 111: '  2019cc_23'
        +    line 545: '  2019contributors-conference-date'
        +    line 504: '  participants-title'
        +    line 505: '  support-title'
        +    line 506: '  support1'
        +    line 507: '  support2'
        +    line 508: '  support3'
        +    line 509: '  support4'
        +    line 510: '  support5'
        +    line 511: '  support6'
        +    line 34: '  p2xh2'
        +    line 391: '  p5.localmessage'
        +    line 399: '  Rotating Knobs'
        +    line 401: '  p5.screenPosition'
        +    line 404: '  Shape5'
        +    line 406: '  p5.start.js'
        +    line 407: '  p5.start2d.js'
        +    line 409: '  tramontana'
             line 120: '  coordinate-system-simple-shapes-p9x1'
        -    line 386: '  create-your-own4'
        -    line 359: '  p5.clickable'
        -    line 362: '  p5.dimensions1'
        -    line 373: '  mappa'
        -    line 374: '  p5.play'
        -    line 376: '  rita.js'
        -    line 379: '  p5.serial1'
        -    line 381: '  p5.serial3'
        -    line 382: '  p5.speech'
        -    line 391: '  p5.3D'
        -    line 355: '  asciiart'
        -    line 356: '  p5.ble'
        -    line 360: '  p5.createloop'
        -    line 371: '  vida'
        -    line 357: '  asciiart'
        -    line 361: '  p5.clickable'
        -    line 12: Showcase
        -    line 20: ''
        -    line 21: showcase
        -    line 22: '  Showcase'
        -    line 23: '  test'
        -    line 515: '  showcase-title'
        -    line 528: '  project-qianqian'
        -    line 529: '  credit-qianqian'
        -    line 530: '  description-qianqian'
        -    line 532: '  credit-conchinha-lessel'
        -    line 533: '  description-conchinha-lessel'
        -    line 535: '  description-phuong'
        -    line 539: '  description-daein'
        -    line 546: '  description-qianqian'
        -    line 547: '  project-casey-louise'
        -    line 548: '  credit-casey-louise'
        -    line 549: '  description-casey-louise'
        -    line 550: '  project-moon-xin'
        -    line 551: '  credit-moon-xin'
        -    line 552: '  description-moon-xin'
        -    line 669: '  credit-moon-xin'
        +    line 38: '  p1xh1'
        +    line 4: Sidebar-Title
        +    line 400: '  p5.collide2D'
        +    line 402: '  p5.dimensions'
        +    line 403: '  p5.experience'
        +    line 405: '  p5.geolocation'
        +    line 408: '  p5.gui'
        +    line 410: '  p5.play'
        +    line 411: '  p5.particle'
        +    line 424: '  p5.serial'
        +    line 426: '  p5.tiledmap'
        +    line 427: '  vida'
        +    line 428: '  p5.voronoi'
        +    line 429: '  p5.3D'
        +    line 156: '  etc-title'
        +    line 157: '  older-releases'
        +    line 158: '  github-repository'
        +    line 159: '  report-bugs'
        +    line 392: '  marching'
        +    line 394: '  ml5.js'
        +    line 397: '  p5.Riso'
        +    line 476: '  contributors-conference-title'
        +    line 477: '  contributors-conference1'
        +    line 478: '  contributors-conference2'
        +    line 479: '  contributors-conference3'
        +    line 480: '  contributors-conference4'
        +    line 485: ''
        +    line 486: '  2015contributors-conference-title'
        +    line 487: '  2015contributors-conference-date'
        +    line 488: '  2015contributors-conference1'
        +    line 489: '  2015contributors-conference2'
        +    line 490: '  2015contributors-conference3'
        +    line 491: '  2015contributors-conference-participants-title'
        +    line 492: '  2015contributors-conference-diversity-title'
        +    line 493: '  2015contributors-conference-diversity1'
        +    line 494: '  2015contributors-conference-diversity2'
        +    line 495: '  2015contributors-conference-diversity3'
        +    line 496: '  2015contributors-conference-diversity4'
        +    line 497: '  2015contributors-conference-diversity5'
        +    line 498: '  2015contributors-conference-diversity6'
        +    line 499: '  2015contributors-conference-diversity7'
        +    line 500: '  2015contributors-conference-diversity8'
        +    line 501: '  2015contributors-conference-diversity9'
        +    line 502: '  2015contributors-conference-support-title'
        +    line 503: '  2015contributors-conference-support1'
        +    line 512: '  2015cc_4'
        +    line 513: '  2015cc_5'
        +    line 514: '  2015cc_6'
        +    line 515: '  2015cc_7'
        +    line 516: '  2015cc_8'
        +    line 517: '  2015cc_9'
        +    line 518: '  2015cc_10'
        +    line 519: '  2015cc_11'
        +    line 520: '  2015cc_12'
        +    line 521: '  2015cc_13'
        +    line 522: '  2015cc_14'
        +    line 523: '  2015cc_15'
        +    line 139: '  download-intro'
        +    line 140: '  editor-title'
        +    line 141: '  p5.js-editor'
        +    line 142: '  p5.js-editor-intro'
        +    line 143: '  editor-includes'
        +    line 145: '  complete-library-intro1'
        +    line 146: '  complete-library-intro2'
        +    line 147: '  complete-library-intro3'
        +    line 154: '  single-files-intro'
        +    line 541: '  2019contributors-conference-title'
        +    line 542: '  2019contributors-conference-date'
        +    line 546: '  2019contributors-conference2'
        +    line 547: '  2019contributors-conference3'
        +    line 548: '  2019contributors-conference4'
        +    line 549: '  2019cc_1'
        +    line 550: '  2019cc_2'
        +    line 551: '  2019cc_3'
        +    line 553: '  2019cc_5'
        +    line 21: '  support-options'
        +    line 112: '  2019cc_24'
        +    line 420: '  p5.shape.js'
        +    line 573: '  output15'
        diff --git a/package-lock.json b/package-lock.json
        index a22b5b54a4..8b32dc5b08 100644
        --- a/package-lock.json
        +++ b/package-lock.json
        @@ -516,8 +516,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
               "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "arch": {
               "version": "2.1.1",
        @@ -622,7 +621,6 @@
               "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
               "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
                 "readable-stream": "^2.0.6"
        @@ -2759,7 +2757,6 @@
                   "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
                   "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "p-finally": "^1.0.0"
                   }
        @@ -3164,7 +3161,6 @@
               "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
               "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "get-proxy": "^2.0.0",
                 "isurl": "^1.0.0-alpha5",
        @@ -3517,7 +3513,6 @@
               "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
               "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "graceful-readlink": ">= 1.0.0"
               }
        @@ -3870,7 +3865,6 @@
               "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
               "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "ini": "^1.3.4",
                 "proto-list": "~1.2.1"
        @@ -3898,8 +3892,7 @@
               "version": "1.1.0",
               "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
               "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "console-stream": {
               "version": "0.1.1",
        @@ -3913,7 +3906,6 @@
               "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
               "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "safe-buffer": "5.1.2"
               }
        @@ -4677,7 +4669,6 @@
               "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
               "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.0.0",
                 "decompress-tarbz2": "^4.0.0",
        @@ -4694,7 +4685,6 @@
               "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
               "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "mimic-response": "^1.0.0"
               }
        @@ -4704,7 +4694,6 @@
               "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
               "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "file-type": "^5.2.0",
                 "is-stream": "^1.1.0",
        @@ -4715,8 +4704,7 @@
                   "version": "5.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
                   "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4725,7 +4713,6 @@
               "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
               "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.1.0",
                 "file-type": "^6.1.0",
        @@ -4738,8 +4725,7 @@
                   "version": "6.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
                   "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4748,7 +4734,6 @@
               "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
               "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.1.1",
                 "file-type": "^5.2.0",
        @@ -4759,8 +4744,7 @@
                   "version": "5.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
                   "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4769,7 +4753,6 @@
               "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
               "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "file-type": "^3.8.0",
                 "get-stream": "^2.2.0",
        @@ -4781,15 +4764,13 @@
                   "version": "3.9.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
                   "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 },
                 "get-stream": {
                   "version": "2.3.1",
                   "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
                   "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "object-assign": "^4.0.1",
                     "pinkie-promise": "^2.0.0"
        @@ -4896,8 +4877,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
               "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "delimiter-regex": {
               "version": "2.0.0",
        @@ -5117,8 +5097,7 @@
               "version": "0.1.4",
               "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
               "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "duplexify": {
               "version": "3.6.0",
        @@ -5745,7 +5724,6 @@
               "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
               "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "cross-spawn": "^5.0.1",
                 "get-stream": "^3.0.0",
        @@ -6040,7 +6018,6 @@
               "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
               "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "mime-db": "^1.28.0"
               }
        @@ -6050,7 +6027,6 @@
               "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
               "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "ext-list": "^2.0.0",
                 "sort-keys-length": "^1.0.0"
        @@ -6496,7 +6472,6 @@
               "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
               "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "pend": "~1.2.0"
               }
        @@ -6611,15 +6586,13 @@
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
               "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "filenamify": {
               "version": "2.1.0",
               "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz",
               "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "filename-reserved-regex": "^2.0.0",
                 "strip-outer": "^1.0.0",
        @@ -6956,7 +6929,6 @@
               "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
               "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "graceful-fs": "^4.1.2",
                 "inherits": "~2.0.0",
        @@ -6981,7 +6953,6 @@
               "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
               "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
                 "console-control-strings": "^1.0.0",
        @@ -6998,7 +6969,6 @@
                   "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
                   "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "code-point-at": "^1.0.0",
                     "is-fullwidth-code-point": "^1.0.0",
        @@ -7072,7 +7042,6 @@
               "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
               "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "npm-conf": "^1.1.0"
               }
        @@ -7087,8 +7056,7 @@
               "version": "3.0.0",
               "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
               "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "get-value": {
               "version": "2.0.6",
        @@ -7525,8 +7493,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
               "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "gray-matter": {
               "version": "3.1.1",
        @@ -8496,8 +8463,7 @@
               "version": "1.4.2",
               "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
               "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "has-symbols": {
               "version": "1.0.1",
        @@ -8510,7 +8476,6 @@
               "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
               "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "has-symbol-support-x": "^1.4.1"
               }
        @@ -8519,8 +8484,7 @@
               "version": "2.0.1",
               "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
               "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "has-value": {
               "version": "0.3.1",
        @@ -8941,7 +8905,6 @@
                   "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
                   "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "color-convert": "^1.9.0"
                   }
        @@ -8951,7 +8914,6 @@
                   "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
                   "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "ansi-styles": "^3.2.1",
                     "escape-string-regexp": "^1.0.5",
        @@ -8984,8 +8946,7 @@
                   "version": "3.0.0",
                   "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
                   "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 },
                 "is-svg": {
                   "version": "3.0.0",
        @@ -9002,7 +8963,6 @@
                   "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
                   "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "has-flag": "^3.0.0"
                   }
        @@ -9586,8 +9546,7 @@
               "version": "4.0.1",
               "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
               "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-number": {
               "version": "2.1.0",
        @@ -9628,8 +9587,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
               "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-observable": {
               "version": "1.1.0",
        @@ -9697,8 +9655,7 @@
               "version": "1.1.0",
               "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
               "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-plain-object": {
               "version": "2.0.4",
        @@ -9789,8 +9746,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
               "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-stream": {
               "version": "1.1.0",
        @@ -9912,7 +9868,6 @@
               "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
               "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "has-to-string-tag-x": "^1.2.0",
                 "is-object": "^1.0.1"
        @@ -11555,8 +11510,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
               "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "lpad-align": {
               "version": "1.1.2",
        @@ -12154,8 +12108,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
               "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "minimatch": {
               "version": "3.0.4",
        @@ -12424,8 +12377,7 @@
               "version": "1.0.5",
               "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
               "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "no-case": {
               "version": "2.3.2",
        @@ -12652,7 +12604,6 @@
               "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
               "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "config-chain": "^1.1.11",
                 "pify": "^3.0.0"
        @@ -12662,8 +12613,7 @@
                   "version": "3.0.0",
                   "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
                   "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -12672,7 +12622,6 @@
               "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
               "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "path-key": "^2.0.0"
               }
        @@ -12682,7 +12631,6 @@
               "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
               "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
                 "console-control-strings": "~1.1.0",
        @@ -13044,8 +12992,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
               "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "p-is-promise": {
               "version": "1.1.0",
        @@ -13106,7 +13053,6 @@
               "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
               "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "p-finally": "^1.0.0"
               }
        @@ -13276,8 +13222,7 @@
               "version": "2.0.1",
               "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
               "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "path-parse": {
               "version": "1.0.6",
        @@ -13317,8 +13262,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
               "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "picomatch": {
               "version": "2.2.1",
        @@ -15788,8 +15732,7 @@
               "version": "1.2.4",
               "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
               "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "pseudomap": {
               "version": "1.0.2",
        @@ -16919,7 +16862,6 @@
               "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
               "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "commander": "~2.8.1"
               }
        @@ -17142,8 +17084,7 @@
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
               "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "set-getter": {
               "version": "0.1.0",
        @@ -17431,7 +17372,6 @@
               "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
               "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "is-plain-obj": "^1.0.0"
               }
        @@ -17441,7 +17381,6 @@
               "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
               "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "sort-keys": "^1.0.0"
               }
        @@ -17905,7 +17844,6 @@
               "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
               "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "is-natural-number": "^4.0.1"
               }
        @@ -17914,8 +17852,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
               "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "strip-final-newline": {
               "version": "2.0.0",
        @@ -17951,7 +17888,6 @@
               "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
               "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "escape-string-regexp": "^1.0.2"
               }
        @@ -18270,15 +18206,13 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz",
               "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "tempfile": {
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz",
               "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "temp-dir": "^1.0.0",
                 "uuid": "^3.0.1"
        @@ -18619,8 +18553,7 @@
               "version": "4.0.1",
               "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
               "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "timers-browserify": {
               "version": "2.0.2",
        @@ -18925,7 +18858,6 @@
               "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
               "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "escape-string-regexp": "^1.0.2"
               }
        @@ -19004,7 +18936,6 @@
               "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz",
               "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "buffer": "^5.2.1",
                 "through": "^2.3.8"
        @@ -19015,7 +18946,6 @@
                   "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz",
                   "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "base64-js": "^1.0.2",
                     "ieee754": "^1.1.4"
        @@ -19286,8 +19216,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
               "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "use": {
               "version": "1.1.2",
        @@ -19679,7 +19608,6 @@
               "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
               "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
               }
        @@ -19810,7 +19738,6 @@
               "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
               "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "buffer-crc32": "~0.2.3",
                 "fd-slicer": "~1.1.0"
        diff --git a/package.json b/package.json
        index 5c5ee52bcf..e8b6d5fd17 100644
        --- a/package.json
        +++ b/package.json
        @@ -5,6 +5,7 @@
           "languages": [
             "en",
             "es",
        +    "ko",
             "zh-Hans"
           ],
           "homepage": "https://github.com/processing/p5.js-website",
        diff --git a/src/data/examples/ko/00_Structure/00_Coordinates.js b/src/data/examples/ko/00_Structure/00_Coordinates.js
        new file mode 100644
        index 0000000000..b7a9e4091b
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/00_Coordinates.js
        @@ -0,0 +1,34 @@
        +/*
        + * @name 좌표
        + * @description 모든 도형들은 좌표값으로 지정된 화면 위치에 나타납니다.
        + * 픽셀 단위를 기준으로 원점(0,0)으로부터의 거리 
        + * 모든 좌표값은 원점으로부터의 거리를 픽셀 단위로 측정합니다.
        + * 원점 [0,0]는 화면 좌측 상단의 좌표이며, 우측 하단의 좌표는 [너비-1, 높이-1]에 해당합니다.
        + */
        +function setup() {
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        +  createCanvas(720, 400);
        +}
        +
        +function draw() {
        +  // 배경색을 검정색(0)으로 지정, noFill()로 면채우기 기능 해제
        +  background(0);
        +  noFill();
        +    
        +  // point()의 괄호 안 두 인수로 좌표값 지정
        +  // 첫번째 인수는 x값을, 두번째 인수는 y값 의미
        +  stroke(255);
        +  point(width * 0.5, height * 0.5);
        +  point(width * 0.5, height * 0.25);
        +
        +  // 좌표를 활용해 점 뿐 아니라 모든 도형을 그릴 수 있습니다.
        +  // 각 함수별 괄호에 적힌 매개 변수들은 각기 다른 목적을 위해 사용됩니다.
        +  // 예를들어 line()함수에 쓰인 처음 두 매개 변수들은 각각 첫번째 그리고 두번째 끝점을 지정합니다.
        +  stroke(0, 153, 255);
        +  line(0, height * 0.33, width, height * 0.33);
        +
        +  // rect()함수의 처음 두 매개 변수는 상단 모서리의 좌표값을 의미하고,
        +  // 그 다음 두 매개 변수는 너비와 높이를 지정합니다.
        +  stroke(255, 153, 0);
        +  rect(width * 0.25, height * 0.1, width * 0.5, height * 0.8);
        +}
        diff --git a/src/data/examples/ko/00_Structure/01_Width_and_Height.js b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        new file mode 100644
        index 0000000000..933addbe47
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        @@ -0,0 +1,19 @@
        +/*
        + * @name 너비와 높이
        + * @description '너비(width)'와 '높이(height)' 변수들은 createCanvas() 함수에 따라
        + * 정의된, 윈도우 화면의 너비 및 높이 값을 포함합니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +}
        +
        +function draw() {
        +  background(127);
        +  noStroke();
        +  for (let i = 0; i < height; i += 20) {
        +    fill(129, 206, 15);
        +    rect(0, i, width, 10);
        +    fill(255);
        +    rect(i, 0, 10, height);
        +  }
        +}
        diff --git a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        new file mode 100644
        index 0000000000..b5517e7754
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        @@ -0,0 +1,25 @@
        +/*
        + * @name 설정하고 그리기
        + * @description draw()함수 안에의 코드는 위에서 아래 방향으로
        + * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
        + */
        +let y = 100;
        +
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
        +function setup() {
        +  // createCanvas가 그 첫 선언문입니다. 
        +  createCanvas(720, 400);
        +  stroke(255); // 선색을 흰색(255)으로 지정
        +  frameRate(30);
        +}
        +// draw()함 수 안 선언문은 프로그램이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
        +function draw() {
        +  background(0); // 배경색을 검정색(0)으로 지정
        +  y = y - 1;
        +  if (y < 0) {
        +    y = height;
        +  }
        +  line(0, y, width, y);
        +}
        diff --git a/src/data/examples/ko/00_Structure/03_No_Loop.js b/src/data/examples/ko/00_Structure/03_No_Loop.js
        new file mode 100644
        index 0000000000..107d2edf8b
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/03_No_Loop.js
        @@ -0,0 +1,28 @@
        +/*
        + * @name 루프 해제
        + * @description noLoop()함수는 draw()함수가 반복없이 단 한번만 실행되게 합니다.
        + * noLoop()를 호출하지 않는다면 draw()함수는 계속해서 반복 실행될 것입니다.
        + */
        +let y;
        +
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
        +function setup() {
        +  // createCanvas가 그 첫 선언문입니다.
        +  createCanvas(720, 400);
        +  stroke(255); // 선색을 흰색(255)으로 지정
        +  noLoop();
        +
        +  y = height * 0.5;
        +}
        +
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
        +function draw() {
        +  background(0); // 배경색을 검정색(0)으로 지정
        +  y = y - 1;
        +  if (y < 0) {
        +    y = height;
        +  }
        +  line(0, y, width, y);
        +}
        diff --git a/src/data/examples/ko/00_Structure/04_Loop.js b/src/data/examples/ko/00_Structure/04_Loop.js
        new file mode 100644
        index 0000000000..058a1d55a4
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/04_Loop.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 루프
        + * @description draw()함수 안에의 코드는 위에서 아래 방향으로
        + * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
        + */
        +let y = 100;
        +
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
        +function setup() {
        +  createCanvas(720, 400); // 캔버스 크기 지정이 그 첫 선언문입니다.
        +  stroke(255); // 선색을 흰색(255)로 지정
        +  frameRate(30);
        +}
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
        +function draw() {
        +  background(0); // 배경색을 검정색(0)으로 지정
        +  y = y - 1;
        +  if (y < 0) {
        +    y = height;
        +  }
        +  line(0, y, width, y);
        +}
        diff --git a/src/data/examples/ko/00_Structure/05_Redraw.js b/src/data/examples/ko/00_Structure/05_Redraw.js
        new file mode 100644
        index 0000000000..b4895ea150
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/05_Redraw.js
        @@ -0,0 +1,31 @@
        +/*
        + * @name 다시 그리기
        + * @description redraw()함수는 draw()함수를 다시 한번 실행합니다.
        + * 이 예제에서 draw()는 마우스가 클릭될 때마다 매번 재실행됩니다.
        + */
        +
        +let y;
        +
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
        +function setup() {
        +  createCanvas(720, 400);
        +  stroke(255);
        +  noLoop();
        +  y = height * 0.5;
        +}
        +
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
        +function draw() {
        +  background(0);
        +  y = y - 4;
        +  if (y < 0) {
        +    y = height;
        +  }
        +  line(0, y, width, y);
        +}
        +
        +function mousePressed() {
        +  redraw();
        +}
        diff --git a/src/data/examples/ko/00_Structure/06_Functions.js b/src/data/examples/ko/00_Structure/06_Functions.js
        new file mode 100644
        index 0000000000..47f31593aa
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/06_Functions.js
        @@ -0,0 +1,27 @@
        +/*
        + *@name 그 외 함수들
        + *@description 각 drawTarget()함수로 과녁판 형상의 도형 여러개를 쉽게 만들 수 있습니다.
        + *호출된 drawTarget()함수들은 각기 다른 과녁판 도형의 위치, 크기 그리고 고리 개수를 지정합니다.
        + */
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  background(51);
        +  noStroke();
        +  noLoop();
        +}
        +
        +function draw() {
        +  drawTarget(width * 0.25, height * 0.4, 200, 4);
        +  drawTarget(width * 0.5, height * 0.5, 300, 10);
        +  drawTarget(width * 0.75, height * 0.3, 120, 6);
        +}
        +
        +function drawTarget(xloc, yloc, size, num) {
        +  const grayvalues = 255 / num;
        +  const steps = size / num;
        +  for (let i = 0; i < num; i++) {
        +    fill(i * grayvalues);
        +    ellipse(xloc, yloc, size - i * steps, size - i * steps);
        +  }
        +}
        diff --git a/src/data/examples/ko/00_Structure/07_Recursion.js b/src/data/examples/ko/00_Structure/07_Recursion.js
        new file mode 100644
        index 0000000000..9833a01bae
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/07_Recursion.js
        @@ -0,0 +1,27 @@
        +/*
        + *@name 재귀 함수
        + *@description 재귀 함수는 자기 자신을 다시 호출하는 함수를 말합니다.
        + * drawCircle()함수가 블록 말미에 그 자신을 다시 호출하는 것을 볼 수 있습니다.
        + * 이 경우, drawCircle()함수의 변수인 "level"의 값이 1과 같아질 때까지 계속해서 재호출됩니다.
        + */
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  noLoop();
        +}
        +
        +function draw() {
        +  drawCircle(width / 2, 280, 6);
        +}
        +
        +function drawCircle(x, radius, level) {
        +  const tt = (126 * level) / 4.0;
        +  fill(tt);
        +  ellipse(x, height / 2, radius * 2, radius * 2);
        +  if (level > 1) {
        +    level = level - 1;
        +    drawCircle(x - radius / 2, radius / 2, level);
        +    drawCircle(x + radius / 2, radius / 2, level);
        +  }
        +}
        diff --git a/src/data/examples/ko/00_Structure/08_Create_Graphics.js b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        new file mode 100644
        index 0000000000..5af2a082bf
        --- /dev/null
        +++ b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        @@ -0,0 +1,29 @@
        +/*
        + * @name 그래픽 만들기
        + * @description 새로운 p5.Renderer 오브젝트를 만들고 반환합니다.
        + * 아래의 클래스는 특정 사각 스크린의 바깥 영역에 그래픽 버퍼를 만드는 데에 사용됩니다.
        + * 두 인수들은 사각 스크린의 너비와 높이값을 픽셀 단위로 각각 지정합니다.
        + */
        +
        +let pg;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  pg = createGraphics(400, 250);
        +}
        +
        +function draw() {
        +  fill(0, 12);
        +  rect(0, 0, width, height);
        +  fill(255);
        +  noStroke();
        +  ellipse(mouseX, mouseY, 60, 60);
        +
        +  pg.background(51);
        +  pg.noFill();
        +  pg.stroke(255);
        +  pg.ellipse(mouseX - 150, mouseY - 75, 60, 60);
        +
        +  //image() 선언문으로 사각 스크린 바깥에 위치한 그래픽 버퍼를 그립니다.
        +  image(pg, 150, 75);
        +}
        diff --git a/src/data/examples/ko/01_Form/00_Points_and_Lines.js b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        new file mode 100644
        index 0000000000..a7e1028623
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 점과 선
        + * @description 점과 선을 활용하여 기본적인 기하 형태를 그릴 수 있습니다.
        + * 도형의 크기 조정을 위해 변수인 'd'값을 바꿔보세요.
        + * 4개의 변수들은 d값을 기준으로 위치값을 설정합니다.
        + */
        +function setup() {
        +  let d = 70;
        +  let p1 = d;
        +  let p2 = p1 + d;
        +  let p3 = p2 + d;
        +  let p4 = p3 + d;
        +
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        +  createCanvas(720, 400);
        +  background(0);
        +  noSmooth();
        +
        +  translate(140, 0);
        +
        +  // 회색의 사각형 그리기
        +  stroke(153);
        +  line(p3, p3, p2, p3);
        +  line(p2, p3, p2, p2);
        +  line(p2, p2, p3, p2);
        +  line(p3, p2, p3, p3);
        +
        +  // 흰색 점들 그리기
        +  stroke(255);
        +  point(p1, p1);
        +  point(p1, p3);
        +  point(p2, p4);
        +  point(p3, p1);
        +  point(p4, p2);
        +  point(p4, p4);
        +}
        diff --git a/src/data/examples/ko/01_Form/01_Shape_Primitives.js b/src/data/examples/ko/01_Form/01_Shape_Primitives.js
        new file mode 100644
        index 0000000000..3a6a3d26e3
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/01_Shape_Primitives.js
        @@ -0,0 +1,31 @@
        +/*
        + * @name 기본 조형
        + * @description 기본 조형을 그리는 함수로는 triangle(),
        + * rect(), quad(), ellipse(), 그리고 arc()가 있습니다. 사각형은 rect()로,
        + * 원형은 ellipse()로 만들 수 있습니다. 도형의 위치와 크기 조정을 위해
        + * 각 함수들의 괄호 안 인수들을 반드시 지정해야합니다.
        + */
        +function setup() {
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        +  createCanvas(720, 400);
        +  background(0);
        +  noStroke();
        +
        +  fill(204);
        +  triangle(18, 18, 18, 360, 81, 360);
        +
        +  fill(102);
        +  rect(81, 81, 63, 63);
        +
        +  fill(204);
        +  quad(189, 18, 216, 18, 216, 360, 144, 360);
        +
        +  fill(255);
        +  ellipse(252, 144, 72, 72);
        +
        +  fill(204);
        +  triangle(288, 18, 351, 360, 288, 360);
        +
        +  fill(255);
        +  arc(479, 300, 280, 280, PI, TWO_PI);
        +}
        diff --git a/src/data/examples/ko/01_Form/02_Pie_Chart.js b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        new file mode 100644
        index 0000000000..248006533f
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        @@ -0,0 +1,33 @@
        +/*
        + * @name 파이형 차트
        + * @description arc()함수를 사용하여 배열에 저장된 데이터로 파이형 차트를 생성해보세요.
        + */
        +let angles = [30, 10, 45, 35, 60, 38, 75, 67];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  noLoop(); // 프로그램 시작시 한 번 실행 뒤 멈추기
        +}
        +
        +function draw() {
        +  background(100);
        +  pieChart(300, angles);
        +}
        +
        +function pieChart(diameter, data) {
        +  let lastAngle = 0;
        +  for (let i = 0; i < data.length; i++) {
        +    let gray = map(i, 0, data.length, 0, 255);
        +    fill(gray);
        +    arc(
        +      width / 2,
        +      height / 2,
        +      diameter,
        +      diameter,
        +      lastAngle,
        +      lastAngle + radians(angles[i])
        +    );
        +    lastAngle += radians(angles[i]);
        +  }
        +}
        diff --git a/src/data/examples/ko/01_Form/03_Regular_Polygon.js b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        new file mode 100644
        index 0000000000..0fd70871c0
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 정다각형
        + * @description 가장 좋아하는 정다각형이 있나요? 오각형? 육각형? 칠각형? 아니면, 이십각형은요?
        + * 이 예제에서 소개하는 polygon()함수는 그 어떠한 정다각형도 그릴 수 있습니다.
        + * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +}
        +
        +function draw() {
        +  background(102);
        +
        +  push();
        +  translate(width * 0.2, height * 0.5);
        +  rotate(frameCount / 200.0);
        +  polygon(0, 0, 82, 3);
        +  pop();
        +
        +  push();
        +  translate(width * 0.5, height * 0.5);
        +  rotate(frameCount / 50.0);
        +  polygon(0, 0, 80, 20);
        +  pop();
        +
        +  push();
        +  translate(width * 0.8, height * 0.5);
        +  rotate(frameCount / -100.0);
        +  polygon(0, 0, 70, 7);
        +  pop();
        +}
        +
        +function polygon(x, y, radius, npoints) {
        +  let angle = TWO_PI / npoints;
        +  beginShape();
        +  for (let a = 0; a < TWO_PI; a += angle) {
        +    let sx = x + cos(a) * radius;
        +    let sy = y + sin(a) * radius;
        +    vertex(sx, sy);
        +  }
        +  endShape(CLOSE);
        +}
        diff --git a/src/data/examples/ko/01_Form/04_Star.js b/src/data/examples/ko/01_Form/04_Star.js
        new file mode 100644
        index 0000000000..7e98f1d2b4
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/04_Star.js
        @@ -0,0 +1,45 @@
        +/*
        + * @name 별모양
        + * @description 이 예제에서 소개하는 star()함수는 여러가지 다양한 모양을 그립니다. 
        + * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +}
        +
        +function draw() {
        +  background(102);
        +
        +  push();
        +  translate(width * 0.2, height * 0.5);
        +  rotate(frameCount / 200.0);
        +  star(0, 0, 5, 70, 3);
        +  pop();
        +
        +  push();
        +  translate(width * 0.5, height * 0.5);
        +  rotate(frameCount / 50.0);
        +  star(0, 0, 80, 100, 40);
        +  pop();
        +
        +  push();
        +  translate(width * 0.8, height * 0.5);
        +  rotate(frameCount / -100.0);
        +  star(0, 0, 30, 70, 5);
        +  pop();
        +}
        +
        +function star(x, y, radius1, radius2, npoints) {
        +  let angle = TWO_PI / npoints;
        +  let halfAngle = angle / 2.0;
        +  beginShape();
        +  for (let a = 0; a < TWO_PI; a += angle) {
        +    let sx = x + cos(a) * radius2;
        +    let sy = y + sin(a) * radius2;
        +    vertex(sx, sy);
        +    sx = x + cos(a + halfAngle) * radius1;
        +    sy = y + sin(a + halfAngle) * radius1;
        +    vertex(sx, sy);
        +  }
        +  endShape(CLOSE);
        +}
        diff --git a/src/data/examples/ko/01_Form/05_Triangle_Strip.js b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        new file mode 100644
        index 0000000000..62308eea3d
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        @@ -0,0 +1,38 @@
        +/*
        + * @name 삼각형 고리
        + * @description 이라 그린버그(Ira Greenberg) 제작 예제. vertex()함수와
        + * beginShape(TRIANGLE_STRIP) 모드를 이용하여 닫힌 고리를 하나 생성하세요. 
        + * outsideRadius와 insideRadius 변수를 이용하여 각 고리의 지름(radius)을 조정할 수 있습니다.
        + */
        +let x;
        +let y;
        +let outsideRadius = 150;
        +let insideRadius = 100;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  background(204);
        +  x = width / 2;
        +  y = height / 2;
        +}
        +
        +function draw() {
        +  background(204);
        +
        +  let numPoints = int(map(mouseX, 0, width, 6, 60));
        +  let angle = 0;
        +  let angleStep = 180.0 / numPoints;
        +
        +  beginShape(TRIANGLE_STRIP);
        +  for (let i = 0; i <= numPoints; i++) {
        +    let px = x + cos(radians(angle)) * outsideRadius;
        +    let py = y + sin(radians(angle)) * outsideRadius;
        +    angle += angleStep;
        +    vertex(px, py);
        +    px = x + cos(radians(angle)) * insideRadius;
        +    py = y + sin(radians(angle)) * insideRadius;
        +    vertex(px, py);
        +    angle += angleStep;
        +  }
        +  endShape();
        +}
        diff --git a/src/data/examples/ko/01_Form/06_Bezier.js b/src/data/examples/ko/01_Form/06_Bezier.js
        new file mode 100644
        index 0000000000..e7e881637d
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/06_Bezier.js
        @@ -0,0 +1,26 @@
        +/*
        + * @name 베지어 곡선
        + * @description bezier()함수의 처음 두 인수들은 각각 곡선의 시작점과 끝점을 지정합니다.
        + * 중간의 인수들은 곡선의 모양을 조정하는 '조정점(control point)'들입니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  stroke(255);
        +  noFill();
        +}
        +
        +function draw() {
        +  background(0);
        +  for (let i = 0; i < 200; i += 20) {
        +    bezier(
        +      mouseX - i / 2.0,
        +      40 + i,
        +      410,
        +      20,
        +      440,
        +      300,
        +      240 - i / 16.0,
        +      300 + i / 8.0
        +    );
        +  }
        +}
        diff --git a/src/data/examples/ko/01_Form/07_3D_Primitives.js b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        new file mode 100644
        index 0000000000..d0a36e9c9a
        --- /dev/null
        +++ b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 3D 기본 조형
        + * @frame 720,400 (optional)
        + * @description 3D 오브젝트를 합성 공간에 수학적으로 배치하기.
        + * box()와 sphere()함수는 최소 한 개의 인수를 사용하여 그 크기를 조정할 수 있습니다.
        + * 도형의 위치는 translate()함수를 통해 조정할 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +}
        +
        +function draw() {
        +  background(100);
        +
        +  noStroke();
        +  fill(50);
        +  push();
        +  translate(-275, 175);
        +  rotateY(1.25);
        +  rotateX(-0.9);
        +  box(100);
        +  pop();
        +
        +  noFill();
        +  stroke(255);
        +  push();
        +  translate(500, height * 0.35, -200);
        +  sphere(300);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/02_Data/00_Variables.js b/src/data/examples/ko/02_Data/00_Variables.js
        new file mode 100644
        index 0000000000..9a80193720
        --- /dev/null
        +++ b/src/data/examples/ko/02_Data/00_Variables.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 변수들
        + * @description 변수는 값을 저장하기 위해 사용됩니다. 예제의 변수값을 바꿔 구성을 변형해보세요.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  background(0);
        +  stroke(153);
        +  strokeWeight(4);
        +  strokeCap(SQUARE);
        +
        +  let a = 50;
        +  let b = 120;
        +  let c = 180;
        +
        +  line(a, b, a + c, b);
        +  line(a, b + 10, a + c, b + 10);
        +  line(a, b + 20, a + c, b + 20);
        +  line(a, b + 30, a + c, b + 30);
        +
        +  a = a + c;
        +  b = height - b;
        +
        +  line(a, b, a + c, b);
        +  line(a, b + 10, a + c, b + 10);
        +  line(a, b + 20, a + c, b + 20);
        +  line(a, b + 30, a + c, b + 30);
        +
        +  a = a + c;
        +  b = height - b;
        +
        +  line(a, b, a + c, b);
        +  line(a, b + 10, a + c, b + 10);
        +  line(a, b + 20, a + c, b + 20);
        +  line(a, b + 30, a + c, b + 30);
        +}
        diff --git a/src/data/examples/ko/02_Data/01_True_and_False.js b/src/data/examples/ko/02_Data/01_True_and_False.js
        new file mode 100644
        index 0000000000..4ebc9f2224
        --- /dev/null
        +++ b/src/data/examples/ko/02_Data/01_True_and_False.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 참과 거짓
        + * @description 불리언(Boolean) 변수는 오직 'true(참)'과 'false(거짓)'이라는 두 개의 값만 갖습니다.
        + * 불리언과 함께 제어문을 사용하여 프로그램의 흐름을 조정하는 것이 일반적인 방식입니다. 
        + * 이 예제에서는, b값이 'true(참)'일 때 세로선들이 그려지고
        + * b값이 'false(거짓)'일 때 가로선들이 그려집니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  background(0);
        +  stroke(255);
        +
        +  let b = false;
        +  let d = 20;
        +  let middle = width / 2;
        +
        +  for (let i = d; i <= width; i += d) {
        +    b = i < middle;
        +
        +    if (b === true) {
        +      // 세로선
        +      line(i, d, i, height - d);
        +    }
        +
        +    if (b === false) {
        +      // 가로선
        +      line(middle, i - middle + d, width - d, i - middle + d);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/02_Data/03_Variable_Scope.js b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        new file mode 100644
        index 0000000000..371a0600b6
        --- /dev/null
        +++ b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        @@ -0,0 +1,44 @@
        +/*
        + * @name 변수 범위
        + * @description 변수는 '전역(global) 변수'로서 선언되거나, 그 범위를 조정하여 '지역(local) 변수'로 사용할 수 있습니다.
        + * 예를 들어, setup() 및 draw()함수 안에 선언된 변수들은 해당 함수들의 범위 내에서만 사용되는 '지역 변수'가 됩니다.
        + * '전역 변수'의 경우, setup() 및 draw()함수 범위 외에서 사용 가능합니다. 
        + * 어떤 함수의 '지역 변수'가 '전역 변수'와 동일한 이름으로 선언된 경우,
        + * 이 변수는 해당 함수에 한해 지역 변수로서 처리됩니다.
        + */
        +let a = 80; // Create a global variable "a"
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  background(0);
        +  stroke(255);
        +  noLoop();
        +}
        +
        +function draw() {
        +  // 전역 변수 a를 사용하여 선 그리기
        +  line(a, 0, a, height);
        +
        +  // 반복문 안에 지역 변수 a를 사용하기
        +  for (let a = 120; a < 200; a += 3) {
        +    line(a, 0, a, height);
        +  }
        +
        +  // 사용자가 만든 함수 drawAnotherLine() 호출하기
        +  drawAnotherLine();
        +
        +  // 사용자가 만든 함수 drawYetAnotherLine() 호출하기
        +  drawYetAnotherLine();
        +}
        +
        +function drawAnotherLine() {
        +  // 이 함수에 대한 지역 변수로서 새로운 a 선언하기
        +  let a = 320;
        +  // 지역 변수 a를 사용하여 선 그리기  line(a, 0, a, height);
        +}
        +
        +function drawYetAnotherLine() {
        +  // 새로운 지역 변수 a를 선언하지 않았으므로,
        +  // 이 선은 위에서 선언된 전역 변수 a(값 80)를 사용하여 그려집니다.
        +  line(a + 3, 0, a + 3, height);
        +}
        diff --git a/src/data/examples/ko/02_Data/04_Numbers.js b/src/data/examples/ko/02_Data/04_Numbers.js
        new file mode 100644
        index 0000000000..56dd62c09e
        --- /dev/null
        +++ b/src/data/examples/ko/02_Data/04_Numbers.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 숫자값
        + * @frame 720,400
        + * @description 숫자값은 소수점과 함께, 또는 없이 사용할 수 있습니다.
        + * 보통 "int"라 불리는 정수(integer)는 소수점이 없는 숫자를 말합니다.
        + * 실수(float)는 소수점 이하 자릿수를 갖는 부동소수점 숫자를 말합니다.
        + */
        +let a = 0; // "a"를 숫자형 전역 변수로 선언
        +let b = 0; // "b"를 숫자형 전역 변수로 선언
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  stroke(255);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  a = a + 1; // a를 정수 단위로 증가
        +  b = b + 0.2; // b를 실수 단위로 증가
        +  line(a, 0, a, height / 2);
        +  line(b, height / 2, b, height);
        +
        +  if (a > width) {
        +    a = 0;
        +  }
        +  if (b > width) {
        +    b = 0;
        +  }
        +}
        diff --git a/src/data/examples/ko/03_Arrays/00_Array.js b/src/data/examples/ko/03_Arrays/00_Array.js
        new file mode 100644
        index 0000000000..4f624aaaa8
        --- /dev/null
        +++ b/src/data/examples/ko/03_Arrays/00_Array.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 배열
        + * @description 배열은 데이터의 리스트를 말합니다. 배열 속 각 데이터는 
        + * 배열에서의 위치를 나타내는 색인(index) 번호로 식별됩니다. 배열의 시작은 0을 기준으로 합니다.
        + * 따라서, 배열의 첫 번째 데이터는 [0]이고 두 번째 데이터는 [1]로 식별됩니다.
        + * 이 예제에서는 "coswave"라는 배열을 만들고, 이를 코사인 값으로 채웁니다.
        + * 데이터는 실행 화면상 세 가지의 다른 방법으로 표현됩니다.
        + */
        +let coswave = [];
        +
        +function setup() {
        +  createCanvas(720, 360);
        +  for (let i = 0; i < width; i++) {
        +    let amount = map(i, 0, width, 0, PI);
        +    coswave[i] = abs(cos(amount));
        +  }
        +  background(255);
        +  noLoop();
        +}
        +
        +function draw() {
        +  let y1 = 0;
        +  let y2 = height / 3;
        +  for (let i = 0; i < width; i += 3) {
        +    stroke(coswave[i] * 255);
        +    line(i, y1, i, y2);
        +  }
        +
        +  y1 = y2;
        +  y2 = y1 + y1;
        +  for (let i = 0; i < width; i += 3) {
        +    stroke((coswave[i] * 255) / 4);
        +    line(i, y1, i, y2);
        +  }
        +
        +  y1 = y2;
        +  y2 = height;
        +  for (let i = 0; i < width; i += 3) {
        +    stroke(255 - coswave[i] * 255);
        +    line(i, y1, i, y2);
        +  }
        +}
        diff --git a/src/data/examples/ko/03_Arrays/01_Array_2d.js b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        new file mode 100644
        index 0000000000..47da9cc5f1
        --- /dev/null
        +++ b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        @@ -0,0 +1,37 @@
        +/*
        + * @name 2D 배열
        + * @description 2차원(2D) 배열 작성을 위한 구문입니다.
        + * 2D 배열의 값은 두 개의 색인(index)값을 통해 가져올 수 있습니다.
        + * 2D 배열은 이미지를 저장하는 데에 유용합니다. 
        + * 이 예제에서 각 점의 색상은 이미지 중심으로부터의 거리에 따라 지정됩니다.
        + */
        +let distances = [];
        +let maxDistance;
        +let spacer;
        +
        +function setup() {
        +  createCanvas(720, 360);
        +  maxDistance = dist(width / 2, height / 2, width, height);
        +  for (let x = 0; x < width; x++) {
        +    distances[x] = []; // 중첩 배열 만들기
        +    for (let y = 0; y < height; y++) {
        +      let distance = dist(width / 2, height / 2, x, y);
        +      distances[x][y] = (distance / maxDistance) * 255;
        +    }
        +  }
        +  spacer = 10;
        +  noLoop(); // 한번 실행 후 멈추기
        +}
        +
        +function draw() {
        +  background(0);
        +  // 이 함수에 내장된 반복문은 앞서 선언된 spacer변수에 따라 배열값 사이의 간격을 생성하게 됩니다.
        +  // 따라서, 이 함수로 그려진 것보다 더 많은 값이 배열에 있는 셈입니다.
        +  // spacer 변수의 값을 변경하여 점들 간의 밀도를 조정해보세요.
        +  for (let x = 0; x < width; x += spacer) {
        +    for (let y = 0; y < height; y += spacer) {
        +      stroke(distances[x][y]);
        +      point(x + spacer / 2, y + spacer / 2);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/03_Arrays/02_Array_Objects.js b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        new file mode 100644
        index 0000000000..8379a2066e
        --- /dev/null
        +++ b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        @@ -0,0 +1,71 @@
        +/*
        + * @name 객체 배열
        + * @description 사용자가 정의한 객체 배열을 만듭니다.
        + */
        +
        +class Module {
        +  constructor(xOff, yOff, x, y, speed, unit) {
        +    this.xOff = xOff;
        +    this.yOff = yOff;
        +    this.x = x;
        +    this.y = y;
        +    this.speed = speed;
        +    this.unit = unit;
        +    this.xDir = 1;
        +    this.yDir = 1;
        +  }
        +
        +  // 사용자 정의한 메소드를 통해 변수들을 업데이트합니다.
        +  update() {
        +    this.x = this.x + this.speed * this.xDir;
        +    if (this.x >= this.unit || this.x <= 0) {
        +      this.xDir *= -1;
        +      this.x = this.x + 1 * this.xDir;
        +      this.y = this.y + 1 * this.yDir;
        +    }
        +    if (this.y >= this.unit || this.y <= 0) {
        +      this.yDir *= -1;
        +      this.y = this.y + 1 * this.yDir;
        +    }
        +  }
        +
        +  // 사용자가 정의한 메소드를 통해 오브젝트를 그립니다.
        +  draw() {
        +    fill(255);
        +    ellipse(this.xOff + this.x, this.yOff + this.y, 6, 6);
        +  }
        +}
        +
        +let unit = 40;
        +let count;
        +let mods = [];
        +
        +function setup() {
        +  createCanvas(720, 360);
        +  noStroke();
        +  let wideCount = width / unit;
        +  let highCount = height / unit;
        +  count = wideCount * highCount;
        +
        +  let index = 0;
        +  for (let y = 0; y < highCount; y++) {
        +    for (let x = 0; x < wideCount; x++) {
        +      mods[index++] = new Module(
        +        x * unit,
        +        y * unit,
        +        unit / 2,
        +        unit / 2,
        +        random(0.05, 0.8),
        +        unit
        +      );
        +    }
        +  }
        +}
        +
        +function draw() {
        +  background(0);
        +  for (let i = 0; i < count; i++) {
        +    mods[i].update();
        +    mods[i].draw();
        +  }
        +}
        diff --git a/src/data/examples/ko/04_Control/00_Iteration.js b/src/data/examples/ko/04_Control/00_Iteration.js
        new file mode 100644
        index 0000000000..5bfeee8b68
        --- /dev/null
        +++ b/src/data/examples/ko/04_Control/00_Iteration.js
        @@ -0,0 +1,41 @@
        +/*
        + * @name for 반복문
        + * @description "for"구조를 사용하여 반복 형식을 만듭니다.
        + */
        +let y;
        +let num = 14;
        +
        +function setup() {
        +  createCanvas(720, 360);
        +  background(102);
        +  noStroke();
        +
        +  // 흰색 막대기들 그리기
        +  fill(255);
        +  y = 60;
        +  for (let i = 0; i < num / 3; i++) {
        +    rect(50, y, 475, 10);
        +    y += 20;
        +  }
        +
        +  // 회색 막대기들
        +  fill(51);
        +  y = 40;
        +  for (let i = 0; i < num; i++) {
        +    rect(405, y, 30, 10);
        +    y += 20;
        +  }
        +  y = 50;
        +  for (let i = 0; i < num; i++) {
        +    rect(425, y, 30, 10);
        +    y += 20;
        +  }
        +
        +  // 얇은 선들
        +  y = 45;
        +  fill(0);
        +  for (let i = 0; i < num - 1; i++) {
        +    rect(120, y, 40, 1);
        +    y += 20;
        +  }
        +}
        diff --git a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        new file mode 100644
        index 0000000000..33c571bb01
        --- /dev/null
        +++ b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        @@ -0,0 +1,21 @@
        +/*
        + * @name for 내장 반복문
        + * @description "for" 반복문 구조를 이중 사용하여 2차원 도형을 반복할 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(720, 360);
        +  background(0);
        +  noStroke();
        +
        +  let gridSize = 35;
        +
        +  for (let x = gridSize; x <= width - gridSize; x += gridSize) {
        +    for (let y = gridSize; y <= height - gridSize; y += gridSize) {
        +      noStroke();
        +      fill(255);
        +      rect(x - 1, y - 1, 3, 3);
        +      stroke(255, 50);
        +      line(x, y, width / 2, height / 2);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/04_Control/02_Conditionals_1.js b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        new file mode 100644
        index 0000000000..3d809536b0
        --- /dev/null
        +++ b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 조건문 1
        + * @description 조건문은 마치 질문과도 같습니다.
        + * 프로그램은 조건문이 던지는 질문이 참인지 거짓인지에 따라
        + * 특정 선언문을 실행할 지 여부를 결정합니다.
        + * 조건문으로 던지는 질문들은 언제나 논리 또는 관계 선언문의 형식을 갖습니다. 
        + * 이 예제의 경우, 변수 i가 0이라는 조건이 충족될 시 선이 그려집니다.
        + */
        +function setup() {
        +  createCanvas(720, 360);
        +  background(0);
        +
        +  for (let i = 10; i < width; i += 10) {
        +    // i가 20으로 나누어 떨어진다면, 첫번째 선을 그린다.
        +    // 그렇지 않을 경우, 두번째 선을 그린다.
        +    if (i % 20 === 0) {
        +      stroke(255);
        +      line(i, 80, i, height / 2);
        +    } else {
        +      stroke(153);
        +      line(i, 20, i, 180);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/04_Control/03_Conditionals_2.js b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        new file mode 100644
        index 0000000000..bde90ef016
        --- /dev/null
        +++ b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        @@ -0,0 +1,27 @@
        +/*
        + * @name 조건문 2
        + * @description 조건문 1 예제에 "else"라는 키워드를 더해 조건문의 문법을 확장해봅시다.
        + * "else"를 사용하면 연속하여 2개 이상의 질문을 던질 수 있습니다.
        + * 이 때, 각각의 질문은 서로 다른 행위를 요청할 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(720, 360);
        +  background(0);
        +
        +  for (let i = 2; i < width - 2; i += 4) {
        +    // i가 20으로 나누어 떨어질 경우
        +    if (i % 20 === 0) {
        +      stroke(255);
        +      line(i, 80, i, height / 2);
        +      // i가 10으로 나누어 떨어질 경우
        +    } else if (i % 10 === 0) {
        +      stroke(153);
        +      line(i, 20, i, 180);
        +      // 위의 두 조건 모두 충족하지 않을 경우
        +      // 이 선을 그린다.
        +    } else {
        +      stroke(102);
        +      line(i, height / 2, i, height - 20);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/04_Control/04_Logical_Operators.js b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        new file mode 100644
        index 0000000000..db1a918329
        --- /dev/null
        +++ b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        @@ -0,0 +1,43 @@
        +/*
        + * @name 논리적 연산자
        + * @description 논리 연산자인 AND (&&) 와 OR (||) 는 
        + * 간단한 관계 선언문에 좀 더 복잡한 조건을 더할 때 쓰입니다.
        + * NOT (!) 연산자는 불리언 선언문을 부정할 때 쓰입니다.
        + */
        +let test = false;
        +
        +function setup() {
        +  createCanvas(720, 360);
        +  background(126);
        +
        +  for (let i = 5; i <= height; i += 5) {
        +    // 논리적 연산자 AND
        +    stroke(0);
        +    if (i > 35 && i < 100) {
        +      line(width / 4, i, width / 2, i);
        +      test = false;
        +    }
        +
        +    // 논리적 연산자 OR
        +    stroke(76);
        +    if (i <= 35 || i >= 100) {
        +      line(width / 2, i, width, i);
        +      test = true;
        +    }
        +
        +    // 불리언 값이 참(true)인지 여부를 테스트
        +    // "if(test)"이 "if(test == true)"와 동일한지 여부를 확인
        +    if (test) {
        +      stroke(0);
        +      point(width / 3, i);
        +    }
        +
        +      
        +    // 불리언 값이 거짓(false)인지 여부를 테스트
        +    // "if(!test)"이 "if(test == false)"와 동일한지 여부를 확인
        +    if (!test) {
        +      stroke(255);
        +      point(width / 4, i);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        new file mode 100644
        index 0000000000..5111273db6
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        @@ -0,0 +1,19 @@
        +/*
        + * @name 이미지 불러오기 및 보이기
        + * @description 이미지를 실제 또는 다른 크기로 지정하여 화면상 불러오고 보이게 할 수 있습니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let img; // 변수 'img' 선언
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  img = loadImage('assets/moonwalk.jpg'); // 이미지 불러오기
        +}
        +
        +function draw() {
        +  // 이미지를 화면상 좌표 (0,0) 위치에 실제 크기로 보이게 한다.
        +  image(img, 0, 0);
        +  // 이미지를 화면상 좌표 (0,높이/2) 위치에 절반 크기로 보이게 한다.
        +  image(img, 0, height / 2, img.width / 2, img.height / 2);
        +}
        diff --git a/src/data/examples/ko/05_Image/01_Background_Image.js b/src/data/examples/ko/05_Image/01_Background_Image.js
        new file mode 100644
        index 0000000000..2dd361abad
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/01_Background_Image.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 배경 이미지
        + * @description 이 예제는 배경 이미지를 불러오는 가장 빠른 방법을 소개합니다. This example presents the fastest way to load a
        + * 이미지 파일을 배경으로 쓰기 위해선, 이미지의 너비와 높이를 
        + * 프로그램 화면 크기와 동일하게 맞추면 됩니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let bg;
        +let y = 0;
        +
        +function setup() {
        +  // 이미지 파일을 배경으로 쓰기 위해, createCanvas() 메소드의 인수에
        +  // 이미지 크기와 동일한 사이즈를 기입하면 됩니다.
        +  // 이 예제의 경우, 이미지 크기는 720x400 픽셀입니다.
        +  bg = loadImage('assets/moonwalk.jpg');
        +  createCanvas(720, 400);
        +}
        +
        +function draw() {
        +  background(bg);
        +
        +  stroke(226, 204, 0);
        +  line(0, y, width, y);
        +
        +  y++;
        +  if (y > height) {
        +    y = 0;
        +  }
        +}
        diff --git a/src/data/examples/ko/05_Image/02_Transparency.js b/src/data/examples/ko/05_Image/02_Transparency.js
        new file mode 100644
        index 0000000000..dd608742d3
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/02_Transparency.js
        @@ -0,0 +1,23 @@
        +/*
        + * @name 투명도
        + * @description 마우스 포인터를 좌우로 움직혀 이미지의 위치를 옮겨보세요.
        + * 이 예제의 경우, tint()함수로 알파값이 수정된 이미지를 원본 이미지에 위에 겹쳐 보여줍니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let img;
        +let offset = 0;
        +let easing = 0.05;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  img = loadImage('assets/moonwalk.jpg'); // 프로그램상 이미지 불러오기
        +}
        +
        +function draw() {
        +  image(img, 0, 0); // 이미지를 투명도 100%로 보이게하기
        +  let dx = mouseX - img.width / 2 - offset;
        +  offset += dx * easing;
        +  tint(255, 127); // 이미지를 투명도 50%로 보이게하기
        +  image(img, offset, 0);
        +}
        diff --git a/src/data/examples/ko/05_Image/03_Alpha_Mask.js b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        new file mode 100644
        index 0000000000..ad500307c6
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        @@ -0,0 +1,26 @@
        +/*
        + * @name 알파 마스크
        + * @description 이미지 일부의 투명도를 설정하기 위해 마스크를 불러옵니다.
        + * 이미지와 마스크는 p5.Image의 mask() 메소드를 통해 합쳐집니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let img;
        +let imgMask;
        +
        +function preload() {
        +  img = loadImage('assets/moonwalk.jpg');
        +  imgMask = loadImage('assets/mask.png');
        +}
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  img.mask(imgMask);
        +  imageMode(CENTER);
        +}
        +
        +function draw() {
        +  background(0, 102, 153);
        +  image(img, width / 2, height / 2);
        +  image(img, mouseX, mouseY);
        +}
        diff --git a/src/data/examples/ko/05_Image/04_Create_Image.js b/src/data/examples/ko/05_Image/04_Create_Image.js
        new file mode 100644
        index 0000000000..da7700fd21
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/04_Create_Image.js
        @@ -0,0 +1,25 @@
        +/*
        + * @name 이미지 만들기
        + * @description createImage() 함수로 재밌는 픽셀 버퍼를 만들 수 있습니다.
        + * 이 예제는 그래디언트 이미지를 만듭니다.
        + */
        +let img; // Declare variable 'img'.
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  img = createImage(230, 230);
        +  img.loadPixels();
        +  for (let x = 0; x < img.width; x++) {
        +    for (let y = 0; y < img.height; y++) {
        +      let a = map(y, 0, img.height, 255, 0);
        +      img.set(x, y, [0, 153, 204, a]);
        +    }
        +  }
        +  img.updatePixels();
        +}
        +
        +function draw() {
        +  background(0);
        +  image(img, 90, 80);
        +  image(img, mouseX - img.width / 2, mouseY - img.height / 2);
        +}
        diff --git a/src/data/examples/ko/05_Image/05_Pointillism.js b/src/data/examples/ko/05_Image/05_Pointillism.js
        new file mode 100644
        index 0000000000..04a9391294
        --- /dev/null
        +++ b/src/data/examples/ko/05_Image/05_Pointillism.js
        @@ -0,0 +1,32 @@
        +/*
        + * @name 점묘법
        + * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스의 가로 위치는 점의 크기를 조정합니다. 
        + * 픽셀에 따라 색칠된 원형(ellipse)으로 간단한 점묘법 효과를 만듭니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let img;
        +let smallPoint, largePoint;
        +
        +function preload() {
        +  img = loadImage('assets/moonwalk.jpg');
        +}
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  smallPoint = 4;
        +  largePoint = 40;
        +  imageMode(CENTER);
        +  noStroke();
        +  background(255);
        +  img.loadPixels();
        +}
        +
        +function draw() {
        +  let pointillize = map(mouseX, 0, width, smallPoint, largePoint);
        +  let x = floor(random(img.width));
        +  let y = floor(random(img.height));
        +  let pix = img.get(x, y);
        +  fill(pix, 128);
        +  ellipse(x, y, pointillize, pointillize);
        +}
        diff --git a/src/data/examples/ko/07_Color/00_Hue.js b/src/data/examples/ko/07_Color/00_Hue.js
        new file mode 100644
        index 0000000000..3719823704
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/00_Hue.js
        @@ -0,0 +1,25 @@
        +/*
        + * @name 색조
        + * @description 색조는 오브젝트에 반사되거나 이를 통해 전달된 색상을 말하며,
        + * 일반적으로 색상명(빨강, 파랑, 노랑 등)으로 불립니다.
        + * 마우스 커서를 세로축으로 움직여 막대기의 색조를 변경해 보세요.
        + */
        +const barWidth = 20;
        +let lastBar = -1;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  colorMode(HSB, height, height, height);
        +  noStroke();
        +  background(0);
        +}
        +
        +function draw() {
        +  let whichBar = mouseX / barWidth;
        +  if (whichBar !== lastBar) {
        +    let barX = whichBar * barWidth;
        +    fill(mouseY, height, height);
        +    rect(barX, 0, barWidth, height);
        +    lastBar = whichBar;
        +  }
        +}
        diff --git a/src/data/examples/ko/07_Color/01_Saturation.js b/src/data/examples/ko/07_Color/01_Saturation.js
        new file mode 100644
        index 0000000000..0e9cb3fff6
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/01_Saturation.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 채도
        + * @description 채도는 회색이 차지하는 비율에 따른, 색조의 짙음 또는 맑음 정도를 말합니다.
        + * 포화된 색은 맑고, 불포화된 색은 높은 비율의 회색조를 갖습니다.
        + * 마우스 커서를 세로축으로 움직여 막대기의 채도를 변경해 보세요.
        + */
        +const barWidth = 20;
        +let lastBar = -1;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  colorMode(HSB, width, height, 100);
        +  noStroke();
        +}
        +
        +function draw() {
        +  let whichBar = mouseX / barWidth;
        +  if (whichBar !== lastBar) {
        +    let barX = whichBar * barWidth;
        +    fill(barX, mouseY, 66);
        +    rect(barX, 0, barWidth, height);
        +    lastBar = whichBar;
        +  }
        +}
        diff --git a/src/data/examples/ko/07_Color/02_Brightness.js b/src/data/examples/ko/07_Color/02_Brightness.js
        new file mode 100644
        index 0000000000..46352ed4bb
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/02_Brightness.js
        @@ -0,0 +1,46 @@
        +/*
        + * @name 밝기
        + * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스와 각 픽셀 간의 거리값을 
        + * 계산하여 이미지 일부의 밝기를 조정합니다. 
        + * <p><em><span class="small"> 로컬 컴퓨터에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        + */
        +let img;
        +
        +function preload() {
        +  img = loadImage('assets/moonwalk.jpg');
        +}
        +
        +function setup() {
        +  createCanvas(720, 200);
        +  pixelDensity(1);
        +  img.loadPixels();
        +  loadPixels();
        +}
        +
        +function draw() {
        +  for (let x = 0; x < img.width; x++) {
        +    for (let y = 0; y < img.height; y++) {
        +      // 2D 그리드로부터 1차원 위치 계산
        +      let loc = (x + y * img.width) * 4;
        +      // 이미지에서 R,G,B값 받기
        +      let r, g, b;
        +      r = img.pixels[loc];
        +      // 마우스와의 거리에 따라 변경할 밝기 계산
        +      let maxdist = 50;
        +      let d = dist(x, y, mouseX, mouseY);
        +      let adjustbrightness = (255 * (maxdist - d)) / maxdist;
        +      r += adjustbrightness;
        +      // RGB의 색상 범위가 0-255에 국한되도록 설정
        +      r = constrain(r, 0, 255);
        +      // 새로운 색상 생성 후 화면에 픽셀 위치 고정
        +      //color c = color(r, g, b);
        +      let pixloc = (y * width + x) * 4;
        +      pixels[pixloc] = r;
        +      pixels[pixloc + 1] = r;
        +      pixels[pixloc + 2] = r;
        +      pixels[pixloc + 3] = 255;
        +    }
        +  }
        +  updatePixels();
        +}
        diff --git a/src/data/examples/ko/07_Color/03_Color_Variables.js b/src/data/examples/ko/07_Color/03_Color_Variables.js
        new file mode 100644
        index 0000000000..5c3aa3d911
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/03_Color_Variables.js
        @@ -0,0 +1,40 @@
        +/*
        + * @name 색상 변수
        + * @description (Albers에게 바칩니다.) 이 예제는 색상 조정을 위한 변수 생성 방법을 다룹니다.
        + * 이 때, 변수들은 숫자가 아닌 특정 명칭으로 지정됩니다.
        + */
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +  background(51, 0, 0);
        +
        +  let inside = color(204, 102, 0);
        +  let middle = color(204, 153, 0);
        +  let outside = color(153, 51, 0);
        +
        +  // 아래의 변수 선언문은 위의 선언문들과 동일합니다.
        +  // 둘 중 원하는 형식을 사용하면 됩니다.
        +  //let inside = color('#CC6600');
        +  //let middle = color('#CC9900');
        +  //let outside = color('#993300');
        +
        +  push();
        +  translate(80, 80);
        +  fill(outside);
        +  rect(0, 0, 200, 200);
        +  fill(middle);
        +  rect(40, 60, 120, 120);
        +  fill(inside);
        +  rect(60, 90, 80, 80);
        +  pop();
        +
        +  push();
        +  translate(360, 80);
        +  fill(inside);
        +  rect(0, 0, 200, 200);
        +  fill(outside);
        +  rect(40, 60, 120, 120);
        +  fill(middle);
        +  rect(60, 90, 80, 80);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/07_Color/04_Relativity.js b/src/data/examples/ko/07_Color/04_Relativity.js
        new file mode 100644
        index 0000000000..f54aef95d9
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/04_Relativity.js
        @@ -0,0 +1,34 @@
        +/*
        + * @name 상대성
        + * @description 각 색상은 다른 색상과의 관계 속에서 인식됩니다. 
        + * 상단과 하단의 막대기들은 둘 다 동일한 색상 요소들을 갖지만,
        + * 색상 요소들의 배열에 따라 마치 다른 색조를 갖는 듯 보입니다.
        + */
        +let a, b, c, d, e;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +  a = color(165, 167, 20);
        +  b = color(77, 86, 59);
        +  c = color(42, 106, 105);
        +  d = color(165, 89, 20);
        +  e = color(146, 150, 127);
        +  noLoop(); // 반복없이 한번만 그리기
        +}
        +
        +function draw() {
        +  drawBand(a, b, c, d, e, 0, width / 128);
        +  drawBand(c, a, d, b, e, height / 2, width / 128);
        +}
        +
        +function drawBand(v, w, x, y, z, ypos, barWidth) {
        +  let num = 5;
        +  let colorOrder = [v, w, x, y, z];
        +  for (let i = 0; i < width; i += barWidth * num) {
        +    for (let j = 0; j < num; j++) {
        +      fill(colorOrder[j]);
        +      rect(i + j * barWidth, ypos, barWidth, height / 2);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/07_Color/05_Linear_Gradient.js b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        new file mode 100644
        index 0000000000..12e322f2a6
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        @@ -0,0 +1,51 @@
        +/*
        + * @name 선형 그래디언트
        + * @description lerpColor() 함수는 두 가지 색상을 보간하는 데에 쓰입니다.
        + */
        +// Constants
        +const Y_AXIS = 1;
        +const X_AXIS = 2;
        +let b1, b2, c1, c2;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // Define colors
        +  b1 = color(255);
        +  b2 = color(0);
        +  c1 = color(204, 102, 0);
        +  c2 = color(0, 102, 153);
        +
        +  noLoop();
        +}
        +
        +function draw() {
        +  // Background
        +  setGradient(0, 0, width / 2, height, b1, b2, X_AXIS);
        +  setGradient(width / 2, 0, width / 2, height, b2, b1, X_AXIS);
        +  // Foreground
        +  setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
        +  setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
        +}
        +
        +function setGradient(x, y, w, h, c1, c2, axis) {
        +  noFill();
        +
        +  if (axis === Y_AXIS) {
        +    // Top to bottom gradient
        +    for (let i = y; i <= y + h; i++) {
        +      let inter = map(i, y, y + h, 0, 1);
        +      let c = lerpColor(c1, c2, inter);
        +      stroke(c);
        +      line(x, i, x + w, i);
        +    }
        +  } else if (axis === X_AXIS) {
        +    // Left to right gradient
        +    for (let i = x; i <= x + w; i++) {
        +      let inter = map(i, x, x + w, 0, 1);
        +      let c = lerpColor(c1, c2, inter);
        +      stroke(c);
        +      line(i, y, i, y + h);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/07_Color/06_Radial_Gradient.js b/src/data/examples/ko/07_Color/06_Radial_Gradient.js
        new file mode 100644
        index 0000000000..ce2df1dde5
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/06_Radial_Gradient.js
        @@ -0,0 +1,32 @@
        +/*
        + * @name 방사형 그래디언트
        + * @description 동심원을 그려 한 색상이 다른 색상으로 퍼지는 듯한 효과를 만듭니다.
        + */
        +let dim;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  dim = width / 2;
        +  background(0);
        +  colorMode(HSB, 360, 100, 100);
        +  noStroke();
        +  ellipseMode(RADIUS);
        +  frameRate(1);
        +}
        +
        +function draw() {
        +  background(0);
        +  for (let x = 0; x <= width; x += dim) {
        +    drawGradient(x, height / 2);
        +  }
        +}
        +
        +function drawGradient(x, y) {
        +  let radius = dim / 2;
        +  let h = random(0, 360);
        +  for (let r = radius; r > 0; --r) {
        +    fill(h, 90, 90);
        +    ellipse(x, y, r, r);
        +    h = (h + 1) % 360;
        +  }
        +}
        diff --git a/src/data/examples/ko/07_Color/07_Lerp_Color.js b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        new file mode 100644
        index 0000000000..0c1324183f
        --- /dev/null
        +++ b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        @@ -0,0 +1,49 @@
        +/*
        + * @name 선형 보간(lerp) 색상
        + * @description 무작위의 도형을 반복하고,
        + * 빨강색과 파란색을 선형적으로 보간합니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  background(255);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(255);
        +  from = color(255, 0, 0, 0.2 * 255);
        +  to = color(0, 0, 255, 0.2 * 255);
        +  c1 = lerpColor(from, to, 0.33);
        +  c2 = lerpColor(from, to, 0.66);
        +  for (let i = 0; i < 15; i++) {
        +    fill(from);
        +    quad(
        +      random(-40, 220), random(height),
        +      random(-40, 220), random(height),
        +      random(-40, 220), random(height),
        +      random(-40, 220), random(height)
        +    );
        +    fill(c1);
        +    quad(
        +      random(140, 380), random(height),
        +      random(140, 380), random(height),
        +      random(140, 380), random(height),
        +      random(140, 380), random(height)
        +    );
        +    fill(c2);
        +    quad(
        +      random(320, 580), random(height),
        +      random(320, 580), random(height),
        +      random(320, 580), random(height),
        +      random(320, 580), random(height)
        +    );
        +    fill(to);
        +    quad(
        +      random(500, 760), random(height),
        +      random(500, 760), random(height),
        +      random(500, 760), random(height),
        +      random(500, 760), random(height)
        +    );
        +  }
        +  frameRate(5);
        +}
        diff --git a/src/data/examples/ko/08_Math/00_incrementdecrement.js b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        new file mode 100644
        index 0000000000..2fa2db7120
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 증가와 감소
        + * @description "a++"는 "a = a + 1"와 같은 표현입니다.
        + * "a--"는 "a = a - 1"과 같은 표현입니다.
        + */
        +let a;
        +let b;
        +let direction;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  colorMode(RGB, width);
        +  a = 0;
        +  b = width;
        +  direction = true;
        +  frameRate(30);
        +}
        +
        +function draw() {
        +  a++;
        +  if (a > width) {
        +    a = 0;
        +    direction = !direction;
        +  }
        +  if (direction === true) {
        +    stroke(a);
        +  } else {
        +    stroke(width - a);
        +  }
        +  line(a, 0, a, height / 2);
        +
        +  b--;
        +  if (b < 0) {
        +    b = width;
        +  }
        +  if (direction == true) {
        +    stroke(width - b);
        +  } else {
        +    stroke(b);
        +  }
        +  line(b, height / 2 + 1, b, height);
        +}
        diff --git a/src/data/examples/ko/08_Math/01_operatorprecedence.js b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        new file mode 100644
        index 0000000000..b4cdcd4eef
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        @@ -0,0 +1,51 @@
        +/*
        + * @name 연산자 우선 순위
        + * @description 연산자의 실행 순서를 명시하는 경우를 제하고, 모든 선언문은 연산자 우선 순위에 따라
        + * 처리됩니다. 예를 들어, "4+2*8"에서 2는 가장 먼저 8에 곱해지고, 그 결과값이 4에 더해집니다.
        + * 이는 "*"이 "+"보다 높은 우선 순위를 갖기 때문입니다.
        + * 혼동 방지를 위해 "4+(2*8)"라 쓰는 것이 권장되기도 합니다.
        + * 이처럼, 코드 내에 괄호를 사용하여 처리 순서를 명시할 수 있습니다.
        + * 연산자 우선 순위는 다음과 같습니다.
        + */
        +// 처리 순위가 높은 연산자는 목록 상단에, 
        +// 가장 낲은 연산자는 목록 하단에 적힙니다.
        +// 곱하기 연산자: * / %
        +// 증감 연산자: + -
        +// 비교 연산자: < > <= >=
        +// 등호 연산자: == !=
        +// 논리 연산자 AND: &&
        +// 논리 연산자 OR: ||
        +// 할당 연산자: = += -= *= /= %=
        +function setup() {
        +  createCanvas(710, 400);
        +  background(51);
        +  noFill();
        +  stroke(51);
        +
        +  stroke(204);
        +  for (let i = 0; i < width - 20; i += 4) {
        +    // 70이 30을 더한 결과값이
        +    // 현재 "i"값보다 큰 지의 여부를 평가
        +    // 처리 순서를 명확히하고자 "if (i > (30 + 70)) {"로 작성
        +    if (i > 30 + 70) {
        +      line(i, 0, i, 50);
        +    }
        +  }
        +
        +  stroke(255);
        +  // 2와 8을 곱한 뒤, 그 결과값에 4를 더함
        +  // 처리 순서를 명확히하고자, "rect(5 + (2 * 8), 0, 90, 20);"로 작성
        +  rect(4 + 2 * 8, 52, 290, 48);
        +  rect((4 + 2) * 8, 100, 290, 49);
        +
        +  stroke(153);
        +  for (let i = 0; i < width; i += 2) {
        +    // 비교 선언문을 가장 먼저 처리한 뒤,
        +    // 다음으로 논리 연산자 AND, 마지막으로 논리 연산자 OR 순으로 처리.
        +    // 처리 순서를 명확히하고자 다음과 같이 작성:
        +    // "if(((i > 20) && (i < 50)) || ((i > 100) && (i < width-20))) {"
        +    if ((i > 20 && i < 50) || (i > 100 && i < width - 20)) {
        +      line(i, 151, i, height - 1);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/02_distance1d.js b/src/data/examples/ko/08_Math/02_distance1d.js
        new file mode 100644
        index 0000000000..36e93c6904
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/02_distance1d.js
        @@ -0,0 +1,64 @@
        +/*
        + * @name 1D 거리
        + * @description 마우스를 좌우로 움직여, 화면 속 도형의 움직임 속도와 방향을 조정해보세요.
        + */
        +let xpos1;
        +let xpos2;
        +let xpos3;
        +let xpos4;
        +let thin = 8;
        +let thick = 36;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +  xpos1 = width / 2;
        +  xpos2 = width / 2;
        +  xpos3 = width / 2;
        +  xpos4 = width / 2;
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let mx = mouseX * 0.4 - width / 5.0;
        +
        +  fill(102);
        +  rect(xpos2, 0, thick, height / 2);
        +  fill(204);
        +  rect(xpos1, 0, thin, height / 2);
        +  fill(102);
        +  rect(xpos4, height / 2, thick, height / 2);
        +  fill(204);
        +  rect(xpos3, height / 2, thin, height / 2);
        +
        +  xpos1 += mx / 16;
        +  xpos2 += mx / 64;
        +  xpos3 -= mx / 16;
        +  xpos4 -= mx / 64;
        +
        +  if (xpos1 < -thin) {
        +    xpos1 = width;
        +  }
        +  if (xpos1 > width) {
        +    xpos1 = -thin;
        +  }
        +  if (xpos2 < -thick) {
        +    xpos2 = width;
        +  }
        +  if (xpos2 > width) {
        +    xpos2 = -thick;
        +  }
        +  if (xpos3 < -thin) {
        +    xpos3 = width;
        +  }
        +  if (xpos3 > width) {
        +    xpos3 = -thin;
        +  }
        +  if (xpos4 < -thick) {
        +    xpos4 = width;
        +  }
        +  if (xpos4 > width) {
        +    xpos4 = -thick;
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/03_distance2d.js b/src/data/examples/ko/08_Math/03_distance2d.js
        new file mode 100644
        index 0000000000..3fa5d7efa0
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/03_distance2d.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 2D 거리
        + * @description 이미지 위로 마우스를 움직여, 매트릭스를 흐리게 또는 뚜렷하게 만들어보세요.
        + * 각 타원과 마우스 간의 거리에 비례하여 원형의 크기가 조정됩니다.
        + */
        +let max_distance;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +  max_distance = dist(0, 0, width, height);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  for (let i = 0; i <= width; i += 20) {
        +    for (let j = 0; j <= height; j += 20) {
        +      let size = dist(mouseX, mouseY, i, j);
        +      size = (size / max_distance) * 66;
        +      ellipse(i, j, size, size);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/04_sine.js b/src/data/examples/ko/08_Math/04_sine.js
        new file mode 100644
        index 0000000000..566b2faa99
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/04_sine.js
        @@ -0,0 +1,27 @@
        +/*
        + * @name 싸인
        + * @description sin() 함수로 도형의 크기를 부드럽게 조정합니다.
        + */
        +let diameter;
        +let angle = 0;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  diameter = height - 10;
        +  noStroke();
        +  fill(255, 204, 0);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let d1 = 10 + (sin(angle) * diameter) / 2 + diameter / 2;
        +  let d2 = 10 + (sin(angle + PI / 2) * diameter) / 2 + diameter / 2;
        +  let d3 = 10 + (sin(angle + PI) * diameter) / 2 + diameter / 2;
        +
        +  ellipse(0, height / 2, d1, d1);
        +  ellipse(width / 2, height / 2, d2, d2);
        +  ellipse(width, height / 2, d3, d3);
        +
        +  angle += 0.02;
        +}
        diff --git a/src/data/examples/ko/08_Math/05_sincosine.js b/src/data/examples/ko/08_Math/05_sincosine.js
        new file mode 100644
        index 0000000000..dbb6fd2b42
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/05_sincosine.js
        @@ -0,0 +1,43 @@
        +/*
        + * @name 싸인 코싸인
        + * @description sin()와 cos() 함수를 이용한 선형적 움직임.
        + * 0과 PI*2 사이의 숫자(TWO_PI의 경우, 약 6.28)를 위의 함수에 넣으면
        + * -1과 1 사이의 값이 반환됩니다.
        + * 이러한 반환값은 더 큰 움직임을 만드는 척도로서 쓰입니다.
        + */
        +let angle1 = 0;
        +let angle2 = 0;
        +let scalar = 70;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +  rectMode(CENTER);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let ang1 = radians(angle1);
        +  let ang2 = radians(angle2);
        +
        +  let x1 = width / 2 + scalar * cos(ang1);
        +  let x2 = width / 2 + scalar * cos(ang2);
        +
        +  let y1 = height / 2 + scalar * sin(ang1);
        +  let y2 = height / 2 + scalar * sin(ang2);
        +
        +  fill(255);
        +  rect(width * 0.5, height * 0.5, 140, 140);
        +
        +  fill(0, 102, 153);
        +  ellipse(x1, height * 0.5 - 120, scalar, scalar);
        +  ellipse(x2, height * 0.5 + 120, scalar, scalar);
        +
        +  fill(255, 204, 0);
        +  ellipse(width * 0.5 - 120, y1, scalar, scalar);
        +  ellipse(width * 0.5 + 120, y2, scalar, scalar);
        +
        +  angle1 += 2;
        +  angle2 += 3;
        +}
        diff --git a/src/data/examples/ko/08_Math/06_sinewave.js b/src/data/examples/ko/08_Math/06_sinewave.js
        new file mode 100644
        index 0000000000..46ca3fe589
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/06_sinewave.js
        @@ -0,0 +1,47 @@
        +/*
        + * @name 싸인파
        + * @description 간단한 싸인파를 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman)이 원본 제작.
        + */
        +
        +let xspacing = 16; // 각 도형들 간의 가로 거리
        +let w; // 전체 파형의 너비
        +let theta = 0.0; // 시작 각도 0
        +let amplitude = 75.0; // 파형의 높이
        +let period = 500.0; // 파형이 반복되기 전까지 생성되는 픽셀 갯수
        +let dx; // x 증가값
        +let yvalues; // 파형의 최고 높이를 저장하기 위한 배열
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  w = width + 16;
        +  dx = (TWO_PI / period) * xspacing;
        +  yvalues = new Array(floor(w / xspacing));
        +}
        +
        +function draw() {
        +  background(0);
        +  calcWave();
        +  renderWave();
        +}
        +
        +function calcWave() {
        +  // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
        +  theta += 0.02;
        +
        +  // 매 x값마다 싸인 함수를 이용해 y값을 계산
        +  let x = theta;
        +  for (let i = 0; i < yvalues.length; i++) {
        +    yvalues[i] = sin(x) * amplitude;
        +    x += dx;
        +  }
        +}
        +
        +function renderWave() {
        +  noStroke();
        +  fill(255);
        +  // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
        +  for (let x = 0; x < yvalues.length; x++) {
        +    ellipse(x * xspacing, height / 2 + yvalues[x], 16, 16);
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/07_additivewave.js b/src/data/examples/ko/08_Math/07_additivewave.js
        new file mode 100644
        index 0000000000..46694c8c10
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/07_additivewave.js
        @@ -0,0 +1,67 @@
        +/*
        + * @name 파형 추가
        + * @description 두 개의 파형을 합쳐 좀 더 복잡한 파도 모양을 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
        + */
        +let xspacing = 8; // 각 타원 간 가로 거리
        +let w; // 전체 파형의 너비
        +let maxwaves = 4; // 더해진 파형들의 전체 갯수
        +
        +let theta = 0.0;
        +let amplitude = new Array(maxwaves); // 파형의 높이
        +// X를 증가하는 값으로, period와 xspacing로 계산됨
        +let dx = new Array(maxwaves);
        +// 파형의 최고 높이를 저장하기 위한 배열 (반드시 필요한 건 아님)
        +let yvalues;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  frameRate(30);
        +  colorMode(RGB, 255, 255, 255, 100);
        +  w = width + 16;
        +
        +  for (let i = 0; i < maxwaves; i++) {
        +    amplitude[i] = random(10, 30);
        +    let period = random(100, 300); // 파형이 반복되기 전까지 생성되는 픽셀 갯수
        +    dx[i] = (TWO_PI / period) * xspacing;
        +  }
        +
        +  yvalues = new Array(floor(w / xspacing));
        +}
        +
        +function draw() {
        +  background(0);
        +  calcWave();
        +  renderWave();
        +}
        +
        +function calcWave() {
        +  // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
        +  theta += 0.02;
        +
        +  // 모든 높이값을 0으로 설정
        +  for (let i = 0; i < yvalues.length; i++) {
        +    yvalues[i] = 0;
        +  }
        +
        +  // 파형 높이값 축적하기
        +  for (let j = 0; j < maxwaves; j++) {
        +    let x = theta;
        +    for (let i = 0; i < yvalues.length; i++) {
        +      // 매번 모든 파형들은 싸인 대신 코싸인으로 처리
        +      if (j % 2 == 0) yvalues[i] += sin(x) * amplitude[j];
        +      else yvalues[i] += cos(x) * amplitude[j];
        +      x += dx[j];
        +    }
        +  }
        +}
        +
        +function renderWave() {
        +  // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
        +  noStroke();
        +  fill(255, 50);
        +  ellipseMode(CENTER);
        +  for (let x = 0; x < yvalues.length; x++) {
        +    ellipse(x * xspacing, width / 2 + yvalues[x], 16, 16);
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/08_polartocartesian.js b/src/data/examples/ko/08_Math/08_polartocartesian.js
        new file mode 100644
        index 0000000000..16907e4cfd
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/08_polartocartesian.js
        @@ -0,0 +1,44 @@
        +/*
        + * @name 극좌표를 직교 좌표로
        + * @description 극좌표(지름 r, 세타 theta)를 직교 좌표(x,y)로 변환
        + * : x = rcos(theta) y = rsin(theta)
        + * 다니엘 쉬프만(Daniel Shiffman)이 원본 제작.
        + */
        +let r;
        +
        +// 각도, 각속도, 가속
        +let theta;
        +let theta_vel;
        +let theta_acc;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 모든값 초기화
        +  r = height * 0.45;
        +  theta = 0;
        +  theta_vel = 0;
        +  theta_acc = 0.0001;
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // 원점을 화면 중간 위치에 해당하는 좌표값으로 설정
        +  translate(width / 2, height / 2);
        +
        +  // 극좌표를 직교 좌표로 변환
        +  let x = r * cos(theta);
        +  let y = r * sin(theta);
        +
        +  // 직교 좌표에서 타원 그리기
        +  ellipseMode(CENTER);
        +  noStroke();
        +  fill(200);
        +  ellipse(x, y, 32, 32);
        +
        +  // 가속도와 속도를 각도에 적용하기
        +  // (이 예제에서 r은 고정됩니다.)
        +  theta_vel += theta_acc;
        +  theta += theta_vel;
        +}
        diff --git a/src/data/examples/ko/08_Math/09_arctangent.js b/src/data/examples/ko/08_Math/09_arctangent.js
        new file mode 100644
        index 0000000000..21c053b7fd
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/09_arctangent.js
        @@ -0,0 +1,45 @@
        +/*
        + * @name 아크탄젠트
        + * @description 마우스를 움직여 눈의 방향을 바꿔보세요. <br>atan2()함수는 마우스 커서와 눈의 각도를 계산합니다.
        + */
        +let e1, e2, e3;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  e1 = new Eye(250, 16, 120);
        +  e2 = new Eye(164, 185, 80);
        +  e3 = new Eye(420, 230, 220);
        +}
        +
        +function draw() {
        +  background(102);
        +  e1.update(mouseX, mouseY);
        +  e2.update(mouseX, mouseY);
        +  e3.update(mouseX, mouseY);
        +  e1.display();
        +  e2.display();
        +  e3.display();
        +}
        +
        +function Eye(tx, ty, ts) {
        +  this.x = tx;
        +  this.y = ty;
        +  this.size = ts;
        +  this.angle = 0;
        +
        +  this.update = function(mx, my) {
        +    this.angle = atan2(my - this.y, mx - this.x);
        +  };
        +
        +  this.display = function() {
        +    push();
        +    translate(this.x, this.y);
        +    fill(255);
        +    ellipse(0, 0, this.size, this.size);
        +    rotate(this.angle);
        +    fill(153, 204, 0);
        +    ellipse(this.size / 4, 0, this.size / 2, this.size / 2);
        +    pop();
        +  };
        +}
        diff --git a/src/data/examples/ko/08_Math/10_Interpolate.js b/src/data/examples/ko/08_Math/10_Interpolate.js
        new file mode 100644
        index 0000000000..eff9e09115
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/10_Interpolate.js
        @@ -0,0 +1,32 @@
        +/*
        + * @name 선형 보간법
        + * @frame 720, 400
        + * @description 화면 위로 마우스를 움직이면 타원이 따라옵니다.
        + * 애니메이션의 매 프레임 사이에, 타원은 현재 위치에서 커서를 향해 지정된 거리(0.05)의 일부만큼 움직입니다.
        + * 이는 lerp() 함수를 사용하여 구현된 것입니다.
        + * 이 예제는 인풋>이징(Easing) 예제와 동일한 효과를 만들지만, lerp()만으로 구현한다는 점에서 다릅니다.
        + */
        +
        +let x = 0;
        +let y = 0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  // lerp()는 특정 값만큼 증가하는 두 개의 숫자로부터 결과값을 계산합니다.
        +  // amt인수는 이 두 개의 숫자를 선형적으로 결정하는데,
        +  // 0.0은 처음 위치, 0.1은 첫번째 점과 아주 가까운 위치, 0.5는 앞의 두 점의 중간 위치인 식입니다.
        +
        +  // 매 프레임마다 마우스 위치를 향해 5%의 거리를 움직이도록 합니다.
        +  x = lerp(x, mouseX, 0.05);
        +  y = lerp(y, mouseY, 0.05);
        +
        +  fill(255);
        +  stroke(255);
        +  ellipse(x, y, 66, 66);
        +}
        diff --git a/src/data/examples/ko/08_Math/11_doubleRandom.js b/src/data/examples/ko/08_Math/11_doubleRandom.js
        new file mode 100644
        index 0000000000..5abd9f7b01
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/11_doubleRandom.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name Double Random
        + * @frame 720,400 (optional)
        + * @description Using two random() calls and the point()
        + * function to create an irregular sawtooth line.
        + * Original by by Ira Greenberg.
        + */
        +let totalPts = 300;
        +let steps = totalPts + 1;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  stroke(255);
        +  frameRate(1);
        +}
        +
        +function draw() {
        +  background(0);
        +  let rand = 0;
        +  for (let i = 1; i < steps; i++) {
        +    point((width / steps) * i, height / 2 + random(-rand, rand));
        +    rand += random(-5, 5);
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/12_random.js b/src/data/examples/ko/08_Math/12_random.js
        new file mode 100644
        index 0000000000..6475297be5
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/12_random.js
        @@ -0,0 +1,19 @@
        +/*
        + * @name Random
        + * @description Random numbers create the basis of this image.
        + * Each time the program is loaded the result is different.
        + */
        +function setup() {
        +  createCanvas(710, 400);
        +  background(0);
        +  strokeWeight(20);
        +  frameRate(2);
        +}
        +
        +function draw() {
        +  for (let i = 0; i < width; i++) {
        +    let r = random(255);
        +    stroke(r);
        +    line(i, 0, i, height);
        +  }
        +}
        diff --git a/src/data/examples/ko/08_Math/13_noise1D.js b/src/data/examples/ko/08_Math/13_noise1D.js
        new file mode 100644
        index 0000000000..6d9fb9ca69
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/13_noise1D.js
        @@ -0,0 +1,31 @@
        +/*
        + * @name 1D 노이즈
        + * @description 1차원 펄린 노이즈를 사용해 위치를 지정합니다.
        + */
        +let xoff = 0.0;
        +let xincrement = 0.01;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  background(0);
        +  noStroke();
        +}
        +
        +function draw() {
        +  // 알파값이 섞인 배경 생성
        +  fill(0, 10);
        +  rect(0, 0, width, height);
        +
        +  //let n = random(0,width);  // 노이즈 대신 이 줄을 사용할 수 있습니다.
        +
        +  // xoff로 노이즈값을 지정하고
        +  // 화면의 너비에 따라 크기 조정
        +  let n = noise(xoff) * width;
        +
        +  // 매 사이클마다 xoff만큼 증가
        +  xoff += xincrement;
        +
        +  // 펄린 노이즈가 생성한 값으로 타원 그리기
        +  fill(200);
        +  ellipse(n, height / 2, 64, 64);
        +}
        diff --git a/src/data/examples/ko/08_Math/14_noisewave.js b/src/data/examples/ko/08_Math/14_noisewave.js
        new file mode 100644
        index 0000000000..ca8d2ad731
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/14_noisewave.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 노이즈 파형
        + * @description 펄린 노이즈를 사용하여 파도같은 패턴을 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
        + */
        +let yoff = 0.0; // 펄린 노이즈의 2차원
        +
        +function setup() {
        +  createCanvas(710, 400);
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  fill(255);
        +  // 파형의 점들을 이용한 다각형 그리기
        +  beginShape();
        +
        +  let xoff = 0; // 옵션 #1: 2D 노이즈
        +  // let xoff = yoff; // 옵션 #2: 1D 노이즈
        +
        +  // 가로 픽셀들에 반복
        +  for (let x = 0; x <= width; x += 10) {
        +    // y값을 노이즈에 따라 계산, 다음에 맵핑(map)하기
        +
        +    // 옵션 #1: 2D 노이즈
        +    let y = map(noise(xoff, yoff), 0, 1, 200, 300);
        +
        +    // 옵션 #2: 1D 노이즈
        +    // let y = map(noise(xoff), 0, 1, 200,300);
        +
        +    // 버텍스 설정하기
        +    vertex(x, y);
        +    // 노이즈의 x차원 증가하기
        +    xoff += 0.05;
        +  }
        +  // 노이즈의 y차원 증가하기
        +  yoff += 0.01;
        +  vertex(width, height);
        +  vertex(0, height);
        +  endShape(CLOSE);
        +}
        diff --git a/src/data/examples/ko/08_Math/15_Noise2D.js b/src/data/examples/ko/08_Math/15_Noise2D.js
        new file mode 100644
        index 0000000000..16091565b7
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/15_Noise2D.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 2D 노이즈
        + * @frame 710,400 (optional)
        + * @description 여러 인수를 사용하여 2D 노이즈를 만들어보세요.
        + *
        + */
        +
        +let noiseVal;
        +let noiseScale = 0.02;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +}
        +
        +function draw() {
        +  background(0);
        +  // 이미지의 좌측 절반 그리기
        +  for (let y = 0; y < height - 30; y++) {
        +    for (let x = 0; x < width / 2; x++) {
        +      // noiceDetail, 픽셀 옥타브와 번짐 정도
        +      noiseDetail(2, 0.2);
        +      noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
        +      stroke(noiseVal * 255);
        +      point(x, y);
        +    }
        +  }
        +  // 이미지의 우측 절반 그리기
        +  for (let y = 0; y < height - 30; y++) {
        +    for (let x = width / 2; x < width; x++) {
        +      // noiceDetail, 픽셀 옥타브와 번짐 정도
        +      noiseDetail(5, 0.5);
        +      noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
        +      stroke(noiseVal * 255);
        +      point(x, y);
        +    }
        +  }
        +  //두 화면의 디테일 구성하기
        +  textSize(18);
        +  fill(255, 255, 255);
        +  text('2옥타브와 0.2 번짐 정도의 2D 노이즈', 10, 350);
        +  text('1옥타브와 0.7 번짐 정도의 2D 노이즈', 330, 350);
        +}
        diff --git a/src/data/examples/ko/08_Math/16_Noise3D.js b/src/data/examples/ko/08_Math/16_Noise3D.js
        new file mode 100644
        index 0000000000..907a90cfb1
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/16_Noise3D.js
        @@ -0,0 +1,48 @@
        +/*
        + * @name 3D 노이즈
        + * @frame 710,400 (optional)
        + * @description 3D 노이즈를 사용하여 간단한 동적 텍스쳐를 만듭니다.
        + */
        +
        +let noiseVal;
        +//x를 0.01씩 증가
        +let x_increment = 0.01;
        +//draw()함수 사이클 마다 z를 0.02씩 증가
        +let z_increment = 0.02;
        +
        +//Offset values
        +let z_off, y_off, x_off;
        +
        +function setup() {
        +  //캔버스 만들기
        +  createCanvas(640, 360);
        +  //프레임 속도 조정
        +  frameRate(20);
        +  //z_off의 초기값
        +  z_off = 0;
        +}
        +
        +function draw() {
        +  x_off = 0;
        +  y_off = 0;
        +  //배경을 검정색으로 설정
        +  background(0);
        +  //노이즈 디테일 조정
        +  noiseDetail(8, 0.65);
        +
        +  //매 x,y마다 노이즈값 계산
        +  for (let y = 0; y < height; y++) {
        +    x_off += x_increment;
        +    y_off = 0;
        +
        +    for (let x = 0; x < width; x++) {
        +      //각 픽셀을 계산하고 그리기
        +      noiseVal = noise(x_off, y_off, z_off);
        +      stroke(noiseVal * 255);
        +      y_off += x_increment;
        +      point(x, y);
        +    }
        +  }
        +
        +  z_off += z_increment;
        +}
        diff --git a/src/data/examples/ko/08_Math/17_Randomchords.js b/src/data/examples/ko/08_Math/17_Randomchords.js
        new file mode 100644
        index 0000000000..f4c971363d
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/17_Randomchords.js
        @@ -0,0 +1,35 @@
        +/*
        + * @name 무작위 선들
        + * @description 원형을 그리는 무작위 선들을 축적합니다.
        + * 불투명하게 처리된 선들이 축적될수록 마치 명암이 적용된 구처럼 보입니다.
        + * 애티쉬 바티아(Aatish Bhatia) 기여, <a href ="http://inconvergent.net/">앤더스 호프(Anders Hoff)</a>로부터 영감을 받음.
        + */
        +
        +function setup() {
        +  createCanvas(400, 400);
        +  background(255, 255, 255);
        +
        +  // 알파값을 활용하여 선의 불투명도 조정
        +  stroke(0, 0, 0, 15);
        +}
        +
        +function draw() {
        +  // 매 프레임마다 두 개의 선을 무작위로 그린다
        +  randomChord();
        +  randomChord();
        +}
        +
        +function randomChord() {
        +  // 원형 위 점 하나를 무작위로 찾는다
        +  let angle1 = random(0, 2 * PI);
        +  let xpos1 = 200 + 200 * cos(angle1);
        +  let ypos1 = 200 + 200 * sin(angle1);
        +
        +  // 원형 위 또다른 점 하나를 무작위로 찾는다
        +  let angle2 = random(0, 2 * PI);
        +  let xpos2 = 200 + 200 * cos(angle2);
        +  let ypos2 = 200 + 200 * sin(angle2);
        +
        +  // 둘 사이에 선을 긋는다
        +  line(xpos1, ypos1, xpos2, ypos2);
        +}
        diff --git a/src/data/examples/ko/08_Math/18_Map.js b/src/data/examples/ko/08_Math/18_Map.js
        new file mode 100644
        index 0000000000..43f81c9bdd
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/18_Map.js
        @@ -0,0 +1,21 @@
        +/*
        + * @name 매핑(map)
        + * @description map()함수 사용하면 그 어떠한 숫자든 여러분의 프로젝트에 더 많은 도움이 될
        + * 숫자로 매핑됩니다.
        + * 예를 들어, 마우스 위치값을 사용하여 도형의 크기와 색상을 조정할 수 있습니다.
        + * 이 예제에서는 마우스의 x 좌표(0과 360사이의 숫자)가 원형의 색상과 크기를 정의하는 새로운 숫자들로 처리됩니다.
        + */
        +function setup() {
        +  createCanvas(640, 400);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(0);
        +  // 0부터 640에 이르는 mouseX 값을 0부터 175의 범위로 조정
        +  let c = map(mouseX, 0, width, 0, 175);
        +  // 0부터 640에 이르는 mouseX 값을 40부터 300의 범위로 조정
        +  let d = map(mouseX, 0, width, 40, 300);
        +  fill(255, c, 0);
        +  ellipse(width/2, height/2, d, d);
        +}
        diff --git a/src/data/examples/ko/09_Simulate/00_Forces.js b/src/data/examples/ko/09_Simulate/00_Forces.js
        new file mode 100644
        index 0000000000..fae423f149
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/00_Forces.js
        @@ -0,0 +1,147 @@
        +/*
        + * @name 힘
        + * @description 바디 오브젝트에 작용하는 여러가지 물리학적 힘
        + * (<a href="http://natureofcode.com">natureofcode.com</a>)
        + */
        +// 바디에 적용되는 여러가지 물리학적 힘(Mover 클래스)
        +// 바디는 중력을 끊임없이 경험합니다.
        +// 바디는 물 속에서 유체 저항을 경험합니다.
        +
        +// 5개의 움직이는 형체
        +let movers = [];
        +
        +// Liquid
        +let liquid;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  reset();
        +  // 액체 오브젝트 생성
        +  liquid = new Liquid(0, height / 2, width, height / 2, 0.1);
        +}
        +
        +function draw() {
        +  background(127);
        +
        +  // 물 그리기
        +  liquid.display();
        +
        +  for (let i = 0; i < movers.length; i++) {
        +
        +    // Mover가 액체인가요?
        +    if (liquid.contains(movers[i])) {
        +      // 항력 계산하기
        +      let dragForce = liquid.calculateDrag(movers[i]);
        +      // Mover에 항력 적용하기
        +      movers[i].applyForce(dragForce);
        +    }
        +
        +    // 중력은 여기서 mass(질량)에 따라 결정됩니다!
        +    let gravity = createVector(0, 0.1 * movers[i].mass);
        +    // 중력 적용하기
        +    movers[i].applyForce(gravity);
        +
        +    // 업데이트하고 화면에 보이기(display)
        +    movers[i].update();
        +    movers[i].display();
        +    movers[i].checkEdges();
        +  }
        +
        +}
        +
        +
        +function mousePressed() {
        +  reset();
        +}
        +
        +// 모든 Mover 오브젝트들을 무작위로 재시작하기
        +function reset() {
        +  for (let i = 0; i < 9; i++) {
        +    movers[i] = new Mover(random(0.5, 3), 40 + i * 70, 0);
        +  }
        +}
        +
        +let Liquid = function(x, y, w, h, c) {
        +  this.x = x;
        +  this.y = y;
        +  this.w = w;
        +  this.h = h;
        +  this.c = c;
        +};
        +
        +// Mover가 액체인가요?
        +Liquid.prototype.contains = function(m) {
        +  let l = m.position;
        +  return l.x > this.x && l.x < this.x + this.w &&
        +         l.y > this.y && l.y < this.y + this.h;
        +};
        +
        +// 항력 계산하기
        +Liquid.prototype.calculateDrag = function(m) {
        +  // Magnitue(크기) = 계수 * speed(속도)의 제곱
        +  let speed = m.velocity.mag();
        +  let dragMagnitude = this.c * speed * speed;
        +
        +  // 방향은 속도와 반대쪽으로
        +  let dragForce = m.velocity.copy();
        +  dragForce.mult(-1);
        +
        +  // 힘의 크기에 따라 조정하기
        +  // dragForce.setMag(dragMagnitude);
        +  dragForce.normalize();
        +  dragForce.mult(dragMagnitude);
        +  return dragForce;
        +};
        +
        +Liquid.prototype.display = function() {
        +  noStroke();
        +  fill(50);
        +  rect(this.x, this.y, this.w, this.h);
        +};
        +
        +function Mover(m, x, y) {
        +  this.mass = m;
        +  this.position = createVector(x, y);
        +  this.velocity = createVector(0, 0);
        +  this.acceleration = createVector(0, 0);
        +}
        +
        +// 뉴턴(Newton)의 두번째 법칙: F = M * A
        +// 또는 A = F / M
        +Mover.prototype.applyForce = function(force) {
        +  let f = p5.Vector.div(force, this.mass);
        +  this.acceleration.add(f);
        +};
        +
        +Mover.prototype.update = function() {
        +  // 가속도에 따라 변하는 속도
        +  this.velocity.add(this.acceleration);
        +  // 속도에 따라 변하는 위치
        +  this.position.add(this.velocity);
        +  // 매 프레임마다 가속도 초기화
        +  this.acceleration.mult(0);
        +};
        +
        +Mover.prototype.display = function() {
        +  stroke(0);
        +  strokeWeight(2);
        +  fill(255,127);
        +  ellipse(this.position.x, this.position.y, this.mass * 16, this.mass * 16);
        +};
        +
        +// 바닥면에서 튀어오르기
        +Mover.prototype.checkEdges = function() {
        +  if (this.position.y > (height - this.mass * 8)) {
        +    // 바닥면에 닿을 때 약간의 완충 현상 발생
        +    this.velocity.y *= -0.9;
        +    this.position.y = (height - this.mass * 8);
        +  }
        +};
        +
        +
        +
        +
        +
        +
        +
        +
        diff --git a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        new file mode 100644
        index 0000000000..2ad9a2ae10
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        @@ -0,0 +1,69 @@
        +/*
        + * @name 파티클 시스템
        + * @description 이 예제는 기초적인 파티클 시스템을 다룹니다.
        + * (<a href="http://natureofcode.com">natureofcode.com</a>)
        + */
        +let system;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  system = new ParticleSystem(createVector(width / 2, 50));
        +}
        +
        +function draw() {
        +  background(51);
        +  system.addParticle();
        +  system.run();
        +}
        +
        +// A simple Particle class
        +let Particle = function(position) {
        +  this.acceleration = createVector(0, 0.05);
        +  this.velocity = createVector(random(-1, 1), random(-1, 0));
        +  this.position = position.copy();
        +  this.lifespan = 255;
        +};
        +
        +Particle.prototype.run = function() {
        +  this.update();
        +  this.display();
        +};
        +
        +// Method to update position
        +Particle.prototype.update = function(){
        +  this.velocity.add(this.acceleration);
        +  this.position.add(this.velocity);
        +  this.lifespan -= 2;
        +};
        +
        +// Method to display
        +Particle.prototype.display = function() {
        +  stroke(200, this.lifespan);
        +  strokeWeight(2);
        +  fill(127, this.lifespan);
        +  ellipse(this.position.x, this.position.y, 12, 12);
        +};
        +
        +// Is the particle still useful?
        +Particle.prototype.isDead = function(){
        +  return this.lifespan < 0;
        +};
        +
        +let ParticleSystem = function(position) {
        +  this.origin = position.copy();
        +  this.particles = [];
        +};
        +
        +ParticleSystem.prototype.addParticle = function() {
        +  this.particles.push(new Particle(this.origin));
        +};
        +
        +ParticleSystem.prototype.run = function() {
        +  for (let i = this.particles.length-1; i >= 0; i--) {
        +    let p = this.particles[i];
        +    p.run();
        +    if (p.isDead()) {
        +      this.particles.splice(i, 1);
        +    }
        +  }
        +};
        diff --git a/src/data/examples/ko/09_Simulate/02_Flocking.js b/src/data/examples/ko/09_Simulate/02_Flocking.js
        new file mode 100644
        index 0000000000..55fa0b262b
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/02_Flocking.js
        @@ -0,0 +1,229 @@
        +/*
        + * @name 플로킹
        + * @description 크레이그 레이놀즈(Craig Reynolds)의 "군집(Flocking)" 행위를 묘사합니다.
        + * 참고: http://www.red3d.com/cwr/
        + * 규칙: 응집, 분리, 정렬
        + * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
        + * 마우스를 드래그하여 시스템에 개체(boid)를 더해보세요.
        + */
        +
        +
        +let flock;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  createP("Drag the mouse to generate new boids.");
        +
        +  flock = new Flock();
        +  // 시스템에 초기 개체(boid) 더하기
        +  for (let i = 0; i < 100; i++) {
        +    let b = new Boid(width / 2,height / 2);
        +    flock.addBoid(b);
        +  }
        +}
        +
        +function draw() {
        +  background(51);
        +  flock.run();
        +}
        +
        +// 시스템에 새로운 개체 더하기
        +function mouseDragged() {
        +  flock.addBoid(new Boid(mouseX, mouseY));
        +}
        +
        +// The Nature of Code
        +// 다니엘 쉬프만(Daniel Shiffman)
        +// http://natureofcode.com
        +
        +// Flock 객체는
        +// 모든 개체(boid)의 배열을 관리하는, 간단한 작업을 수행합니다.
        +
        +function Flock() {
        +  // 모든 개체의 배열
        +  this.boids = []; // 배열 초기화
        +}
        +
        +Flock.prototype.run = function() {
        +  for (let i = 0; i < this.boids.length; i++) {
        +    this.boids[i].run(this.boids);  // 전체 보이즈 개체 목록을 각 개체에 보내기
        +  }
        +}
        +
        +Flock.prototype.addBoid = function(b) {
        +  this.boids.push(b);
        +}
        +
        +// The Nature of Code
        +// 다니엘 쉬프만(Daniel Shiffman)
        +// http://natureofcode.com
        +
        +// Boid(개체) 클래스
        +// 응집(cohesion), 분리(seperation), 정렬(alignment)을 위한 메소드 추가
        +
        +function Boid(x, y) {
        +  this.acceleration = createVector(0, 0);
        +  this.velocity = createVector(random(-1, 1), random(-1, 1));
        +  this.position = createVector(x, y);
        +  this.r = 3.0;
        +  this.maxspeed = 3;    // 최대 속도
        +  this.maxforce = 0.05; // 최대 조타력
        +}
        +
        +Boid.prototype.run = function(boids) {
        +  this.flock(boids);
        +  this.update();
        +  this.borders();
        +  this.render();
        +}
        +
        +Boid.prototype.applyForce = function(force) {
        +  // A = F / M 으로 계산하고 싶다면, 여기에 질량을 더하면 됩니다. 
        +  this.acceleration.add(force);
        +}
        +
        +// 3가지 규칙에 따라 매번 새로운 가속도를 만듭니다.
        +Boid.prototype.flock = function(boids) {
        +  let sep = this.separate(boids);   // 분리
        +  let ali = this.align(boids);      // 정렬
        +  let coh = this.cohesion(boids);   // 응집
        +  // 세 힘들을 임의로 가중하기
        +  sep.mult(1.5);
        +  ali.mult(1.0);
        +  coh.mult(1.0);
        +  // 가속도에 force 벡터 더하기
        +  this.applyForce(sep);
        +  this.applyForce(ali);
        +  this.applyForce(coh);
        +}
        +
        +// 위치 업데이트를 위한 메소드
        +Boid.prototype.update = function() {
        +  // 속도 업데이트
        +  this.velocity.add(this.acceleration);
        +  // 속도 제한
        +  this.velocity.limit(this.maxspeed);
        +  this.position.add(this.velocity);
        +  // 매 사이클마다 가속도를 0으로 리셋
        +  this.acceleration.mult(0);
        +}
        +
        +// 특정 목표점을 향한 조타력을 계산하고 적용하는 메소드
        +// STEER(조타력) = DESIRED(목표점) - VELOCITY(속도)
        +Boid.prototype.seek = function(target) {
        +  let desired = p5.Vector.sub(target,this.position);  // 현위치에서 목표점을 가리키는 벡터
        +  // desired를 표준화하고 최대 속도로 조정
        +  desired.normalize();
        +  desired.mult(this.maxspeed);
        +  // Steering = Desired minus Velocity
        +  let steer = p5.Vector.sub(desired,this.velocity);
        +  steer.limit(this.maxforce);  // 최대 조타력으로 제한
        +  return steer;
        +}
        +
        +Boid.prototype.render = function() {
        +  // 속도의 방향에 따라 회전하는 삼각형 그리기
        +  let theta = this.velocity.heading() + radians(90);
        +  fill(127);
        +  stroke(200);
        +  push();
        +  translate(this.position.x, this.position.y);
        +  rotate(theta);
        +  beginShape();
        +  vertex(0, -this.r * 2);
        +  vertex(-this.r, this.r * 2);
        +  vertex(this.r, this.r * 2);
        +  endShape(CLOSE);
        +  pop();
        +}
        +
        +// Wraparound
        +Boid.prototype.borders = function() {
        +  if (this.position.x < -this.r)  this.position.x = width + this.r;
        +  if (this.position.y < -this.r)  this.position.y = height + this.r;
        +  if (this.position.x > width + this.r) this.position.x = -this.r;
        +  if (this.position.y > height + this.r) this.position.y = -this.r;
        +}
        +
        +// 분리 Seperation
        +// 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
        +Boid.prototype.separate = function(boids) {
        +  let desiredseparation = 25.0;
        +  let steer = createVector(0, 0);
        +  let count = 0;
        +  // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
        +  for (let i = 0; i < boids.length; i++) {
        +    let d = p5.Vector.dist(this.position,boids[i].position);
        +    // 만약 그 거리가 0보다 크고 임의의 값보다 작다면(0은 개체의 현위치)
        +    if ((d > 0) && (d < desiredseparation)) {
        +      // 인근의 개체로부터 떨어진 지점을 향하는 벡터 계산
        +      let diff = p5.Vector.sub(this.position, boids[i].position);
        +      diff.normalize();
        +      diff.div(d);        // 거리에 따른 가중
        +      steer.add(diff);
        +      count++;            // 개체수 카운트
        +    }
        +  }
        +  // 평균 -- 얼마로 나눌 것인가
        +  if (count > 0) {
        +    steer.div(count);
        +  }
        +
        +  // 벡터가 0보다 크다면,
        +  if (steer.mag() > 0) {
        +    // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
        +    steer.normalize();
        +    steer.mult(this.maxspeed);
        +    steer.sub(this.velocity);
        +    steer.limit(this.maxforce);
        +  }
        +  return steer;
        +}
        +
        +// 배열 Alignment
        +// 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
        +Boid.prototype.align = function(boids) {
        +  let neighbordist = 50;
        +  let sum = createVector(0,0);
        +  let count = 0;
        +  for (let i = 0; i < boids.length; i++) {
        +    let d = p5.Vector.dist(this.position,boids[i].position);
        +    if ((d > 0) && (d < neighbordist)) {
        +      sum.add(boids[i].velocity);
        +      count++;
        +    }
        +  }
        +  if (count > 0) {
        +    sum.div(count);
        +    sum.normalize();
        +    sum.mult(this.maxspeed);
        +    let steer = p5.Vector.sub(sum, this.velocity);
        +    steer.limit(this.maxforce);
        +    return steer;
        +  } else {
        +    return createVector(0, 0);
        +  }
        +}
        +
        +// 응집 Cohesion
        +// 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
        +Boid.prototype.cohesion = function(boids) {
        +  let neighbordist = 50;
        +  let sum = createVector(0, 0);   // 빈 벡터값으로 시작하여 모든 위치들을 축적
        +  let count = 0;
        +  for (let i = 0; i < boids.length; i++) {
        +    let d = p5.Vector.dist(this.position,boids[i].position);
        +    if ((d > 0) && (d < neighbordist)) {
        +      sum.add(boids[i].position); // 위치 추가
        +      count++;
        +    }
        +  }
        +  if (count > 0) {
        +    sum.div(count);
        +    return this.seek(sum);  // 해당 위치를 향해 조타
        +  } else {
        +    return createVector(0, 0);
        +  }
        +}
        +
        +
        diff --git a/src/data/examples/ko/09_Simulate/03_WolframCA.js b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        new file mode 100644
        index 0000000000..6472f7d97f
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        @@ -0,0 +1,73 @@
        +/*
        + * @name 울프램 셀룰러 오토마타
        + * @description 1차원 셀룰러 오토마타(cellular automata) 간단하게 구현하기.
        + * (<a href="http://natureofcode.com">natureofcode.com</a>)
        + */
        +
        +let w = 10;
        +// 0과 1들의 배열
        +let cells;
        +
        + // "1"의 상태를 갖는 중간 셀과 함께 시작합니다.
        +let generation = 0;
        +
        +// {0,1,1,0,1,1,0,1}과 같은 규칙 묶음(ruleset)을 저장하는 배열
        +let ruleset = [0, 1, 0, 1, 1, 0, 1, 0];
        +
        +function setup() {
        +  createCanvas(640, 400);
        +  cells = Array(floor(width / w));
        +  for (let i = 0; i < cells.length; i++) {
        +    cells[i] = 0;
        +  }
        +  cells[cells.length/2] = 1;
        +
        +}
        +
        +function draw() {
        +  for (let i = 0; i < cells.length; i++) {
        +    if (cells[i] === 1) {
        +      fill(200);
        +    } else {
        +      fill(51);
        +      noStroke();
        +      rect(i * w, generation * w, w, w);
        +    }
        +  }
        +  if (generation < height/w) {
        +    generate();
        +  }
        +}
        +
        +// 새로운 세대(generation) 생성 과정
        +function generate() {
        +  // 먼저, 새로운 값을 위한 빈 배열을 만듭니다.
        +  let nextgen = Array(cells.length);
        +  // 매 셀마다 현재 상태를 확인하여 새로운 상태를 결정하고 이 둘을 이웃하게 만듭니다.
        +  // 모서리에 위치하여 한 개의 이웃만을 가진 상태는 무시합니다.
        +  for (let i = 1; i < cells.length-1; i++) {
        +    let left   = cells[i-1];   // 좌측 이웃 상태
        +    let me     = cells[i];     // 현재 상태
        +    let right  = cells[i+1];   // 우측 이웃 상태
        +    nextgen[i] = rules(left, me, right); // 다음 세대 상태를 규칙 묶음(ruleset)에 의거하여 계산
        +  }
        +  // 현재 상태가 새로운 세대가 됩니다.
        +  cells = nextgen;
        +  generation++;
        +}
        +
        +
        +// 울프램 규칙 구현하기
        +// 더 향상되거나 간결해질 수도 있지만, 여기서 각 사례별로 어떤 일이 일어나는지 명확히 볼 수 있습니다.
        +function rules(a, b, c) {
        +  if (a == 1 && b == 1 && c == 1) return ruleset[0];
        +  if (a == 1 && b == 1 && c == 0) return ruleset[1];
        +  if (a == 1 && b == 0 && c == 1) return ruleset[2];
        +  if (a == 1 && b == 0 && c == 0) return ruleset[3];
        +  if (a == 0 && b == 1 && c == 1) return ruleset[4];
        +  if (a == 0 && b == 1 && c == 0) return ruleset[5];
        +  if (a == 0 && b == 0 && c == 1) return ruleset[6];
        +  if (a == 0 && b == 0 && c == 0) return ruleset[7];
        +  return 0;
        +}
        +
        diff --git a/src/data/examples/ko/09_Simulate/04_GameOfLife.js b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        new file mode 100644
        index 0000000000..d203b1a791
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        @@ -0,0 +1,95 @@
        +/*
        + * @name 라이프 게임
        + * @description 존 콘웨이(John Conway)의 라이프 게임 셀룰러 오토마타
        + * (Game of Life Cellular Automata)의 기초적 구현
        + * (<a href="http://natureofcode.com">natureofcode.com</a>)
        + */
        +
        +let w;
        +let columns;
        +let rows;
        +let board;
        +let next;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  w = 20;
        +  // 행렬 계산하기
        +  columns = floor(width / w);
        +  rows = floor(height / w);
        +  // JS를 사용하여 요상한 2D 배열 만들기
        +  board = new Array(columns);
        +  for (let i = 0; i < columns; i++) {
        +    board[i] = new Array(rows);
        +  }
        +  // 복수의 2D 배열을 만들고 바꾸기
        +  next = new Array(columns);
        +  for (i = 0; i < columns; i++) {
        +    next[i] = new Array(rows);
        +  }
        +  init();
        +}
        +
        +function draw() {
        +  background(255);
        +  generate();
        +  for ( let i = 0; i < columns;i++) {
        +    for ( let j = 0; j < rows;j++) {
        +      if ((board[i][j] == 1)) fill(0);
        +      else fill(255);
        +      stroke(0);
        +      rect(i * w, j * w, w-1, w-1);
        +    }
        +  }
        +
        +}
        +
        +// 마우스 버튼 클릭시 보드 리셋하기
        +function mousePressed() {
        +  init();
        +}
        +
        +// 무작위로 보드 채우기
        +function init() {
        +  for (let i = 0; i < columns; i++) {
        +    for (let j = 0; j < rows; j++) {
        +      // 0으로 모서리 테두리 그리기
        +      if (i == 0 || j == 0 || i == columns-1 || j == rows-1) board[i][j] = 0;
        +      // 나머지는 무작위로 채우기
        +      else board[i][j] = floor(random(2));
        +      next[i][j] = 0;
        +    }
        +  }
        +}
        +
        +// 새로운 세대 생성하는 과정
        +function generate() {
        +
        +  // 2D 배열 상 모든 셀들을 걸쳐 반복하며 각 셀별 이웃 확인하기
        +  for (let x = 1; x < columns - 1; x++) {
        +    for (let y = 1; y < rows - 1; y++) {
        +      // 3x3의 주변 그리드에 모든 상태들을 더하여 넣기
        +      let neighbors = 0;
        +      for (let i = -1; i <= 1; i++) {
        +        for (let j = -1; j <= 1; j++) {
        +          neighbors += board[x+i][y+j];
        +        }
        +      }
        +
        +      // 위의 반복을 통해 모든 셀들의 현재 상태를 계산해 넣었으므로,
        +      // 이 계산을 빼주는 요령
        +      neighbors -= board[x][y];
        +      // 라이프 규칙
        +      if      ((board[x][y] == 1) && (neighbors <  2)) next[x][y] = 0;           // 외로움
        +      else if ((board[x][y] == 1) && (neighbors >  3)) next[x][y] = 0;           // 인구과잉
        +      else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1;           // 재생산
        +      else                                             next[x][y] = board[x][y]; // 균형
        +    }
        +  }
        +
        +  // 바꾸기!
        +  let temp = board;
        +  board = next;
        +  next = temp;
        +}
        +
        diff --git a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        new file mode 100644
        index 0000000000..1fc5960de4
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        @@ -0,0 +1,137 @@
        +/*
        + * @name 멀티플 파티클 시스템
        + * @description 마우스를 클릭한 위치에서 파티클이 폭발적으로 생성되도록 만들어보세요. <br> 매 폭발은 Particle 클래스의 하위 클래스인 Particles와 CrazyParticles
        + * 의 한 인스턴스에 해당합니다. <br> 클래스 상속과 다형 사용에 대한 방법을 확인해보세요. <br>
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
        + */
        +let systems;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  systems = [];
        +}
        +
        +function draw() {
        +  background(51);
        +  background(0);
        +  for (i = 0; i < systems.length; i++) {
        +    systems[i].run();
        +    systems[i].addParticle();
        +  }
        +  if (systems.length == 0) {
        +    fill(255);
        +    textAlign(CENTER);
        +    textSize(32);
        +    text("click mouse to add particle systems", width / 2, height / 2);
        +  }
        +}
        +
        +function mousePressed() {
        +  this.p = new ParticleSystem(createVector(mouseX, mouseY));
        +  systems.push(p);
        +}
        +
        +// 간단한 Particle 클래스
        +let Particle = function(position) {
        +  this.acceleration = createVector(0, 0.05);
        +  this.velocity = createVector(random(-1, 1), random(-1, 0));
        +  this.position = position.copy();
        +  this.lifespan = 255.0;
        +};
        +
        +Particle.prototype.run = function() {
        +  this.update();
        +  this.display();
        +};
        +
        +// 위치 업데이트를 위한 메소드
        +Particle.prototype.update = function(){
        +  this.velocity.add(this.acceleration);
        +  this.position.add(this.velocity);
        +  this.lifespan -= 2;
        +};
        +
        +// 화면에 보이게 하기 위한 메소드
        +Particle.prototype.display = function () {
        +  stroke(200, this.lifespan);
        +  strokeWeight(2);
        +  fill(127, this.lifespan);
        +  ellipse(this.position.x, this.position.y, 12, 12);
        +};
        +
        +// 파티클이 여전히 유용한가요?
        +Particle.prototype.isDead = function () {
        +  if (this.lifespan < 0) {
        +    return true;
        +  } else {
        +    return false;
        +  }
        +};
        +
        +let ParticleSystem = function (position) {
        +  this.origin = position.copy();
        +  this.particles = [];
        +};
        +
        +ParticleSystem.prototype.addParticle = function () {
        +  // Particle 또는 CrazyParticle을 시스템에 더하기
        +  if (int(random(0, 2)) == 0) {
        +    p = new Particle(this.origin);
        +  }
        +  else {
        +    p = new CrazyParticle(this.origin);
        +  }
        +  this.particles.push(p);
        +};
        +
        +ParticleSystem.prototype.run = function () {
        +  for (let i = this.particles.length - 1; i >= 0; i--) {
        +    let p = this.particles[i];
        +    p.run();
        +    if (p.isDead()) {
        +      this.particles.splice(i, 1);
        +    }
        +  }
        +};
        +
        +// Particle의 하위 클래스
        +
        +function CrazyParticle(origin) {
        +  // 부모 생성자(constructor) 만들기
        +  // 이 때, Function#call을 사용하여 "this"가 올바르게 설정되었는지 확인합니다.
        +  Particle.call(this, origin);
        +
        +  // 더해진 속성들 초기화하기
        +  this.theta = 0.0;
        +};
        +
        +// Particle.prototype을 상속하는 Crazy.prototype 오브젝트 만들기
        +// 주의: 여기서 자주 발생하는 실수는, Crazy.prototype을 만들기 위해 새로운 "particle()"함수를 쓰는 것입니다.
        +// 이는 여러가지 이유로 적당하지 않은데, 특히 Particle에 "origin" 인수를 제공할 게 없다는 점에서 그렇습니다.
        +// Particle은 위와 같이 Crazy에서 호출하면 됩니다.
        +CrazyParticle.prototype = Object.create(Particle.prototype); // 아래의 주석을 보세요.
        +
        +// "constructor(생성자)" 속성이 CrazyParticle을 참조하게 설정하기
        +CrazyParticle.prototype.constructor = CrazyParticle;
        +
        +// 여기서 우리는 run()메소드를 쓰지 않습니다. Particle로부터 상속되었기 때문입니다.
        +
        +// 이 update() 메소드는 부모 클래스의 update() 메소드를 오버라이드합니다.
        +CrazyParticle.prototype.update=function() {
        +  Particle.prototype.update.call(this);
        +  // 가로 속도에 따라 회전값 증가하기
        +  this.theta += (this.velocity.x * this.velocity.mag()) / 10.0;
        +}
        +
        +// 이 display() 메소드는 부모 클래스의 display() 메소드를 오버라이드합니다.
        +CrazyParticle.prototype.display=function() {
        +  // 타원형을 일반적인 파티클처럼 렌더링하기
        +  Particle.prototype.display.call(this);
        +  // 그 다음, 회전하는 선들 더하기
        +  push();
        +  translate(this.position.x, this.position.y);
        +  rotate(this.theta);
        +  stroke(255, this.lifespan);
        +  line(0, 0, 25, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/09_Simulate/06_Spirograph.js b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        new file mode 100644
        index 0000000000..72ebad02d0
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        @@ -0,0 +1,73 @@
        +
        +/*
        + * @name 스피로그래프
        + * @description 일명 싸인이라 불리는 서로 맞물린 원형들을 이용하여,
        + * 스피로그래프와 같은 효과를 만드는 간단한 변형 예제를 소개합니다.
        + * 스페이스바를 눌러 스피로그래프 화면이나, 이것의 기하 궤도 추적 화면으로 전환해보세요.<br>
        + * 이 예제는 <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>가 제작하였습니다.<br>
        + * <a href='http://en.wikipedia.org/wiki/Spirograph'>http://en.wikipedia.org/wiki/Spirograph</a>
        + */
        +let NUMSINES = 20; // 얼마나 싸인을 많은 동시에 그릴 건가요?
        +let sines = new Array(NUMSINES); // 현재 각도들을 모두 저장하는 배열
        +let rad; // 중심 싸인의 초기 반지름값
        +let i; // 카운터 변수
        +
        +// 아래의 값들을 갖고 놀며 어떤 일이 일어나는 건지 감잡아 보세요!
        +let fund = 0.005; // 중심 싸인의 속도
        +let ratio = 1; // 더해진 각 싸인은 속도에 몇을 곱하나요?
        +let alpha = 50; // 궤도 추적 시스템의 투명도
        +
        +let trace = false; // 추적을 하나요?
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  rad = height / 4; // 중심 원의 반지름 계산
        +  background(204); // 화면 비우기
        +
        +  for (let i = 0; i<sines.length; i++) {
        +    sines[i] = PI; // 모든 원들이 북쪽을 향해 시작하도록 설정
        +  }
        +}
        +
        +function draw() {
        +  if (!trace) {
        +    background(204); // 기하 형상이 보일 경우 스크린 비우기
        +    stroke(0, 255); // 검정색 펜
        +    noFill(); // 면채우기 없음
        +  }
        +
        +  // 주요 행위
        +  push(); // 변형 매트릭스 시작하기
        +  translate(width / 2, height / 2); // 화면 중앙으로 이동하기
        +
        +  for (let i = 0; i < sines.length; i++) {
        +    let erad = 0; // 원형 내 작은 "점"의 반지름. 추적 화면에선 이것이 펜으로 쓰입니다.
        +    // 추적을 위한 설정
        +    if (trace) {
        +      stroke(0, 0, 255 * (float(i) / sines.length), alpha); // 파랑
        +      fill(0, 0, 255, alpha / 2); // 음... 또, 파랑!
        +      erad = 5.0 * (1.0 - float(i) / sines.length); // 펜의 너비가 어떤 싸인과 관계할 지
        +    }
        +    let radius = rad / (i + 1); // 원 그 자체의 반지름
        +    rotate(sines[i]); // 원 회전시키기
        +    if (!trace) ellipse(0, 0, radius * 2, radius * 2); // 우리가 시뮬레이션 중이라면, 싸인을 그리세요.
        +    push(); // 레벨 1 업
        +    translate(0, radius); // 싸인 모서리로 이동하기
        +    if (!trace) ellipse(0, 0, 5, 5); // 작은 원 그리기
        +    if (trace) ellipse(0, 0, erad, erad); // 만약 추적 중이라면 erad로 그리기
        +    pop(); // 레벨 1 다운
        +    translate(0, radius); // 다음 싸인을 위한 위치로 이동하기
        +    sines[i] = (sines[i] + (fund + (fund * i * ratio))) % TWO_PI; // fund에 따라 각도 업데이트하기
        +  }
        +
        +  pop(); // 마지막 변형에 다다르면 레벨 1 다운
        +
        +}
        +
        +function keyReleased() {
        +  if (key==' ') {
        +    trace = !trace;
        +    background(255);
        +  }
        +}
        diff --git a/src/data/examples/ko/09_Simulate/07_LSystems.js b/src/data/examples/ko/09_Simulate/07_LSystems.js
        new file mode 100644
        index 0000000000..6fcd73cc69
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/07_LSystems.js
        @@ -0,0 +1,105 @@
        +/*
        + * @name L-시스템
        + * @description 이 스케치는 린덴마이어(Lindenmayer) 또는 (L-) 시스템을 기반으로 한 자동 드로잉을 보여줍니다.
        + * L-시스템은 자연적, 기하학적, 또는 재밌는 "프랙탈형" 패턴을 만드는 제너레이티브 그래픽에 쓰입니다.<br>
        + * 이 예제는 <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>가 제작하였습니다.<br>
        + * <a href='https://en.wikipedia.org/wiki/L-system'>https://en.wikipedia.org/wiki/L-system</a>
        + */
        +// 거북이:
        +let x, y; // 거북이의 현재 위치
        +let currentangle = 0; // 거북이가 가리키는 방향w
        +let step = 20; // 매 'F'마다 거북이가 움직이는 크기
        +let angle = 90; // '-' 또는 '+'에 따라 거북이가 회전하는 크기
        +
        +// 린덴마이어 시스템(L-SYSTEMS)
        +let thestring = 'A'; // 공리, 또는 문자열의 시작
        +let numloops = 5; // 전처리할 반복문 개수
        +let therules = []; // 규칙 배열
        +therules[0] = ['A', '-BF+AFA+FB-']; // 첫 번째 규칙
        +therules[1] = ['B', '+AF-BFB-FA+']; // 두 번째 규칙
        +
        +let whereinstring = 0; // L-시스템 상 현재 위치?
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  background(255);
        +  stroke(0, 0, 0, 255);
        +
        +  // 좌측 하단 코너에서 x와 y 위치 시작
        +  x = 0;
        +  y = height-1;
        +
        +  // L-시스템 처리하기
        +  for (let i = 0; i < numloops; i++) {
        +    thestring = lindenmayer(thestring);
        +  }
        +}
        +
        +function draw() {
        +
        +  // 현재의 문자를 문자열로 그리기:
        +  drawIt(thestring[whereinstring]);
        +
        +  // 문자열을 읽는 지점 증가하기
        +  // 마지막에 wrap around
        +  whereinstring++;
        +  if (whereinstring > thestring.length-1) whereinstring = 0;
        +
        +}
        +
        +// L-시스템 해석하기
        +function lindenmayer(s) {
        +  let outputstring = ''; // 빈 출력 문자열 시작하기
        +
        +  // 'therules'를 반복하여 일치하는 기호 찾기:
        +  for (let i = 0; i < s.length; i++) {
        +    let ismatch = 0; // 기본값으로, 일치하는 기호 없음
        +    for (let j = 0; j < therules.length; j++) {
        +      if (s[i] == therules[j][0])  {
        +        outputstring += therules[j][1]; // 대체내용 작성
        +        ismatch = 1; // 일치하는 기호가 있으므로 복사하지 않음
        +        break; // for() 반복문 나오기
        +      }
        +    }
        +    // 일치하는 기호가 없으면 복사
        +    if (ismatch == 0) outputstring+= s[i];
        +  }
        +
        +  return outputstring; // 수정된 문자열 전송
        +}
        +
        +// 아래는 거북이를 그리는 사용자 정의 함수입니다.
        +function drawIt(k) {
        +
        +  if (k=='F') { // 앞으로 그리기
        +    // step과 currentangle을 기준으로, 극좌표에서 직교 좌표로 변환하기:
        +    let x1 = x + step*cos(radians(currentangle));
        +    let y1 = y + step*sin(radians(currentangle));
        +    line(x, y, x1, y1); // 이전의 것과 새로운 것을 연결
        +
        +    // 거북이의 위치 업데이트:
        +    x = x1;
        +    y = y1;
        +  } else if (k == '+') {
        +    currentangle += angle; // 왼쪽으로 돌기
        +  } else if (k == '-') {
        +    currentangle -= angle; // 오른쪽으로 돌기
        +  }
        +
        +  // 무작위의 색상값을 주세요:
        +  let r = random(128, 255);
        +  let g = random(0, 192);
        +  let b = random(0, 50);
        +  let a = random(50, 100);
        +
        +  // 반지름에 대한 가우스 분포(D&D) 선택하기:
        +  let radius = 0;
        +  radius += random(0, 15);
        +  radius += random(0, 15);
        +  radius += random(0, 15);
        +  radius = radius / 3;
        +
        +  // 그리기:
        +  fill(r, g, b, a);
        +  ellipse(x, y, radius, radius);
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/08_Spring.js b/src/data/examples/ko/09_Simulate/08_Spring.js
        new file mode 100644
        index 0000000000..3fe9db5820
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/08_Spring.js
        @@ -0,0 +1,92 @@
        +/*
        + * @name 스프링
        + * @frame 710, 400
        + * @description 스프링 효과를 보려면 수평 막대를 클릭하고 드래그한 뒤 놓아보세요.
        + */
        +// 상단의 막대를 위한 Spring drawing constants for top bar
        +let springHeight = 32,
        +    left,
        +    right,
        +    maxHeight = 200,
        +    minHeight = 100,
        +    over = false,
        +    move = false;
        +
        +// 스프링 시뮬레이션 상수들
        +let M = 0.8,  // Mass(질량)
        +    K = 0.2,  // 스프링 상수
        +    D = 0.92, // Damping(감쇠)
        +    R = 150;  // Rest Position(놓인 위치)
        +
        +// 스프링 시뮬레이션 변수들
        +let ps = R,   // 위치
        +    vs = 0.0, // 속도
        +    as = 0,   // 가속도
        +    f = 0;    // 힘
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  rectMode(CORNERS);
        +  noStroke();
        +  left = width / 2 - 100;
        +  right = width / 2 + 100;
        +}
        +
        +function draw() {
        +  background(102);
        +  updateSpring();
        +  drawSpring();
        +}
        +
        +function drawSpring() {
        +  // Draw base
        +  fill(0.2);
        +  let baseWidth = 0.5 * ps + -8;
        +  rect(width / 2 - baseWidth, ps + springHeight, width / 2 + baseWidth, height);
        +
        +  // 상단 막대기의 색상 설정하고 그리기
        +  if (over || move) {
        +    fill(255);
        +  } else {
        +    fill(204);
        +  }
        +
        +  rect(left, ps, right, ps + springHeight);
        +}
        +
        +function updateSpring() {
        +  // 스프링 위치 업데이트
        +  if ( !move ) {
        +    f = -K * ( ps - R ); // f=-ky
        +    as = f / M;          // 가속도 설정, f=ma == a=f/m
        +    vs = D * (vs + as);  // 속도 설정
        +    ps = ps + vs;        // 업데이트된 위치
        +  }
        +
        +  if (abs(vs) < 0.1) {
        +    vs = 0.0;
        +  }
        +
        +  // 마우스가 상단 막대기 위에 있는지 여부 테스트
        +  if (mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + springHeight) {
        +    over = true;
        +  } else {
        +    over = false;
        +  }
        +
        +  // 상단 막대기의 위치 설정 및 제한
        +  if (move) {
        +    ps = mouseY - springHeight / 2;
        +    ps = constrain(ps, minHeight, maxHeight);
        +  }
        +}
        +
        +function mousePressed() {
        +  if (over) {
        +    move = true;
        +  }
        +}
        +
        +function mouseReleased() {
        +  move = false;
        +}
        diff --git a/src/data/examples/ko/09_Simulate/09_Springs.js b/src/data/examples/ko/09_Simulate/09_Springs.js
        new file mode 100644
        index 0000000000..62c3178141
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/09_Springs.js
        @@ -0,0 +1,147 @@
        +/*
        + * @name 스프링들
        + * @frame 710,400
        + * @description 마우스로 원형 하나를 클릭해 재배치해보세요.
        + * 마우스 클릭을 놓으면 원위치로 되돌아갑니다.
        + * 각 원형은 조금씩 다른 행동을 보입니다.
        + * (ported from https://processing.org/examples/springs.html)
        + */
        +let num = 3;
        +let springs = [];
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noStroke();
        +
        +  springs[0] = new Spring(240, 260, 40, 0.98, 8.0, 0.1, springs, 0);
        +  springs[1] = new Spring(320, 210, 120, 0.95, 9.0, 0.1, springs, 1);
        +  springs[2] = new Spring(180, 170, 200, 0.90, 9.9, 0.1, springs, 2);
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  for (let i = 0; i < num; i++) {
        +	springs[i].update();
        +	springs[i].display();
        +  }
        +}
        +
        +function mousePressed() {
        +  for (let i = 0; i < num; i++) {
        +    springs[i].pressed();
        +  }
        +}
        +
        +function mouseReleased() {
        +  for (let i = 0; i < num; i++) {
        +	springs[i].released();
        +  }
        +}
        +
        +// Spring 클래스
        +function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
        +  // 화면상 위치값들
        +  // this.xpos = _x;
        +  // this.ypos = _y;
        +
        +  this.x_pos = _x;
        +  this.y_pos= _y;
        +
        +  this.size = 20;
        +  this.size = _s;
        +
        +  this.over = false;
        +  this.move = false;
        +
        +	// 스프링 시뮬레이션 상수들
        +  this.mass = _m;       // Mass(질량)
        +  this.k = 0.2;    // Spring constant
        +  this.k = _k_in;
        +  this.damp = _d;       // Damping(감쇠)
        +  this.rest_posx = _x;  // 놓인 위치 X
        +  this.rest_posy = _y;  // 놓인 위치 Y
        +
        +  // 스프링 시뮬레이션 변수들
        +  //float pos = 20.0; // 위치
        +  this.velx = 0.0;   // X 속도
        +  this.vely = 0.0;   // Y 속도
        +  this.accel = 0;    // 가속도
        +  this.force = 0;    // 힘
        +
        +  this.friends = _others;
        +  this.id = _id;
        +
        +  this.update = function() {
        +
        +	if (this.move) {
        +	  this.rest_posy = mouseY;
        +	  this.rest_posx = mouseX;
        +	}
        +
        +	this.force = -this.k * (this.y_pos - this.rest_posy);  // f=-ky
        +	this.accel = this.force / this.mass;                 // 가속도 설정하기, f=ma == a=f/m
        +	this.vely = this.damp * (this.vely + this.accel);         // 속도 설정하기
        +	this.y_pos = this.y_pos + this.vely;           // 업데이트된 위치
        +
        +
        +	this.force = -this.k * (this.x_pos - this.rest_posx);  // f=-ky
        +	this.accel = this.force / this.mass;                 // 가속도 설정하기, f=ma == a=f/m
        +	this.velx = this.damp * (this.velx + this.accel);         // 속도 설정하기
        +	this.x_pos = this.x_pos + this.velx;           // 업데이트된 위치
        +
        +
        +	if ((this.overEvent() || this.move) && !(this.otherOver()) ) {
        +	  this.over = true;
        +	} else {
        +	    this.over = false;
        +	  }
        +  }
        +
        +  // 마우스가 이 스프링 위에 있는지의 여부르 테스트
        +  this.overEvent = function() {
        +	let disX = this.x_pos - mouseX;
        +	let disY = this.y_pos - mouseY;
        +	let dis = createVector(disX, disY);
        +	if (dis.mag() < this.size / 2 ) {
        +	  return true;
        +	} else {
        +		return false;
        +	  }
        +  }
        +
        +  // 다른 스프링이 움직이지 않도록 처리
        +  this.otherOver = function() {
        +	for (let i = 0; i < num; i++) {
        +	  if (i != this.id) {
        +		if (this.friends[i].over == true) {
        +		  return true;
        +		}
        +	  }
        +	}
        +	return false;
        +  }
        +
        +  this.display = function() {
        +	if (this.over) {
        +	  fill(153);
        +	} else {
        +	    fill(255);
        +	  }
        +	ellipse(this.x_pos, this.y_pos, this.size, this.size);
        +  }
        +
        +  this.pressed = function() {
        +	if (this.over) {
        +	  this.move = true;
        +	} else {
        +	  this.move = false;
        +	}
        +  }
        +
        +  this.released = function() {
        +	this.move = false;
        +	this.rest_posx = this.y_pos;
        +	this.rest_posy = this.y_pos;
        +  }
        +};
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/10_SoftBody.js b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        new file mode 100644
        index 0000000000..762b4b05aa
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        @@ -0,0 +1,110 @@
        +/*
        + * @name 소프트 바디
        + * @description 이라 그린버그(Ira Greenberg) 원본 제작.
        + * <br><br>curveVertex() 와 curveTightness()를 사용한 소프트 바디 역학 시뮬레이션.
        + */
        +// 중심점
        +let centerX = 0.0, centerY = 0.0;
        +
        +let radius = 45, rotAngle = -90;
        +let accelX = 0.0, accelY = 0.0;
        +let deltaX = 0.0, deltaY = 0.0;
        +let springing = 0.0009, damping = 0.98;
        +
        +// 코너 노드들
        +let nodes = 5;
        +
        +// 빈 배열
        +let nodeStartX = [];
        +let nodeStartY = [];
        +let nodeX = [];
        +let nodeY = [];
        +let angle = [];
        +let frequency = [];
        +
        +// 소프트 바디 역학
        +let organicConstant = 1.0;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 화면상의 중심 도형
        +  centerX = width / 2;
        +  centerY = height / 2;
        +
        +  // 배열을 0으로 초기화
        +  for (let i = 0; i < nodes; i++){
        +    nodeStartX[i] = 0;
        +    nodeStartY[i] = 0;
        +    nodeY[i] = 0;
        +    nodeY[i] = 0;
        +    angle[i] = 0;
        +  }
        +
        +  // 코너 노드의 빈도수 초기화
        +  for (let i = 0; i < nodes; i++){
        +    frequency[i] = random(5, 12);
        +  }
        +
        +  noStroke();
        +  frameRate(30);
        +}
        +
        +function draw() {
        +  // 배경 사라지게하기
        +  fill(0, 100);
        +  rect(0, 0, width, height);
        +  drawShape();
        +  moveShape();
        +}
        +
        +function drawShape() {
        +  // 노드 시작 위치 계산
        +  for (let i = 0; i < nodes; i++){
        +    nodeStartX[i] = centerX + cos(radians(rotAngle)) * radius;
        +    nodeStartY[i] = centerY + sin(radians(rotAngle)) * radius;
        +    rotAngle += 360.0 / nodes;
        +  }
        +
        +  // 다각형 그리기
        +  curveTightness(organicConstant);
        +  fill(255);
        +  beginShape();
        +  for (let i = 0; i < nodes; i++){
        +    curveVertex(nodeX[i], nodeY[i]);
        +  }
        +  for (let i = 0; i < nodes-1; i++){
        +    curveVertex(nodeX[i], nodeY[i]);
        +  }
        +  endShape(CLOSE);
        +}
        +
        +function moveShape() {
        +  // 중심점 옮기기
        +  deltaX = mouseX - centerX;
        +  deltaY = mouseY - centerY;
        +
        +  // 스프링같은 효과 만들기
        +  deltaX *= springing;
        +  deltaY *= springing;
        +  accelX += deltaX;
        +  accelY += deltaY;
        +
        +  // 프레데터(predator)의 중심 옮기기
        +  centerX += accelX;
        +  centerY += accelY;
        +
        +  // 스프링같은 효과 감쇠하기
        +  accelX *= damping;
        +  accelY *= damping;
        +
        +  // 커브의 탄성 바꾸기
        +  organicConstant = 1 - ((abs(accelX) + abs(accelY)) * 0.1);
        +
        +  // 노드 옮기기
        +  for (let i = 0; i < nodes; i++){
        +    nodeX[i] = nodeStartX[i] + sin(radians(angle[i])) * (accelX * 2);
        +    nodeY[i] = nodeStartY[i] + sin(radians(angle[i])) * (accelY * 2);
        +    angle[i] += frequency[i];
        +  }
        +}
        diff --git a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        new file mode 100644
        index 0000000000..c06ad9cb4d
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        @@ -0,0 +1,181 @@
        +/*
        + * @name 스모크 파티클
        + * @description 다니엘 쉬프만(Dan Shiffman)이 프로세싱(Processing)을 위해 제작한
        + * 스모크 파티클 시스템(SmokeParticleSystem) 예제를 옮겨왔습니다.
        + * 마치 연기와 같은 파티클을 만들어볼까요 :p
        + */
        +
        +// 파티클 텍스쳐
        +let particle_texture = null;
        +
        +// 파티클 시스템을 담는 변수
        +let ps = null;
        +
        +function preload() {
        +  particle_texture = loadImage("assets/particle_texture.png");
        +}
        +
        +function setup() {
        +
        +  // 캔버스 사이즈 설정
        +  createCanvas(640, 360);
        +
        +  // 파티클 시스템 초기화
        +  ps = new ParticleSystem(0, createVector(width / 2, height - 60), particle_texture);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let dx = map(mouseX, 0, width, -0.2, 0.2);
        +  let wind = createVector(dx, 0);
        +
        +  ps.applyForce(wind);
        +  ps.run();
        +  for (let i = 0; i < 2; i++) {
        +    ps.addParticle();
        +  }
        +
        +  // 바람의 힘을 뜻하는 화살표 그리기
        +  drawVector(wind, createVector(width / 2, 50, 0), 500);
        +}
        +
        +/**
        + *  이 함수는 "wind(바람)"이 부는 방향을 나타낸 화살표를 그립니다.
        + */
        +function drawVector(v, loc, scale){
        +  push();
        +  let arrowsize = 4;
        +  translate(loc.x, loc.y);
        +  stroke(255);
        +  rotate(v.heading());
        +
        +  let len = v.mag() * scale;
        +  line(0, 0, len,0);
        +  line(len, 0, len-arrowsize, +arrowsize / 2);
        +  line(len, 0, len-arrowsize, -arrowsize / 2);
        +  pop();
        +}
        +//========= 파티클 시스템 ===========
        +
        +/**
        + * 기본적인 파티클 시스템 클래스
        + * @param num 파티클 개수를 나타내는 매개 변수
        + * @param v 파티클 시스템의 원점을 나타내는 매개 변수
        + * @param img_ 시스템 상 각 파티클의 텍스쳐를 나타내는 매개 변수
        + * @constructor 생성자
        + */
        +let ParticleSystem = function(num, v, img_) {
        +
        +  this.particles = [];
        +  this.origin = v.copy(); // 실수로 원래 벡터값(origin)을 바꾼 경우를 대비하여, 벡터값을 복사합니다.
        +  this.img = img_
        +  for(let i = 0; i < num; ++i){
        +    this.particles.push(new Particle(this.origin, this.img));
        +  }
        +};
        +
        +/**
        + * 이 함수는 전체 파티클 시스템을 실행합니다.
        + */
        +ParticleSystem.prototype.run = function() {
        +
        +  // 변수들에 반복할, 숨겨진 배열 길이
        +  // for 반복문에 <variable> .length가 표시 될 수 있지만, 매 반복마다 그 길이가
        +  // 다시 계산되기 때문에 여기에 숨깁니다.
        +  let len = this.particles.length;
        +
        +  //파티클 반복 및 실행
        +  for (let i = len - 1; i >= 0; i--) {
        +    let particle = this.particles[i];
        +    particle.run();
        +
        +    // 파티클이 죽을 경우, 제거(remove)합니다.
        +    // 자바스크립트의 배열에는 "remove" 기능이 없지만,
        +    // 대신 동일한 기능을 수행하는 "splice"를 사용할 수 있습니다.
        +    // 제거를 시작할 지점에 인덱스를 넣고, 해당 지점부터 몇 개를 제거할 지 넣을 수 있습니다.
        +    if (particle.isDead()) {
        +      this.particles.splice(i, 1);
        +    }
        +  }
        +}
        +
        +/**
        + * 현재 시스템의 존재하는 모든 파티클에 힘 벡터를 추가하는 메소드
        + * @param dir 힘의 방향을 묘사하는 p5.Vector 매개 변수
        + */
        +ParticleSystem.prototype.applyForce = function(dir) {
        +  let len = this.particles.length;
        +  for(let i = 0; i < len; ++i){
        +    this.particles[i].applyForce(dir);
        +  }
        +}
        +
        +/**
        + * 본래 지정된 텍스쳐와 동일한 텍스쳐의 파티클을 시스템 원점에 추가
        + */
        +ParticleSystem.prototype.addParticle = function() {
        +    this.particles.push(new Particle(this.origin, this.img));
        +}
        +
        +//========= 파티클 ===========
        +/**
        + * 파티클을 이미지로 렌더링하는 간단한 파티클 클래스
        + */
        +let Particle = function (pos, img_) {
        +  this.loc = pos.copy();
        +
        +  let vx = randomGaussian() * 0.3;
        +  let vy = randomGaussian() * 0.3 - 1.0;
        +
        +  this.vel = createVector(vx, vy);
        +  this.acc = createVector();
        +  this.lifespan = 100.0;
        +  this.texture = img_;
        +}
        +
        +/**
        + *  파티클을 동시에 업데이트하고 보이게 하기
        + */
        +Particle.prototype.run = function() {
        +  this.update();
        +  this.render();
        +}
        +
        +/**
        + *  A function to display a particle
        + */
        +Particle.prototype.render = function() {
        +  imageMode(CENTER);
        +  tint(255, this.lifespan);
        +  image(this.texture, this.loc.x, this.loc.y);
        +}
        +
        +/**
        + *  파티클에 힘 벡터를 적용하는 메소드
        + */
        +Particle.prototype.applyForce = function(f) {
        +  this.acc.add(f);
        +}
        +
        +/**
        + *  파티클의 lifespan(수명)이 끝나가는지 여부를 확인하는 메소드
        + *  만약 끝나간다면 true(참)을, 그렇지 않다면 false(거짓)을 반환
        + */
        +Particle.prototype.isDead = function () {
        +  if (this.lifespan <= 0.0) {
        +    return true;
        +  } else {
        +      return false;
        +    }
        +}
        +
        +/**
        + *  파티클의 위치를 업데이트하는 메소드
        + */
        +Particle.prototype.update = function() {
        +  this.vel.add(this.acc);
        +  this.loc.add(this.vel);
        +  this.lifespan -= 2.5;
        +  this.acc.mult(0);
        +}
        diff --git a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        new file mode 100644
        index 0000000000..3299544550
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        @@ -0,0 +1,46 @@
        +/*
        + * @name 브라운 운동
        + * @description 무작위의 움직임을 연속된 선으로서 기록합니다.
        + * 프로세싱(Processing) 홈페이지의 예제 페이지에 있는 원본 예제를 옮겨왔습니다.
        + */
        +
        +let num = 2000;
        +let range = 6;
        +
        +let ax = [];
        +let ay = [];
        +
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  for ( let i = 0; i < num; i++ ) {
        +    ax[i] = width / 2;
        +    ay[i] = height / 2;
        +  }
        +  frameRate(30);
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  // 모든 요소들을 좌측으로 1자리 이동
        +  for ( let i = 1; i < num; i++ ) {
        +    ax[i - 1] = ax[i];
        +    ay[i - 1] = ay[i];
        +  }
        +
        +  // 배열의 끝에 새로운 값 넣기
        +  ax[num - 1] += random(-range, range);
        +  ay[num - 1] += random(-range, range);
        +
        +  // 모든 점들을 화면에 제한
        +  ax[num - 1] = constrain(ax[num - 1], 0, width);
        +  ay[num - 1] = constrain(ay[num - 1], 0, height);
        +
        +  // 점들을 잇는 선 그리기
        +  for ( let j = 1; j < num; j++ ) {
        +    let val = j / num * 204.0 + 51;
        +    stroke(val);
        +    line(ax[j - 1], ay[j - 1], ax[j], ay[j]);
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/13_Chain.js b/src/data/examples/ko/09_Simulate/13_Chain.js
        new file mode 100644
        index 0000000000..48dd33d3fa
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/13_Chain.js
        @@ -0,0 +1,56 @@
        +/*
        + * @name 사슬
        + * @description 한 도형은 마우스 커서 위치에, 다른 하나는 이 도형의 위치에 붙어 따라옵니다.
        + * 화면에는 중력이 작용하여 두 도형을 아래 방향으로 끌어당깁니다.
        + * 프로세싱(Processing) 홈페이지의 예제 페이지에서 옮겨왔습니다.
        + */
        +let s1, s2;
        +let gravity = 9.0;
        +let mass = 2.0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  fill(255, 126);
        +  // 입력: x, y, mass(질량), gravity(중력)
        +  s1 = new Spring2D(0.0, width / 2, mass, gravity);
        +  s2 = new Spring2D(0.0, width / 2, mass, gravity);
        +}
        +
        +function draw() {
        +  background(0);
        +  s1.update(mouseX, mouseY);
        +  s1.display(mouseX, mouseY);
        +  s2.update(s1.x, s1.y);
        +  s2.display(s1.x, s1.y);
        +}
        +
        +function Spring2D(xpos, ypos, m, g) {
        +  this.x = xpos;// x 와 y 좌표
        +  this.y = ypos;
        +  this.vx = 0; // x축과 y축 속도
        +  this.vy = 0;
        +  this.mass = m;
        +  this.gravity = g;
        +  this.radius = 30;
        +  this.stiffness = 0.2;
        +  this.damping = 0.7;
        +
        +  this.update = function(targetX, targetY) {
        +    let forceX = (targetX - this.x) * this.stiffness;
        +    let ax = forceX / this.mass;
        +    this.vx = this.damping * (this.vx + ax);
        +    this.x += this.vx;
        +    let forceY = (targetY - this.y) * this.stiffness;
        +    forceY += this.gravity;
        +    let ay = forceY / this.mass;
        +    this.vy = this.damping * (this.vy + ay);
        +    this.y += this.vy;
        +  }
        +
        +  this.display = function(nx, ny) {
        +    noStroke();
        +    ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
        +    stroke(255);
        +    line(this.x, this.y, nx, ny);
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        new file mode 100644
        index 0000000000..abb61316f9
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        @@ -0,0 +1,63 @@
        +/*
        + * @name 눈송이
        + * @description 이 파티클 시스템은 마치 떨어지는 눈송이같은 모션을 시뮬레이션합니다.
        + * 눈송이 파티클을 담는 객체 배열을 사용합니다.
        + * 애티쉬 바티아(Aatish Bhatia) 기여.
        + */
        +
        +let snowflakes = []; // 눈송이 객체를 담는 배열
        +
        +function setup() {
        +  createCanvas(400, 600);
        +  fill(240);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background('brown');
        +  let t = frameCount / 60; // 시간 업데이트
        +
        +  // 매 프라임마다 무작위 개수의 눈송이 생성
        +  for (let i = 0; i < random(5); i++) {
        +    snowflakes.push(new snowflake()); // 눈송이 객체 추가
        +  }
        +
        +  // for 반복문을 사용하여 눈송이 반복
        +  for (let flake of snowflakes) {
        +    flake.update(t); // 눈송이 위치 업데이트
        +    flake.display(); // 눈송이 그리기
        +  }
        +}
        +
        +// snowflake 클래스
        +function snowflake() {
        +  // 좌표값 초기화
        +  this.posX = 0;
        +  this.posY = random(-50, 0);
        +  this.initialangle = random(0, 2 * PI);
        +  this.size = random(2, 5);
        +
        +  // 방사형 눈송이의 반지름
        +  // 눈송이를 화면에 고루 퍼뜨리기 위해 선택
        +  this.radius = sqrt(random(pow(width / 2, 2)));
        +
        +  this.update = function(time) {
        +    // 원형을 따라다니는 x 위치
        +    let w = 0.6; // 각속도
        +    let angle = w * time + this.initialangle;
        +    this.posX = width / 2 + this.radius * sin(angle);
        +
        +    // 크기가 다른 눈송이가 미묘하게 다른 y 속도로 떨어집니다.
        +    this.posY += pow(this.size, 0.5);
        +
        +    // 화면 하단을 지나친 눈송이는 삭제
        +    if (this.posY > height) {
        +      let index = snowflakes.indexOf(this);
        +      snowflakes.splice(index, 1);
        +    }
        +  };
        +
        +  this.display = function() {
        +    ellipse(this.posX, this.posY, this.size);
        +  };
        +}
        diff --git a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        new file mode 100644
        index 0000000000..40e17ca292
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        @@ -0,0 +1,125 @@
        +/*
        + * @name 펜로즈 타일
        + * @frame 710,400
        + * @description 이 예제는 데이비드 블리츠(David Blitz)가 processing.org/examples의 "펜로즈 타일(Penrose Tile)" 예제에서 옮겨왔습니다.
        + */
        +
        +let ds;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  ds = new PenroseLSystem();
        +  //다음의 줄과 함께 놀아보세요!
        +  ds.simulate(5);
        +}
        +
        +function draw() {
        +  background(0);
        +  ds.render();
        +}
        +
        +function PenroseLSystem() {
        +    this.steps = 0;
        +
        +   //아래는 펜로즈 마름모 L-시스템의 공리와 규칙들입니다.
        +   //레퍼런스가 있다면 좋겠지만, 좋은 사례를 찾지 못했습니다.
        +    this.axiom = "[X]++[X]++[X]++[X]++[X]";
        +    this.ruleW = "YF++ZF----XF[-YF----WF]++";
        +    this.ruleX = "+YF--ZF[---WF--XF]+";
        +    this.ruleY = "-WF++XF[+++YF++ZF]-";
        +    this.ruleZ = "--YF++++WF[+ZF++++XF]--XF";
        +
        +    //아래의 두 줄과 함께 놀아보세요!
        +    this.startLength = 460.0;
        +    this.theta = TWO_PI / 10.0; //36도, TWO_PI / 6.0도을 넣어보세요, ...
        +    this.reset();
        +}
        +
        +PenroseLSystem.prototype.simulate = function (gen) {
        +  while (this.getAge() < gen) {
        +    this.iterate(this.production);
        +  }
        +}
        +
        +PenroseLSystem.prototype.reset = function () {
        +    this.production = this.axiom;
        +    this.drawLength = this.startLength;
        +    this.generations = 0;
        +  }
        +
        +PenroseLSystem.prototype.getAge = function () {
        +    return this.generations;
        +  }
        +
        +//대체 규칙을 적용하여, 문자열의 새로운 반복 생성
        +PenroseLSystem.prototype.iterate = function() {
        +    let newProduction = "";
        +
        +    for(let i=0; i < this.production.length; ++i) {
        +      let step = this.production.charAt(i);
        +      // 현재 문자가 'W'이면,
        +      // 이 현재 문자를 규칙에 맞게 대체합니다.
        +      if (step == 'W') {
        +        newProduction = newProduction + this.ruleW;
        +      }
        +      else if (step == 'X') {
        +        newProduction = newProduction + this.ruleX;
        +      }
        +      else if (step == 'Y') {
        +        newProduction = newProduction + this.ruleY;
        +      }
        +      else if (step == 'Z') {
        +        newProduction = newProduction + this.ruleZ;
        +      }
        +      else {
        +        // 모든 'F'를 drop 삭제하되, 
        +        // 여타 문자들(예. '+', '-', '[', ']')은 건들지 않는다.
        +        if (step != 'F') {
        +          newProduction = newProduction + step;
        +        }
        +      }
        +    }
        +
        +    this.drawLength = this.drawLength * 0.5;
        +    this.generations++;
        +    this.production = newProduction;
        +}
        +
        +//문자열을 거북이 그래픽으로 변환
        +PenroseLSystem.prototype.render = function () {
        +    translate(width / 2, height / 2);
        +
        +    this.steps += 20;
        +    if(this.steps > this.production.length) {
        +      this.steps = this.production.length;
        +    }
        +
        +    for(let i=0; i<this.steps; ++i) {
        +      let step = this.production.charAt(i);
        +
        +      //'W', 'X', 'Y', 'Z' 기호들은 거북이 동작에 상응하지 않습니다.
        +      if( step == 'F') {
        +        stroke(255, 60);
        +        for(let j=0; j < this.repeats; j++) {
        +          line(0, 0, 0, -this.drawLength);
        +          noFill();
        +          translate(0, -this.drawLength);
        +        }
        +        this.repeats = 1;
        +      }
        +      else if (step == '+') {
        +        rotate(this.theta);
        +      }
        +      else if (step == '-') {
        +        rotate(-this.theta);
        +      }
        +      else if (step == '[') {
        +        push();
        +      }
        +      else if (step == ']') {
        +        pop();
        +      }
        +    }
        +  }
        +
        +
        diff --git a/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        new file mode 100644
        index 0000000000..14d177dbb5
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        @@ -0,0 +1,55 @@
        +/*
        + * @name 재귀 나무
        + * @description 재귀를 통해 나무와 같은 구조를 간단히 렌더링합니다.
        + * 나뭇가지의 분기 각도는 마우스 수평 위치에 대한 함수로써 계산됩니다.
        + * 마우스를 좌우로 움직혀 각도를 바꿔보세요.
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/tree.html">재귀 나무 예제</a> 에서 옮겨왔습니다.
        + */
        +let theta;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +}
        +
        +function draw() {
        +  background(0);
        +  frameRate(30);
        +  stroke(255);
        +  // 마우스 위치에 따라 0부터 90도 중 각도 한 개를 골라볼까요!
        +  let a = (mouseX / width) * 90;
        +  // 이를 라디안 값으로 전환합니다.
        +  theta = radians(a);
        +  // 화면 하단에서 나무 시작하기
        +  translate(width/2,height);
        +  // 120픽셀 길이의 선 그리기
        +  line(0,0,0,-120);
        +  // 위의 선의 끝 지점으로 이동하기
        +  translate(0,-120);
        +  // 나뭇가지의 재귀적 분기 시작하기!
        +  branchㅌ(120);
        +
        +}
        +
        +function branch(h) {
        +  // 각각의 나뭇가지 크기는 이전 가지의 2/3에 해당합니다.
        +  h *= 0.66;
        +
        +  // 모든 재귀 함수에는 종료(exit) 조건이 있어야합니다!!!
        +  // 이 예제의 경우, 나뭇 가지의 길이가 2픽셀과 같거나 적을 때 입니다.
        +  if (h > 2) {
        +    push();    // 현재의 변형 상태를 저장 (즉, 현재 상태)
        +    rotate(theta);   // theta(세타)값으로 회전하기
        +    line(0, 0, 0, -h);  // 나뭇가지 그리기
        +    translate(0, -h); // 나뭇가지의 끝 지점으로 이동하기
        +    branch(h);       // 자, 이제 자기 자신을 호출하여 2개의 새로운 나뭇가지를 그릴게요!
        +    pop();     // 이 지점에 도달할 때 마다, 이전 매트릭스 상태를 복원하기 위해 "pop(팝)"합니다.
        +
        +    // 같은 내용을 반복하되, 이번에는 "왼쪽"으로만 가지가 분기하도록 만듭니다!
        +    push();
        +    rotate(-theta);
        +    line(0, 0, 0, -h);
        +    translate(0, -h);
        +    branch(h);
        +    pop();
        +  }
        +}
        diff --git a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        new file mode 100644
        index 0000000000..6b41ae6ab4
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        @@ -0,0 +1,86 @@
        +/*
        + * @name 망델브로 집합
        + * @description 망델브로(Mandelbrot) 집합을 간단히 렌더링합니다.
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/mandelbrot.html">망델브로 예제</a>에서 옮겨왔습니다.
        + */
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  pixelDensity(1);
        +  noLoop();
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // 복잡한 평면 위에서 값의 범위를 설정
        +  // 설정된 범위에 따라 프랙탈을 줌인 또는 줌아웃할 수 있습니다.
        +
        +  // 모든 것은 너비값에서 시작합니다. 더 크거나 적은 값을 시도해보세요.
        +  const w = 4;
        +  const h = (w * height) / width;
        +
        +  // 너비와 높이의 음의 절반에서 시작
        +  const xmin = -w/2;
        +  const ymin = -h/2;
        +
        +  // pixels[] 배열에 쓸 수 있는지 확인합니다.
        +  // 다른 드로잉을 하지 않으므로, 이 작업은 한번만 수행합니다.
        +  loadPixels();
        +
        +  // 복잡한 평면 위의 각 점마다 반복할 수 있는 최대 횟수
        +  const maxiterations = 100;
        +
        +  // x는 xmin에서 xmax로 이동
        +  const xmax = xmin + w;
        +  // y는 ymin에서 ymax로 이동
        +  const ymax = ymin + h;
        +
        +  // 각 픽셀마다 x,y를 증가하는 양 계산
        +  const dx = (xmax - xmin) / (width);
        +  const dy = (ymax - ymin) / (height);
        +
        +  // y 시작
        +  let y = ymin;
        +  for (let j = 0; j < height; j++) {
        +    // x 시작
        +    let x = xmin;
        +    for (let i = 0; i < width; i++) {
        +
        +      // 이제, 우리가 z = z^2 + cm 를 반복 할 때 z가 무한대로 향하나요?
        +      let a = x;
        +      let b = y;
        +      let n = 0;
        +      while (n < maxiterations) {
        +        const aa = a * a;
        +        const bb = b * b;
        +        const twoab = 2.0 * a * b;
        +        a = aa - bb + x;
        +        b = twoab + y;
        +        // 이 유한한 세상에서의 무한대 개념은 간단합니다. 여기서는 그냥 16이라 설정하지요.
        +        if (dist(aa, bb, 0, 0) > 16) {
        +          break; 
        +        }
        +        n++;
        +      }
        +
        +      // 무한대에 도달하기까지 걸리는 시간을 기준으로 각 픽셀에 색상을 지정합니다.
        +      // 도달하지 못할 경우, 검정색으로 지정합니다.
        +      const pix = (i+j*width)*4;
        +      const norm = map(n, 0, maxiterations, 0, 1);
        +      let bright = map(sqrt(norm), 0, 1, 0, 255);
        +      if (n == maxiterations) {
        +        bright = 0;
        +      } else {
        +        // 원한다면 여기서 좀 더 화려한 색상을 만들 수 있습니다.
        +        pixels[pix + 0] = bright;
        +        pixels[pix + 1] = bright;
        +        pixels[pix + 2] = bright;
        +        pixels[pix + 3] = 255;
        +      }
        +      x += dx;
        +    }
        +    y += dy;
        +  }
        +  updatePixels();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/10_Tickle.js b/src/data/examples/ko/10_Interaction/10_Tickle.js
        new file mode 100644
        index 0000000000..1a013d41a9
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/10_Tickle.js
        @@ -0,0 +1,48 @@
        +/*
        + * @name 간질간질
        + * @description 마우스 커서를 갖다대면 "tickle"이라는 단어가 간지럼을 타듯 떨립니다.
        + * 너무 간지럽히면 화면 밖으로 튀어나갈 수도 있습니다 XD
        + */
        +let message = 'tickle',
        +  font,
        +  bounds, // 텍스트의 바운딩 박스에 대한 x, y, w, h값
        +  fontsize = 60,
        +  x,
        +  y; // 텍스트의 x 와 y 좌표
        +
        +function preload() {
        +  font = loadFont('assets/SourceSansPro-Regular.otf');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 폰트 설정
        +  textFont(font);
        +  textSize(fontsize);
        +
        +  // 초기화시 중앙 정렬을 하기 위해 텍스트의 너비 및 높이값을 받아옴
        +  bounds = font.textBounds(message, 0, 0, fontsize);
        +  x = width / 2 - bounds.w / 2;
        +  y = height / 2 - bounds.h / 2;
        +}
        +
        +function draw() {
        +  background(204, 120);
        +
        +  // 텍스트를 검정색으로 쓰고 그 바운딩 박스를 받아옴
        +  fill(0);
        +  text(message, x, y);
        +  bounds = font.textBounds(message, x, y, fontsize);
        +
        +  // 마우스가 바운딩 박스 안에 있는지를 확인하고, 안에 있다면 간질간질!
        +  if (
        +    mouseX >= bounds.x &&
        +    mouseX <= bounds.x + bounds.w &&
        +    mouseY >= bounds.y &&
        +    mouseY <= bounds.y + bounds.h
        +  ) {
        +    x += random(-5, 5);
        +    y += random(-5, 5);
        +  }
        +}
        diff --git a/src/data/examples/ko/10_Interaction/20_Follow1.js b/src/data/examples/ko/10_Interaction/20_Follow1.js
        new file mode 100644
        index 0000000000..f6953d4dc0
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/20_Follow1.js
        @@ -0,0 +1,37 @@
        +/*
        + * @name 따라가기 1
        + * @frame 710,400
        + * @description 마우스 커서로 선분을 밀고 당깁니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let x = 100,
        +  y = 100,
        +  angle1 = 0.0,
        +  segLength = 50;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(20.0);
        +  stroke(255, 100);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  dx = mouseX - x;
        +  dy = mouseY - y;
        +  angle1 = atan2(dy, dx);
        +  x = mouseX - cos(angle1) * segLength;
        +  y = mouseY - sin(angle1) * segLength;
        +
        +  segment(x, y, angle1);
        +  ellipse(x, y, 20, 20);
        +}
        +
        +function segment(x, y, a) {
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/21_Follow2.js b/src/data/examples/ko/10_Interaction/21_Follow2.js
        new file mode 100644
        index 0000000000..276ebaa52b
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/21_Follow2.js
        @@ -0,0 +1,39 @@
        +/*
        + * @name 따라다니기 2
        + * @frame 710,400
        + * @description 팔 형상의 두 선분이 마우스 커서의 위치를 따라다닙니다.
        + * 선분들 사이의 상대 각도는 atan2()로, 그 위치는 sin()과 cos()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let x = [0, 0],
        +  y = [0, 0],
        +  segLength = 50;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(20.0);
        +  stroke(255, 100);
        +}
        +
        +function draw() {
        +  background(0);
        +  dragSegment(0, mouseX, mouseY);
        +  dragSegment(1, x[0], y[0]);
        +}
        +
        +function dragSegment(i, xin, yin) {
        +  const dx = xin - x[i];
        +  const dy = yin - y[i];
        +  const angle = atan2(dy, dx);
        +  x[i] = xin - cos(angle) * segLength;
        +  y[i] = yin - sin(angle) * segLength;
        +  segment(x[i], y[i], angle);
        +}
        +
        +function segment(x, y, a) {
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/22_Follow3.js b/src/data/examples/ko/10_Interaction/22_Follow3.js
        new file mode 100644
        index 0000000000..7f585e572b
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/22_Follow3.js
        @@ -0,0 +1,47 @@
        +/*
        + * @name 따라다니기 3
        + * @frame 710,400
        + * @description 선분이 마우스를 따라다닙니다. 한 선분의 다음 선분에 대한 상대 각도는 atan2()로,
        + * 다음 선분의 위치는 sin()과 cos()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let x = [],
        +  y = [],
        +  segNum = 20,
        +  segLength = 18;
        +
        +for (let i = 0; i < segNum; i++) {
        +  x[i] = 0;
        +  y[i] = 0;
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(9);
        +  stroke(255, 100);
        +}
        +
        +function draw() {
        +  background(0);
        +  dragSegment(0, mouseX, mouseY);
        +  for (let i = 0; i < x.length - 1; i++) {
        +    dragSegment(i + 1, x[i], y[i]);
        +  }
        +}
        +
        +function dragSegment(i, xin, yin) {
        +  const dx = xin - x[i];
        +  const dy = yin - y[i];
        +  const angle = atan2(dy, dx);
        +  x[i] = xin - cos(angle) * segLength;
        +  y[i] = yin - sin(angle) * segLength;
        +  segment(x[i], y[i], angle);
        +}
        +
        +function segment(x, y, a) {
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/23_snake.js b/src/data/examples/ko/10_Interaction/23_snake.js
        new file mode 100644
        index 0000000000..4b370aca83
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/23_snake.js
        @@ -0,0 +1,172 @@
        +/*
        + * @name 스네이크 게임
        + * @description 그 유명한 스네이크 게임입니다! 실행(run)을 누르고, 
        + * 검은 화면 위 아무 지점을 클릭한 뒤, i,j,k,l 키로 뱀을 조종할 수 있습니다.
        + * 뱀이 벽이나 자신의 몸통에 닿지 않도록 하세요!<br>
        + * 예제 제작: <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta
        + */
        +
        +// the snake is divided into small segments, which are drawn and edited on each 'draw' call
        +let numSegments = 10;
        +let direction = 'right';
        +
        +const xStart = 0; //starting x coordinate for snake
        +const yStart = 250; //starting y coordinate for snake
        +const diff = 10;
        +
        +let xCor = [];
        +let yCor = [];
        +
        +let xFruit = 0;
        +let yFruit = 0;
        +let scoreElem;
        +
        +function setup() {
        +  scoreElem = createDiv('Score = 0');
        +  scoreElem.position(20, 20);
        +  scoreElem.id = 'score';
        +  scoreElem.style('color', 'white');
        +
        +  createCanvas(500, 500);
        +  frameRate(15);
        +  stroke(255);
        +  strokeWeight(10);
        +  updateFruitCoordinates();
        +
        +  for (let i = 0; i < numSegments; i++) {
        +    xCor.push(xStart + i * diff);
        +    yCor.push(yStart);
        +  }
        +}
        +
        +function draw() {
        +  background(0);
        +  for (let i = 0; i < numSegments - 1; i++) {
        +    line(xCor[i], yCor[i], xCor[i + 1], yCor[i + 1]);
        +  }
        +  updateSnakeCoordinates();
        +  checkGameStatus();
        +  checkForFruit();
        +}
        +
        +/*
        + The segments are updated based on the direction of the snake.
        + All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0
        + gets the value of segment 1, segment 1 gets the value of segment 2, and so on,
        + and this results in the movement of the snake.
        +
        + The last segment is added based on the direction in which the snake is going,
        + if it's going left or right, the last segment's x coordinate is increased by a
        + predefined value 'diff' than its second to last segment. And if it's going up
        + or down, the segment's y coordinate is affected.
        +*/
        +function updateSnakeCoordinates() {
        +  for (let i = 0; i < numSegments - 1; i++) {
        +    xCor[i] = xCor[i + 1];
        +    yCor[i] = yCor[i + 1];
        +  }
        +  switch (direction) {
        +    case 'right':
        +      xCor[numSegments - 1] = xCor[numSegments - 2] + diff;
        +      yCor[numSegments - 1] = yCor[numSegments - 2];
        +      break;
        +    case 'up':
        +      xCor[numSegments - 1] = xCor[numSegments - 2];
        +      yCor[numSegments - 1] = yCor[numSegments - 2] - diff;
        +      break;
        +    case 'left':
        +      xCor[numSegments - 1] = xCor[numSegments - 2] - diff;
        +      yCor[numSegments - 1] = yCor[numSegments - 2];
        +      break;
        +    case 'down':
        +      xCor[numSegments - 1] = xCor[numSegments - 2];
        +      yCor[numSegments - 1] = yCor[numSegments - 2] + diff;
        +      break;
        +  }
        +}
        +
        +/*
        + I always check the snake's head position xCor[xCor.length - 1] and
        + yCor[yCor.length - 1] to see if it touches the game's boundaries
        + or if the snake hits itself.
        +*/
        +function checkGameStatus() {
        +  if (
        +    xCor[xCor.length - 1] > width ||
        +    xCor[xCor.length - 1] < 0 ||
        +    yCor[yCor.length - 1] > height ||
        +    yCor[yCor.length - 1] < 0 ||
        +    checkSnakeCollision()
        +  ) {
        +    noLoop();
        +    const scoreVal = parseInt(scoreElem.html().substring(8));
        +    scoreElem.html('Game ended! Your score was : ' + scoreVal);
        +  }
        +}
        +
        +/*
        + If the snake hits itself, that means the snake head's (x,y) coordinate
        + has to be the same as one of its own segment's (x,y) coordinate.
        +*/
        +function checkSnakeCollision() {
        +  const snakeHeadX = xCor[xCor.length - 1];
        +  const snakeHeadY = yCor[yCor.length - 1];
        +  for (let i = 0; i < xCor.length - 1; i++) {
        +    if (xCor[i] === snakeHeadX && yCor[i] === snakeHeadY) {
        +      return true;
        +    }
        +  }
        +}
        +
        +/*
        + Whenever the snake consumes a fruit, I increment the number of segments,
        + and just insert the tail segment again at the start of the array (basically
        + I add the last segment again at the tail, thereby extending the tail)
        +*/
        +function checkForFruit() {
        +  point(xFruit, yFruit);
        +  if (xCor[xCor.length - 1] === xFruit && yCor[yCor.length - 1] === yFruit) {
        +    const prevScore = parseInt(scoreElem.html().substring(8));
        +    scoreElem.html('Score = ' + (prevScore + 1));
        +    xCor.unshift(xCor[0]);
        +    yCor.unshift(yCor[0]);
        +    numSegments++;
        +    updateFruitCoordinates();
        +  }
        +}
        +
        +function updateFruitCoordinates() {
        +  /*
        +    The complex math logic is because I wanted the point to lie
        +    in between 100 and width-100, and be rounded off to the nearest
        +    number divisible by 10, since I move the snake in multiples of 10.
        +  */
        +
        +  xFruit = floor(random(10, (width - 100) / 10)) * 10;
        +  yFruit = floor(random(10, (height - 100) / 10)) * 10;
        +}
        +
        +function keyPressed() {
        +  switch (keyCode) {
        +    case 74:
        +      if (direction !== 'right') {
        +        direction = 'left';
        +      }
        +      break;
        +    case 76:
        +      if (direction !== 'left') {
        +        direction = 'right';
        +      }
        +      break;
        +    case 73:
        +      if (direction !== 'down') {
        +        direction = 'up';
        +      }
        +      break;
        +    case 75:
        +      if (direction !== 'up') {
        +        direction = 'down';
        +      }
        +      break;
        +  }
        +}
        diff --git a/src/data/examples/ko/10_Interaction/24_Wavemaker.js b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        new file mode 100644
        index 0000000000..92158b8218
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        @@ -0,0 +1,38 @@
        +/*
        + * @name 파도 만들기
        + * @description 이 예제는 특정 위치에서 진동하는 파티클로 파도를 만드는 법을 설명합니다.
        + * 마우스를 움직여 파도의 방향을 바꿔보세요.
        + * 애티쉬 바티아(Aatish Bhatia) 기여, Dan Whyte 제작 <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a>
        + * 로부터 영감을 받았습니다.
        + */
        +
        +let t = 0; // 시간 변수
        +
        +function setup() {
        +  createCanvas(600, 600);
        +  noStroke();
        +  fill(40, 200, 40);
        +}
        +
        +function draw() {
        +  background(10, 10); // 불투명한 배경화면(파티클의 꼬리 만들기)
        +
        +  // 타원형으로 구성된 x와 y 그리드 만들기
        +  for (let x = 0; x <= width; x = x + 30) {
        +    for (let y = 0; y <= height; y = y + 30) {
        +      // 각 타원의 시작 점은 마우스 위치에 따라 달라집니다.
        +      const xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true);
        +      const yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true);
        +      // 또, 파티클의 위치에 따라 달라집니다.
        +      const angle = xAngle * (x / width) + yAngle * (y / height);
        +
        +      // 각 파티클은 동그라미를 그리며 움직입니다.
        +      const myX = x + 20 * cos(2 * PI * t + angle);
        +      const myY = y + 20 * sin(2 * PI * t + angle);
        +
        +      ellipse(myX, myY, 10); // 파티클로 그리기
        +    }
        +  }
        +
        +  t = t + 0.01; // 시간 업데이트
        +}
        diff --git a/src/data/examples/ko/10_Interaction/25_reach1.js b/src/data/examples/ko/10_Interaction/25_reach1.js
        new file mode 100644
        index 0000000000..483283d3da
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/25_reach1.js
        @@ -0,0 +1,57 @@
        +/*
        + * @name 팔닿기 1
        + * @frame 710,400
        + * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let segLength = 80,
        +  x,
        +  y,
        +  x2,
        +  y2;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(20);
        +  stroke(255, 100);
        +
        +  x = width / 2;
        +  y = height / 2;
        +  x2 = x;
        +  y2 = y;
        +}
        +
        +function draw() {
        +  background(0);
        +  dragSegment(0, mouseX, mouseY);
        +  for (let i = 0; i < x.length - 1; i++) {
        +    dragSegment(i + 1, x[i], y[i]);
        +  }
        +}
        +
        +function dragSegment(i, xin, yin) {
        +  background(0);
        +
        +  dx = mouseX - x;
        +  dy = mouseY - y;
        +  angle1 = atan2(dy, dx);
        +
        +  tx = mouseX - cos(angle1) * segLength;
        +  ty = mouseY - sin(angle1) * segLength;
        +  dx = tx - x2;
        +  dy = ty - y2;
        +  angle2 = atan2(dy, dx);
        +  x = x2 + cos(angle2) * segLength;
        +  y = y2 + sin(angle2) * segLength;
        +
        +  segment(x, y, angle1);
        +  segment(x2, y2, angle2);
        +}
        +
        +function segment(x, y, a) {
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/26_reach2.js b/src/data/examples/ko/10_Interaction/26_reach2.js
        new file mode 100644
        index 0000000000..d6b1ae8272
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/26_reach2.js
        @@ -0,0 +1,65 @@
        +/*
        + * @name 팔닿기 2
        + * @frame 710,400
        + * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let numSegments = 10,
        +  x = [],
        +  y = [],
        +  angle = [],
        +  segLength = 26,
        +  targetX,
        +  targetY;
        +
        +for (let i = 0; i < numSegments; i++) {
        +  x[i] = 0;
        +  y[i] = 0;
        +  angle[i] = 0;
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(20);
        +  stroke(255, 100);
        +
        +  x[x.length - 1] = width / 2; // 기본 x좌표 설정
        +  y[x.length - 1] = height; // 기본 y좌표 설정
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  reachSegment(0, mouseX, mouseY);
        +  for (let i = 1; i < numSegments; i++) {
        +    reachSegment(i, targetX, targetY);
        +  }
        +  for (let j = x.length - 1; j >= 1; j--) {
        +    positionSegment(j, j - 1);
        +  }
        +  for (let k = 0; k < x.length; k++) {
        +    segment(x[k], y[k], angle[k], (k + 1) * 2);
        +  }
        +}
        +
        +function positionSegment(a, b) {
        +  x[b] = x[a] + cos(angle[a]) * segLength;
        +  y[b] = y[a] + sin(angle[a]) * segLength;
        +}
        +
        +function reachSegment(i, xin, yin) {
        +  const dx = xin - x[i];
        +  const dy = yin - y[i];
        +  angle[i] = atan2(dy, dx);
        +  targetX = xin - cos(angle[i]) * segLength;
        +  targetY = yin - sin(angle[i]) * segLength;
        +}
        +
        +function segment(x, y, a, sw) {
        +  strokeWeight(sw);
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/10_Interaction/27_reach3.js b/src/data/examples/ko/10_Interaction/27_reach3.js
        new file mode 100644
        index 0000000000..fdf58bc952
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/27_reach3.js
        @@ -0,0 +1,81 @@
        +/*
        + * @name 팔닿기 3
        + * @frame 710,400
        + * @description 팔모양이 공의 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        + */
        +let numSegments = 8,
        +  x = [],
        +  y = [],
        +  angle = [],
        +  segLength = 26,
        +  targetX,
        +  targetY,
        +  ballX = 50,
        +  ballY = 50,
        +  ballXDirection = 1,
        +  ballYDirection = -1;
        +
        +for (let i = 0; i < numSegments; i++) {
        +  x[i] = 0;
        +  y[i] = 0;
        +  angle[i] = 0;
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  strokeWeight(20);
        +  stroke(255, 100);
        +  noFill();
        +
        +  x[x.length - 1] = width / 2; // 기본 x좌표 설정
        +  y[x.length - 1] = height; // 기본 y좌표 설정
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  strokeWeight(20);
        +  ballX = ballX + 1.0 * ballXDirection;
        +  ballY = ballY + 0.8 * ballYDirection;
        +  if (ballX > width - 25 || ballX < 25) {
        +    ballXDirection *= -1;
        +  }
        +  if (ballY > height - 25 || ballY < 25) {
        +    ballYDirection *= -1;
        +  }
        +  ellipse(ballX, ballY, 30, 30);
        +
        +  reachSegment(0, ballX, ballY);
        +  for (let i = 1; i < numSegments; i++) {
        +    reachSegment(i, targetX, targetY);
        +  }
        +  for (let j = x.length - 1; j >= 1; j--) {
        +    positionSegment(j, j - 1);
        +  }
        +  for (let k = 0; k < x.length; k++) {
        +    segment(x[k], y[k], angle[k], (k + 1) * 2);
        +  }
        +}
        +
        +function positionSegment(a, b) {
        +  x[b] = x[a] + cos(angle[a]) * segLength;
        +  y[b] = y[a] + sin(angle[a]) * segLength;
        +}
        +
        +function reachSegment(i, xin, yin) {
        +  const dx = xin - x[i];
        +  const dy = yin - y[i];
        +  angle[i] = atan2(dy, dx);
        +  targetX = xin - cos(angle[i]) * segLength;
        +  targetY = yin - sin(angle[i]) * segLength;
        +}
        +
        +function segment(x, y, a, sw) {
        +  strokeWeight(sw);
        +  push();
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/11_Objects/01_Objects.js b/src/data/examples/ko/11_Objects/01_Objects.js
        new file mode 100644
        index 0000000000..6f20d18677
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/01_Objects.js
        @@ -0,0 +1,39 @@
        +/*
        + * @name 객체(object)
        + * @description Jitter 클래스를 만들고, 객체를 인스턴스화하여
        + * 화면 안에서 움직여보세요. 캐시 리아즈(Casey Reas) & 벤 프라이(Ben Fry) 저 Getting Started with
        + * Processing에서 옮김.
        + */
        +
        +let bug; // 객체 선언
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  // 객체 생성
        +  bug = new Jitter();
        +}
        +
        +function draw() {
        +  background(50, 89, 100);
        +  bug.move();
        +  bug.display();
        +}
        +
        +// Jitter 클래스
        +class Jitter {
        +  constructor() {
        +    this.x = random(width);
        +    this.y = random(height);
        +    this.diameter = random(10, 30);
        +    this.speed = 1;
        +  }
        +
        +  move() {
        +    this.x += random(-this.speed, this.speed);
        +    this.y += random(-this.speed, this.speed);
        +  }
        +
        +  display() {
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        new file mode 100644
        index 0000000000..eb411cdca7
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        @@ -0,0 +1,50 @@
        +/*
        + * @name 복수 객체
        + * @description Jitter 클래스를 만들고, 복수의 객체를 인스턴스화하여
        + * 화면 안에서 움직여보세요.
        + */
        +
        +let bug1; // 객체들 선언
        +let bug2;
        +let bug3;
        +let bug4;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  // 객체 생성
        +  bug1 = new Jitter();
        +  bug2 = new Jitter();
        +  bug3 = new Jitter();
        +  bug4 = new Jitter();
        +}
        +
        +function draw() {
        +  background(50, 89, 100);
        +  bug1.move();
        +  bug1.display();
        +  bug2.move();
        +  bug2.display();
        +  bug3.move();
        +  bug3.display();
        +  bug4.move();
        +  bug4.display();
        +}
        +
        +// Jitter 클래스
        +class Jitter {
        +  constructor() {
        +    this.x = random(width);
        +    this.y = random(height);
        +    this.diameter = random(10, 30);
        +    this.speed = 1;
        +  }
        +
        +  move() {
        +    this.x += random(-this.speed, this.speed);
        +    this.y += random(-this.speed, this.speed);
        +  }
        +
        +  display() {
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Array.js b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        new file mode 100644
        index 0000000000..c64704d1f7
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 객체 배열
        + * @description Jitter 클래스를 만들고, 객체 배열을 인스턴스화하여
        + * 화면 안에서 움직여보세요.
        + */
        +
        +let bugs = []; // array of Jitter objects
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  // Create objects
        +  for (let i = 0; i < 50; i++) {
        +    bugs.push(new Jitter());
        +  }
        +}
        +
        +function draw() {
        +  background(50, 89, 100);
        +  for (let i = 0; i < bugs.length; i++) {
        +    bugs[i].move();
        +    bugs[i].display();
        +  }
        +}
        +
        +// Jitter class
        +class Jitter {
        +  constructor() {
        +    this.x = random(width);
        +    this.y = random(height);
        +    this.diameter = random(10, 30);
        +    this.speed = 1;
        +  }
        +
        +  move() {
        +    this.x += random(-this.speed, this.speed);
        +    this.y += random(-this.speed, this.speed);
        +  }
        +
        +  display() {
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        new file mode 100644
        index 0000000000..25ffa5e70a
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        @@ -0,0 +1,65 @@
        +/*
        + * @name 객체 2
        + * @description hbarragan 제작 예제에서 옮김. 이미지 위로 마우스를 움직여
        + * 기하의 속도와 위치를 바꿔보세요. MRect 클래스가 선들의 군상을 정의합니다.
        + * defines a group of lines.
        + */
        +
        +let r1, r2, r3, r4;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  fill(255, 204);
        +  noStroke();
        +  r1 = new MRect(1, 134.0, 0.532, 0.1 * height, 10.0, 60.0);
        +  r2 = new MRect(2, 44.0, 0.166, 0.3 * height, 5.0, 50.0);
        +  r3 = new MRect(2, 58.0, 0.332, 0.4 * height, 10.0, 35.0);
        +  r4 = new MRect(1, 120.0, 0.0498, 0.9 * height, 15.0, 60.0);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  r1.display();
        +  r2.display();
        +  r3.display();
        +  r4.display();
        +
        +  r1.move(mouseX - width / 2, mouseY + height * 0.1, 30);
        +  r2.move((mouseX + width * 0.05) % width, mouseY + height * 0.025, 20);
        +  r3.move(mouseX / 4, mouseY - height * 0.025, 40);
        +  r4.move(mouseX - width / 2, height - mouseY, 50);
        +}
        +
        +class MRect {
        +  constructor(iw, ixp, ih, iyp, id, it) {
        +    this.w = iw; // 막대기 한 개 너비
        +    this.xpos = ixp; // rect의 x위치
        +    this.h = ih; // rect의 높이
        +    this.ypos = iyp; // rect의 y위치
        +    this.d = id; // 막대기 간 거리
        +    this.t = it; // 막대기 개수
        +  }
        +
        +  move(posX, posY, damping) {
        +    let dif = this.ypos - posY;
        +    if (abs(dif) > 1) {
        +      this.ypos -= dif / damping;
        +    }
        +    dif = this.xpos - posX;
        +    if (abs(dif) > 1) {
        +      this.xpos -= dif / damping;
        +    }
        +  }
        +
        +  display() {
        +    for (let i = 0; i < this.t; i++) {
        +      rect(
        +        this.xpos + i * (this.d + this.w),
        +        this.ypos,
        +        this.w,
        +        height * this.h
        +      );
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/04_Inheritance.js b/src/data/examples/ko/11_Objects/04_Inheritance.js
        new file mode 100644
        index 0000000000..12b3737c05
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/04_Inheritance.js
        @@ -0,0 +1,71 @@
        +/* @name 상속
        + * @description 다른 클래스에 기초하여 클래스를 정의할 수 있습니다. 
        + * 객체 지향 프로그래밍 언어에서, 한 클래스는 다른 클래스의 필드와 메소드를 상속할 수 있습니다.
        + * 이처럼 다른 객체로부터 상속받는 객체를 하위 클래스라 하고,
        + * 상속하는 객체를 상위 클래스라고 합니다.
        + * 하위 클래스는 상위 클래스를 확장합니다.
        + */
        +let spots, arm;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  arm = new SpinArm(width/2, height/2, 0.01);
        +  spots = new SpinSpots(width/2, height/2, -0.02, 90.0);
        +}
        +
        +function draw() {
        +  background(204);
        +  arm.update();
        +  arm.display();
        +  spots.update();
        +  spots.display();
        +}
        +
        +class SpinArm {
        +  constructor(x, y, s) {
        +    this.x = x;
        +    this.y = y;
        +    this.speed = s;
        +    this.angle = 0.0;
        +  }
        +
        +  update() {
        +    this.angle += this.speed;
        +  }
        +
        +  display() {
        +    strokeWeight(1);
        +    stroke(0);
        +    push();
        +    translate(this.x, this.y);
        +    this.angle += this.speed;
        +    rotate(this.angle);
        +    line(0, 0, 165, 0);
        +    pop();
        +  }
        +}
        +
        +class SpinSpots {
        +  constructor(x, y, s, d) {
        +    this.x = x;
        +    this.y = y;
        +    this.speed = s;
        +    this.dim = d;
        +    this.angle = 0.0;
        +  }
        +
        +  update() {
        +    this.angle += this.speed;
        +  }
        +
        +  display() {
        +    noStroke();
        +    push();
        +    translate(this.x, this.y);
        +    this.angle += this.speed;
        +    rotate(this.angle);
        +    ellipse(-this.dim/2, 0, this.dim, this.dim);
        +    ellipse(this.dim/2, 0, this.dim, this.dim);
        +    pop();
        +  }
        +}
        diff --git a/src/data/examples/ko/12_Lights/02_Directional.js b/src/data/examples/ko/12_Lights/02_Directional.js
        new file mode 100644
        index 0000000000..2e09a2c792
        --- /dev/null
        +++ b/src/data/examples/ko/12_Lights/02_Directional.js
        @@ -0,0 +1,28 @@
        +/*
        + * @name 디렉셔널 라이트
        + * @frame 710,400
        + * @description 마우스를 움직여 조명의 방향을 바꿔보세요.
        + * 디렉셔널 라이트는 한 방향에서 비롯되며
        + * 표면에 직각으로 닿을 때 강한 빛을,
        + * 부드러운 각도로 닿았을 때 약한 빛을 보입니다. 
        + * 디렉셔널 라이트는 표면에 닿으면 그 빛이 모든 방향으로 흩어집니다.
        + */
        +const radius = 200;
        +
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +  noStroke();
        +  fill(200);
        +}
        +
        +function draw() {
        +  noStroke();
        +  background(0);
        +  const dirY = (mouseY / height - 0.5) * 4;
        +  const dirX = (mouseX / width - 0.5) * 4;
        +  directionalLight(204, 204, 204, dirX, dirY, 1);
        +  translate(-1.5 * radius, 0, 0);
        +  sphere(radius);
        +  translate(3 * radius, 0, 0);
        +  sphere(radius);
        +}
        diff --git a/src/data/examples/ko/12_Lights/05_Mixture.js b/src/data/examples/ko/12_Lights/05_Mixture.js
        new file mode 100644
        index 0000000000..d01c872f70
        --- /dev/null
        +++ b/src/data/examples/ko/12_Lights/05_Mixture.js
        @@ -0,0 +1,26 @@
        +/*
        + * @name 혼합 라이트
        + * @frame 710,400 (optional)
        + * @description 세 개의 다른 조명과 함께 박스를 보여줍니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // 우측에서 비추는 오렌지색 포인트 라이트
        +  pointLight(150, 100, 0, 500, 0, 200);
        +
        +  // 좌측에서 비추는 파랑색 디렉셔널 라이트
        +  directionalLight(0, 102, 255, -1, 0, 0);
        +
        +  // 정면에서 비추는 노랑색 스포트라이트
        +  pointLight(255, 255, 109, 0, 0, 300);
        +
        +  rotateY(map(mouseX, 0, width, 0, PI));
        +  rotateX(map(mouseY, 0, height, 0, PI));
        +  box(200);
        +}
        diff --git a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        new file mode 100644
        index 0000000000..5fe33ccc9a
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        @@ -0,0 +1,110 @@
        +/*
        + * @name 비직각 반사
        + * @frame 710,400 (optional)
        + * @description 이 예제는 processing.org/examples의 "Reflection 1" 예제를 데이비드 블리츠(David Blitz)가 옮긴 것입니다.
        + */
        +
        +// 바닥의 왼쪽 위치
        +let base1;
        +
        +// 바닥의 오른쪽 위치
        +let base2;
        +// 바닥의 길이
        +//let baseLength;
        +
        +// 움직이는 공에 대한 변수들
        +let position;
        +let velocity;
        +let r = 6;
        +let speed = 3.5;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  fill(128);
        +  base1 = createVector(0, height - 150);
        +  base2 = createVector(width, height);
        +  //createGround();
        +
        +  // 화면 중앙의 상단에서 타원형 시작
        +  position = createVector(width / 2, 0);
        +
        +  // 초기 임의 속도 계산
        +  velocity = p5.Vector.random2D();
        +  velocity.mult(speed);
        +}
        +
        +function draw() {
        +  // 배경 그리기
        +  fill(0, 12);
        +  noStroke();
        +  rect(0, 0, width, height);
        +
        +  // base(밑바닥) 그리기
        +  fill(200);
        +  quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
        +
        +  // base(밑바닥) 상단의 normal(표준) 계산하기
        +  let baseDelta = p5.Vector.sub(base2, base1);
        +  baseDelta.normalize();
        +  let normal = createVector(-baseDelta.y, baseDelta.x);
        +  let intercept = p5.Vector.dot(base1, normal);
        +
        +  // ellipse(타원) 그리기
        +  noStroke();
        +  fill(255);
        +  ellipse(position.x, position.y, r * 2, r * 2);
        +
        +  // 타원 움직이기
        +  position.add(velocity);
        +
        +  // 표준화된 투사 벡터
        +  incidence = p5.Vector.mult(velocity, -1);
        +  incidence.normalize();
        +
        +  // 밑바닥과의 충돌 감지하고 조정하기
        +  if (p5.Vector.dot(normal, position) > intercept) {
        +    //투사 벡터와 밑바닥 상단의 dot(점) 계산
        +    let dot = incidence.dot(normal);
        +
        +    // 반사 벡터 계산
        +    // 반사 벡터를 방향 벡터에 지정
        +    velocity.set(
        +      2 * normal.x * dot - incidence.x,
        +      2 * normal.y * dot - incidence.y,
        +      0
        +    );
        +    velocity.mult(speed);
        +
        +    // 충돌 지점에서 밑바닥 상단 표준 그리기
        +    stroke(255, 128, 0);
        +    line(
        +      position.x,
        +      position.y,
        +      position.x - normal.x * 100,
        +      position.y - normal.y * 100
        +    );
        +  }
        +  //}
        +
        +  // 경계면 충돌 감지
        +  // 우측
        +  if (position.x > width - r) {
        +    position.x = width - r;
        +    velocity.x *= -1;
        +  }
        +  // 좌측
        +  if (position.x < r) {
        +    position.x = r;
        +    velocity.x *= -1;
        +  }
        +  // 상단
        +  if (position.y < r) {
        +    position.y = r;
        +    velocity.y *= -1;
        +
        +    // 밑바닥의 상단 임의화하기
        +    base1.y = random(height - 100, height);
        +    base2.y = random(height - 100, height);
        +  }
        +}
        diff --git a/src/data/examples/ko/13_Motion/02_Linear_Motion.js b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        new file mode 100644
        index 0000000000..454e13377a
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 선형
        + * @frame 720,400
        + * @description 변수를 바꿔 움직이는 선을 만들어보세요.
        + * 선이 화면 상단 밖으로 나가면 변수는 0이 되어
        + * 선의 위치를 화면의 하단으로 되돌립니다.
        + */
        +
        +let a;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  stroke(255);
        +  a = height / 2;
        +}
        +
        +function draw() {
        +  background(51);
        +  line(0, a, width, a);
        +  a = a - 0.5;
        +  if (a < 0) {
        +    a = height;
        +  }
        +}
        diff --git a/src/data/examples/ko/13_Motion/03_Bounce.js b/src/data/examples/ko/13_Motion/03_Bounce.js
        new file mode 100644
        index 0000000000..c1a6b9ae7f
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/03_Bounce.js
        @@ -0,0 +1,44 @@
        +/*
        + * @name 바운스
        + * @frame 720,400
        + * @description 도형이 화면의 모서리에 닿으면 반대 방향으로 움직입니다.
        + */
        +
        +let rad = 60; // 도형의 너비
        +let xpos, ypos; // 도형의 시작점
        +
        +let xspeed = 2.8; // 도형의 속도
        +let yspeed = 2.2; // 도형의 속도
        +
        +let xdirection = 1; // 왼쪽 또는 오른쪽
        +let ydirection = 1; // 위 또는 아래
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  frameRate(30);
        +  ellipseMode(RADIUS);
        +  // 도형의 시작점 설정
        +  xpos = width / 2;
        +  ypos = height / 2;
        +}
        +
        +function draw() {
        +  background(102);
        +
        +  // 도형의 위치 업데이트
        +  xpos = xpos + xspeed * xdirection;
        +  ypos = ypos + yspeed * ydirection;
        +
        +  // 도형이 화면 경계를 넘어가는 지 테스트
        +  // 넘어갈 경우, -1을 곱하여 방향을 반대로 돌린다.
        +  if (xpos > width - rad || xpos < rad) {
        +    xdirection *= -1;
        +  }
        +  if (ypos > height - rad || ypos < rad) {
        +    ydirection *= -1;
        +  }
        +
        +  // 도형 그리기
        +  ellipse(xpos, ypos, rad, rad);
        +}
        diff --git a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        new file mode 100644
        index 0000000000..26566cfe7d
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        @@ -0,0 +1,95 @@
        +/*
        + * @name 바운싱 버블
        + * @frame 720,400
        + * @description 이 예제는 키스 피터스(Keith Peters)가 제작한 복수-객체 충돌(Multiple-object collision) 예제 코드를 기반으로 합니다.
        + */
        +
        +let numBalls = 13;
        +let spring = 0.05;
        +let gravity = 0.03;
        +let friction = -0.9;
        +let balls = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  for (let i = 0; i < numBalls; i++) {
        +    balls[i] = new Ball(
        +      random(width),
        +      random(height),
        +      random(30, 70),
        +      i,
        +      balls
        +    );
        +  }
        +  noStroke();
        +  fill(255, 204);
        +}
        +
        +function draw() {
        +  background(0);
        +  balls.forEach(ball => {
        +    ball.collide();
        +    ball.move();
        +    ball.display();
        +  });
        +}
        +
        +class Ball {
        +  constructor(xin, yin, din, idin, oin) {
        +    this.x = xin;
        +    this.y = yin;
        +    let vx = 0;
        +    let vy = 0;
        +    this.diameter = din;
        +    this.id = idin;
        +    this.others = oin;
        +  }
        +
        +  collide() {
        +    for (let i = this.id + 1; i < numBalls; i++) {
        +      // console.log(others[i]);
        +      let dx = this.others[i].x - this.x;
        +      let dy = this.others[i].y - this.y;
        +      let distance = sqrt(dx * dx + dy * dy);
        +      let minDist = this.others[i].diameter / 2 + this.diameter / 2;
        +      //   console.log(distance);
        +      //console.log(minDist);
        +      if (distance < minDist) {
        +        //console.log("2");
        +        let angle = atan2(dy, dx);
        +        let targetX = this.x + cos(angle) * minDist;
        +        let targetY = this.y + sin(angle) * minDist;
        +        let ax = (targetX - this.others[i].x) * spring;
        +        let ay = (targetY - this.others[i].y) * spring;
        +        vx -= ax;
        +        vy -= ay;
        +        this.others[i].vx += ax;
        +        this.others[i].vy += ay;
        +      }
        +    }
        +  }
        +
        +  move() {
        +    vy += gravity;
        +    this.x += vx;
        +    this.y += vy;
        +    if (this.x + this.diameter / 2 > width) {
        +      this.x = width - this.diameter / 2;
        +      vx *= friction;
        +    } else if (this.x - this.diameter / 2 < 0) {
        +      this.x = this.diameter / 2;
        +      vx *= friction;
        +    }
        +    if (this.y + this.diameter / 2 > height) {
        +      this.y = height - this.diameter / 2;
        +      vy *= friction;
        +    } else if (this.y - this.diameter / 2 < 0) {
        +      this.y = this.diameter / 2;
        +      vy *= friction;
        +    }
        +  }
        +
        +  display() {
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +  }
        +}
        diff --git a/src/data/examples/ko/13_Motion/05_Morph.js b/src/data/examples/ko/13_Motion/05_Morph.js
        new file mode 100644
        index 0000000000..0bf7bdf2fe
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/05_Morph.js
        @@ -0,0 +1,92 @@
        +/*
        + * @name 변형(morph)
        + * @frame 720,400
        + * @description 버텍스를 보간하여 한 모양에서 다른 모양으로 바꾸기
        + */
        +
        +// 두 도형의 버텍스들을 저장하는 두 개의 배열 리스트(ArrayList)
        +// 이 예제는 두 도형이 동일한 개수의 버텍스를 갖고 있다는 것을 전제합니다.
        +// 즉, 배열 리스트가 동일하다는 뜻입니다.
        +let circle = [];
        +let square = [];
        +
        +// 3번째 버텍스 묶음 저장을 위한 배열 리스트
        +// 화면상 그려집니다.
        +let morph = [];
        +
        +// 이 불리언 변수는 원형이나 사각형으로 변형할지 여부를 결정합니다.
        +let state = false;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +
        +  // 중심을 가리키는 벡터를 사용하여 원 그리기
        +  for (let angle = 0; angle < 360; angle += 9) {
        +    // 주의: 원의 이동 경로와 상응하기 위해, 0에서 시작하지 않습니다.
        +    let v = p5.Vector.fromAngle(radians(angle - 135));
        +    v.mult(100);
        +    circle.push(v);
        +    // morph 배열 리스트를 빈 PVector로 채웁니다.
        +    morph.push(createVector());
        +  }
        +
        +  // 사각형은 직선을 따라 이어진 여러 개의 버텍스입니다.
        +  // 사각형 상단
        +  for (let x = -50; x < 50; x += 10) {
        +    square.push(createVector(x, -50));
        +  }
        +  // 사각형 우측
        +  for (let y = -50; y < 50; y += 10) {
        +    square.push(createVector(50, y));
        +  }
        +  // 사각형 하단
        +  for (let x = 50; x > -50; x -= 10) {
        +    square.push(createVector(x, 50));
        +  }
        +  // 사각형 좌측
        +  for (let y = 50; y > -50; y -= 10) {
        +    square.push(createVector(-50, y));
        +  }
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  // 이 버텍스들이 목표 대상으로부터 얼마나 멀리 있는지 확인
        +  let totalDistance = 0;
        +
        +  // 각 버텍스 확인
        +  for (let i = 0; i < circle.length; i++) {
        +    let v1;
        +    // 원형이나 사각형으로 선형 보간합니까?
        +    if (state) {
        +      v1 = circle[i];
        +    } else {
        +      v1 = square[i];
        +    }
        +    // 그려질 버텍스 가져오기
        +    let v2 = morph[i];
        +    // 대상을 향해 선형 보간하기
        +    v2.lerp(v1, 0.1);
        +    // 목표 대상으로부터 얼마나 멀리 있는지 확인
        +    totalDistance += p5.Vector.dist(v1, v2);
        +  }
        +
        +  // 모든 버텍스들이 가까워지면, 모양 전환
        +  if (totalDistance < 0.1) {
        +    state = !state;
        +  }
        +
        +  // 중심을 기준으로 그리기
        +  translate(width / 2, height / 2);
        +  strokeWeight(4);
        +  // 모든 버텍스를 구성하는 다각형 그리기
        +  beginShape();
        +  noFill();
        +  stroke(255);
        +
        +  morph.forEach(v => {
        +    vertex(v.x, v.y);
        +  });
        +  endShape(CLOSE);
        +}
        diff --git a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        new file mode 100644
        index 0000000000..0a65c143f6
        --- /dev/null
        +++ b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        @@ -0,0 +1,47 @@
        +/*
        + * @name 곡선 위 움직이기
        + * @frame 720,400
        + * @description 이 예제에서, 원들은 y = x^4 곡선을 따라 움직입니다.
        + * 마우스를 클릭하여 새로운 위치로 움직이도록 해보세요.
        + */
        +
        +let beginX = 20.0; // 초기 x 좌표
        +let beginY = 10.0; // 초기 y 좌표
        +let endX = 570.0; // 최종 x 좌표
        +let endY = 320.0; // 최종 y 좌표
        +let distX; // 이동할 X축 거리
        +let distY; // 이동할 Y축 거리
        +let exponent = 4; // 곡선 결정
        +let x = 0.0; // 현재 x 좌표
        +let y = 0.0; // 현재 y 좌표
        +let step = 0.01; // 경로를 따른 각 단계별 움직임 크기
        +let pct = 0.0; // 이동 거리 비율 (0.0과 1.0 사이)
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  distX = endX - beginX;
        +  distY = endY - beginY;
        +}
        +
        +function draw() {
        +  fill(0, 2);
        +  rect(0, 0, width, height);
        +  pct += step;
        +  if (pct < 1.0) {
        +    x = beginX + pct * distX;
        +    y = beginY + pow(pct, exponent) * distY;
        +  }
        +  fill(255);
        +  ellipse(x, y, 20, 20);
        +}
        +
        +function mousePressed() {
        +  pct = 0.0;
        +  beginX = x;
        +  beginY = y;
        +  endX = mouseX;
        +  endY = mouseY;
        +  distX = endX - beginX;
        +  distY = endY - beginY;
        +}
        diff --git a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        new file mode 100644
        index 0000000000..a1854cb62d
        --- /dev/null
        +++ b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        @@ -0,0 +1,35 @@
        +/*
        + * @name 인스턴스화
        + * @description p5 인스턴스를 만들어, 해당 페이지의 모든 변수들이
        + * 전역 범위로서 사용되지 않도록 합니다.
        + */
        +let sketch = function(p) {
        +  let x = 100;
        +  let y = 100;
        +
        +  p.setup = function() {
        +    p.createCanvas(700, 410);
        +  };
        +
        +  p.draw = function() {
        +    p.background(0);
        +    p.fill(255);
        +    p.rect(x, y, 50, 50);
        +  };
        +};
        +
        +let myp5 = new p5(sketch);
        +
        +// "전역 모드(global mode)"와 비교
        +// let x = 100;
        +// let y = 100;
        +
        +// function setup() {
        +//   createCanvas(200,200);
        +// }
        +
        +// function draw() {
        +//   background(0);
        +//   fill(255);
        +//   ellipse(x,y,50,50);
        +// }
        diff --git a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        new file mode 100644
        index 0000000000..b5d6647f6e
        --- /dev/null
        +++ b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        @@ -0,0 +1,92 @@
        +/*
        + * @norender
        + * @name 인스턴스 컨테이너
        + * @description 캔버스에 기본 컨테이너를 지정하거나,
        + * 두번째 인수로 추가될 수 있는 모든 요소를 지정할 수 있습니다. 
        + * HTML의 요소 id나 HTML 노드 그 자체도 지원됩니다.
        + * 컨테이너 DOM 요소를 지정하는 세 가지 다른 방법이 있습니다.
        + * p5로 만들어진 모든 DOM 요소(캔버스, 버튼, div 등)는
        + * p5()함수 호출시 두 번째 인수로 지정된 DOM 요소에 담기게 됩니다.
        + */
        +<!-- pass in the ID of the container element -->
        +<!DOCTYPE html>
        +<head>
        +  <script src='p5.js'></script>
        +</head>
        +<body>
        +  <div id='container'></div>
        +  <script>
        +  let sketch = function(p) {
        +    p.setup = function(){
        +      p.createCanvas(100, 100);
        +      p.background(0);
        +    }
        +  };
        +  new p5(sketch, 'container');
        +  </script>
        +</body>
        +</html>
        +
        +
        +<!-- pass in a pointer to the container element -->
        +<!DOCTYPE html>
        +<head>
        +  <script src='p5.js'></script>
        +</head>
        +<body>
        +  <div id='container'></div>
        +  <script>
        +  let sketch = function(p) {
        +    p.setup = function(){
        +      p.createCanvas(100, 100);
        +      p.background(0);
        +    }
        +  };
        +  new p5(sketch, window.document.getElementById('container'));
        +  </script>
        +</body>
        +</html>
        +
        +
        +<!-- create an element, attach it to the body,
        +and pass in a pointer -->
        +<!DOCTYPE html>
        +<head>
        +  <script src='p5.js'></script>
        +</head>
        +<body>
        +  <script>
        +  let sketch = function(p) {
        +    p.setup = function(){
        +      p.createCanvas(100, 100);
        +      p.background(0);
        +    }
        +  };
        +  let node = document.createElement('div');
        +  window.document.getElementsByTagName('body')[0].appendChild(node);
        +  new p5(sketch, node);
        +  </script>
        +</body>
        +</html>
        +
        +
        +<!-- create an element, pass in a pointer,
        +and attach it to the body -->
        +<!DOCTYPE html>
        +<head>
        +  <script src='p5.js'></script>
        +</head>
        +<body>
        +  <script>
        +  let sketch = function(p) {
        +    p.setup = function(){
        +      p.createCanvas(100, 100);
        +      p.background(0);
        +    }
        +  };
        +  let node = document.createElement('div');
        +  new p5(sketch, node);
        +  window.document.getElementsByTagName('body')[0].appendChild(node);
        +  </script>
        +</body>
        +</html>
        \ No newline at end of file
        diff --git a/src/data/examples/ko/16_Dom/03_Input_Button.js b/src/data/examples/ko/16_Dom/03_Input_Button.js
        new file mode 100644
        index 0000000000..3b7d638f6b
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/03_Input_Button.js
        @@ -0,0 +1,41 @@
        +/*
        + * @name 입력과 버튼
        + * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 텍스트를 입력하고 버튼을 클릭하면 어떤 효과가 캔버스에 나타나는지 보세요.
        + */
        +let input, button, greeting;
        +
        +function setup() {
        +  // create canvas
        +  createCanvas(710, 400);
        +
        +  input = createInput();
        +  input.position(20, 65);
        +
        +  button = createButton('submit');
        +  button.position(input.x + input.width, 65);
        +  button.mousePressed(greet);
        +
        +  greeting = createElement('h2', 'what is your name?');
        +  greeting.position(20, 5);
        +
        +  textAlign(CENTER);
        +  textSize(50);
        +}
        +
        +function greet() {
        +  const name = input.value();
        +  greeting.html('hello ' + name + '!');
        +  input.value('');
        +
        +  for (let i = 0; i < 200; i++) {
        +    push();
        +    fill(random(255), 255, 255);
        +    translate(random(width), random(height));
        +    rotate(random(2 * PI));
        +    text(name, 0, 0);
        +    pop();
        +  }
        +}
        diff --git a/src/data/examples/ko/16_Dom/04_Slider.js b/src/data/examples/ko/16_Dom/04_Slider.js
        new file mode 100644
        index 0000000000..ea060a02c5
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/04_Slider.js
        @@ -0,0 +1,33 @@
        +/*
        + * @name 슬라이더
        + * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 슬라이더를 움직여 배경색의 R,G,B값을 조정해보세요.
        + */
        +let rSlider, gSlider, bSlider;
        +
        +function setup() {
        +  // create canvas
        +  createCanvas(710, 400);
        +  textSize(15);
        +  noStroke();
        +
        +  // create sliders
        +  rSlider = createSlider(0, 255, 100);
        +  rSlider.position(20, 20);
        +  gSlider = createSlider(0, 255, 0);
        +  gSlider.position(20, 50);
        +  bSlider = createSlider(0, 255, 255);
        +  bSlider.position(20, 80);
        +}
        +
        +function draw() {
        +  const r = rSlider.value();
        +  const g = gSlider.value();
        +  const b = bSlider.value();
        +  background(r, g, b);
        +  text('red', rSlider.x * 2 + rSlider.width, 35);
        +  text('green', gSlider.x * 2 + gSlider.width, 65);
        +  text('blue', bSlider.x * 2 + bSlider.width, 95);
        +}
        diff --git a/src/data/examples/ko/16_Dom/07_Modify_DOM.js b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        new file mode 100644
        index 0000000000..a836d20fa1
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        @@ -0,0 +1,55 @@
        +/*
        + * @name DOM 변경
        + * @frame 710,300
        + * @description <p>DOM 요소를 만들고 draw()함수가 매번 호출될 때마다
        + * 그 속성들을 변경해보세요. 여러분의 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.</p>
        + */
        +let dancingWords = [];
        +
        +class DanceSpan {
        +  constructor(element, x, y) {
        +    element.position(x, y);
        +    this.element = element;
        +    this.x = x;
        +    this.y = y;
        +  }
        +
        +  brownian() {
        +    this.x += random(-6, 6);
        +    this.y += random(-6, 6);
        +    this.element.position(this.x, this.y);
        +  }
        +}
        +
        +function setup() {
        +  // 이 단락은 윗 단의 주요 코드 블록의 부록으로 작성되었습니다.
        +  // 아래의 코드들은 요소의 생성과 지정 기능을 각각 구분하고자 합니다.
        +  // 지정된 요소들은 p5js로 생성될 필요가 없으며,
        +  // 일반적인 HTML일 수 있습니다.
        +  createP(
        +    'I learn in this Letter, that Don Peter of Aragon, ' +
        +      ' comes this night to Messina'
        +  ).addClass('text').hide();
        +
        +  // 이 줄은 금방 생성된 '단락'을 받지만,
        +  // 동시에 HTML 페이지상 'text' 클래스를 가진 다른 요소들을 받아오기도 합니다.
        +  const texts = selectAll('.text');
        +
        +  for (let i = 0; i < texts.length; i++) {
        +    const paragraph = texts[i].html();
        +    const words = paragraph.split(' ');
        +    for (let j = 0; j < words.length; j++) {
        +      const spannedWord = createSpan(words[j]);
        +      const dw = new DanceSpan(spannedWord, random(600), random(200));
        +      dancingWords.push(dw);
        +    }
        +  }
        +}
        +
        +function draw() {
        +  for (let i = 0; i < dancingWords.length; i++) {
        +    dancingWords[i].brownian();
        +  }
        +}
        diff --git a/src/data/examples/ko/16_Dom/08_Video.js b/src/data/examples/ko/16_Dom/08_Video.js
        new file mode 100644
        index 0000000000..87841c4410
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/08_Video.js
        @@ -0,0 +1,29 @@
        +/*
        + * @name 비디오
        + * @frame 710,250
        + * @description <p>다양한 형식의 비디오를 불러오고 버튼을 눌러 재생과 일시 정지를 전환합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가하면 됩니다.</span></em></p>
        + */
        +let playing = false;
        +let fingers;
        +let button;
        +
        +function setup() {
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
        +  fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        +  button = createButton('play');
        +  button.mousePressed(toggleVid); // 버튼 리스너 붙이기
        +}
        +
        +// 현재 상태에 따라 비디오를 재생 또는 일시 정지
        +function toggleVid() {
        +  if (playing) {
        +    fingers.pause();
        +    button.html('play');
        +  } else {
        +    fingers.loop();
        +    button.html('pause');
        +  }
        +  playing = !playing;
        +}
        diff --git a/src/data/examples/ko/16_Dom/09_Video_Canvas.js b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        new file mode 100644
        index 0000000000..e46d323968
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        @@ -0,0 +1,27 @@
        +/*
        + * @name 비디오 캔버스
        + * @description <p>비디오를 다양한 형식으로 불러와 캔버스 위에 그릴 수 있도록 합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let fingers;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
        +  fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        +  fingers.hide(); // 기본값으로, 비디오는 별개의 DOM 요소로 나타납니다.
        +  // 이를 우선 숨긴 뒤, 캔버스에 그릴 수 있도록 해볼까요
        +}
        +
        +function draw() {
        +  background(150);
        +  image(fingers, 10, 10); // 캔버스에 비디오 프레임 그리기
        +  filter('GRAY');
        +  image(fingers, 150, 150); // 캔버스에 두번째 사본 그리기
        +}
        +
        +function mousePressed() {
        +  fingers.loop(); // 반복 재생 설정 및 비디오 재생
        +}
        diff --git a/src/data/examples/ko/16_Dom/10_Video_Pixels.js b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        new file mode 100644
        index 0000000000..10bd28beef
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        @@ -0,0 +1,33 @@
        +/*
        + * @name 비디오 픽셀
        + * @frame 320,240
        + * @description <p>비디오를 불러와 픽셀을 조정하고 캔버스에 그려보세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let fingers;
        +
        +function setup() {
        +  createCanvas(320, 240);
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
        +  fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        +  fingers.loop();
        +  fingers.hide();
        +  noStroke();
        +  fill(0);
        +}
        +
        +function draw() {
        +  background(255);
        +  fingers.loadPixels();
        +  const stepSize = round(constrain(mouseX / 8, 6, 32));
        +  for (let y = 0; y < height; y += stepSize) {
        +    for (let x = 0; x < width; x += stepSize) {
        +      const i = y * width + x;
        +      const darkness = (255 - fingers.pixels[i * 4]) / 255;
        +      const radius = stepSize * darkness;
        +      ellipse(x, y, radius, radius);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/16_Dom/11_Capture.js b/src/data/examples/ko/16_Dom/11_Capture.js
        new file mode 100644
        index 0000000000..d3ad38b0e3
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/11_Capture.js
        @@ -0,0 +1,25 @@
        +/*
        + * @name 실시간 비디오 화면
        + * @frame 710,240
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p><br><br>
        + * 웹캠을 통해 보여지는 실시간 비디오 화면을 캔버스 위에 그릴 수 있습니다.
        + * 반전 효과 필터도 적용할 수 있습니다.
        + * 실시간 비디오 화면은 기본값으로 캔버스 위에 나타납니다.
        + * 아래의 코드 중 capture.hide()의 주석 처리(//)를 해제하면 이 실시간 비디오 화면을 숨길 수 있습니다. 
        + */
        +let capture;
        +
        +function setup() {
        +  createCanvas(390, 240);
        +  capture = createCapture(VIDEO);
        +  capture.size(320, 240);
        +  //capture.hide();
        +}
        +
        +function draw() {
        +  background(255);
        +  image(capture, 0, 0, 320, 240);
        +  filter('INVERT');
        +}
        diff --git a/src/data/examples/ko/16_Dom/12_Drop.js b/src/data/examples/ko/16_Dom/12_Drop.js
        new file mode 100644
        index 0000000000..c3541c6d1f
        --- /dev/null
        +++ b/src/data/examples/ko/16_Dom/12_Drop.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 드롭 기능
        + * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 이미지 파일을 캔버스에 드래그 & 드롭하여 화면에 보이는지 확인해보세요.
        + */
        +
        +function setup() {
        +  // 캔버스 생성
        +  const c = createCanvas(710, 400);
        +  background(100);
        +  // 캔버스에 이미지 파일이 드롭될 때 이벤트 추가
        +  c.drop(gotFile);
        +}
        +
        +function draw() {
        +  fill(255);
        +  noStroke();
        +  textSize(24);
        +  textAlign(CENTER);
        +  text('Drag an image file onto the canvas.', width / 2, height / 2);
        +  noLoop();
        +}
        +
        +function gotFile(file) {
        +  // 드롭된 파일이 이미지 파일이라면,
        +  if (file.type === 'image') {
        +    // 이미지 DOM 요소를 생성하되, 화면엔 띄우지 않는다.
        +    const img = createImg(file.data).hide();
        +    // 이미지를 캔버스에 그린다.
        +    image(img, 0, 0, width, height);
        +  } else {
        +    console.log('Not an image file!');
        +  }
        +}
        diff --git a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        new file mode 100644
        index 0000000000..aa89265d1d
        --- /dev/null
        +++ b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        @@ -0,0 +1,15 @@
        +/*
        + * @name 연속된 선
        + * @description 마우스를 클릭하고 드래그하여 선을 그려보세요.
        + */
        +function setup() {
        +  createCanvas(710, 400);
        +  background(102);ㅌ
        +}
        +
        +function draw() {
        +  stroke(255);
        +  if (mouseIsPressed === true) {
        +    line(mouseX, mouseY, pmouseX, pmouseY);
        +  }
        +}
        diff --git a/src/data/examples/ko/17_Drawing/01_Pattern.js b/src/data/examples/ko/17_Drawing/01_Pattern.js
        new file mode 100644
        index 0000000000..e1a1f4ae7a
        --- /dev/null
        +++ b/src/data/examples/ko/17_Drawing/01_Pattern.js
        @@ -0,0 +1,26 @@
        +/*
        + * @name 패턴들
        + * @description 캔버스 위로 마우스를 움직여 드로잉할 수 있는 소프트웨어 툴입니다.
        + * 이 때, 드로잉은 마우스의 속도에 반응합니다.
        + */
        +function setup() {
        +  createCanvas(710, 400);
        +  background(102);
        +}
        +
        +function draw() {
        +  // variableEllipse()메소드를 호출하고, 여기에
        +  // 마우스의 현재 및 이전 위치를 담은 매개 변수를 보냅니다.
        +  variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
        +}
        +
        +// 이 간단한 메소드 variableEllipse()는 이 프로그램을 위해
        +// 작성되었습니다. 메소드는 마우스의 속도를 계산하는데,
        +// 마우스가 천천히 움직이면 작은 타원을,
        +// 마우스가 빨리 움직이면 큰 타원을 그립니다.
        +
        +function variableEllipse(x, y, px, py) {
        +  let speed = abs(x - px) + abs(y - py);
        +  stroke(speed);
        +  ellipse(x, y, speed, speed);
        +}
        diff --git a/src/data/examples/ko/17_Drawing/02_Pulses.js b/src/data/examples/ko/17_Drawing/02_Pulses.js
        new file mode 100644
        index 0000000000..845138e69f
        --- /dev/null
        +++ b/src/data/examples/ko/17_Drawing/02_Pulses.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 율동
        + * @description 드로잉 스포트웨어는 특정 리듬이나, 그려진 제스쳐로부터 독립된 규칙을 따를 수 있습니다.
        + * 이 예제의 경우, 협업 드로잉으로도 볼 수 있습니다.
        + * 사용자가 이미지의 일부를 조정하면 소프트웨어가 다른 일부를 조정하는 식입니다.
        + */
        +let angle = 0;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  background(102);
        +  noStroke();
        +  fill(0, 102);
        +}
        +
        +function draw() {
        +  // 마우스 버튼이 눌렸을 때만 그리기
        +  if (mouseIsPressed === true) {
        +    angle += 5;
        +    let val = cos(radians(angle)) * 12.0;
        +    for (let a = 0; a < 360; a += 75) {
        +      let xoff = cos(radians(a)) * val;
        +      let yoff = sin(radians(a)) * val;
        +      fill(0);
        +      ellipse(mouseX + xoff, mouseY + yoff, val, val);
        +    }
        +    fill(255);
        +    ellipse(mouseX, mouseY, 2, 2);
        +  }
        +}
        diff --git a/src/data/examples/ko/18_Transform/00_Translate.js b/src/data/examples/ko/18_Transform/00_Translate.js
        new file mode 100644
        index 0000000000..8be22e1378
        --- /dev/null
        +++ b/src/data/examples/ko/18_Transform/00_Translate.js
        @@ -0,0 +1,39 @@
        +/*
        + * @name 치환(Translate)
        + * @description translate() 함수는 객체를 화면 내 어떤 위치로든 이동하게 합니다.
        + * 그 첫 번째 매개 변수는 x축의 오프셋(offset)을,
        + * 두 번째 매개 변수는 y축의 오프셋을 지정합니다.
        + * 이 예제는 이러한 치환들이 축적되는 것을 보여줍니다.
        + */
        +
        +let x = 0;
        +let y = 0;
        +let dim = 80.0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(102);
        +  // x값을 증가시켜 움직이게 만들기
        +  x = x + 0.8;
        +  // 도형이 캔버스 밖으로 나가면, 위치를 리셋한다.
        +  if (x > width + dim) {
        +    x = -dim;
        +  }
        +
        +  // rect 명령어는 원점을 중심점으로 삼는 도형을 그리지만,
        +  // translate은 이를 새로운 x와 y 위치로 옮깁니다.
        +  translate(x, height / 2 - dim / 2);
        +  fill(255);
        +  rect(-dim / 2, -dim / 2, dim, dim);
        +
        +  // translate(치환)은 축적됩니다. 이 rect가 다른 rect와
        +  // 동일한 x축값 매개 변수를 가졌음에도
        +  // 두 배로 빠르게 움직이는 걸 볼 수 있습니다.
        +  translate(x, dim);
        +  fill(0);
        +  rect(-dim / 2, -dim / 2, dim, dim);
        +}
        diff --git a/src/data/examples/ko/18_Transform/01_Scale.js b/src/data/examples/ko/18_Transform/01_Scale.js
        new file mode 100644
        index 0000000000..b417116c73
        --- /dev/null
        +++ b/src/data/examples/ko/18_Transform/01_Scale.js
        @@ -0,0 +1,45 @@
        +/*
        + * @name 크기 조정(Scale)
        + * @description scale()함수의 매개 변수는 10진수 백분율로 표현됩니다.
        + * 예를 들어, scale(2.0) 메소드 호출은 도형의 차원을 200 퍼센트 증가시킵니다.
        + * 오브젝트의 크기는 항상 원점을 기준으로 조정됩니다. 
        + * 이 예제는 그러한 변형이 축적되는 양상과, 순서에 따라 scale과 translate이
        + * 상호작용하는 것을 보여줍니다.
        + */
        +
        +let a = 0.0;
        +let s = 0.0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  //Draw all rectangles from their center as opposed to
        +  // the default upper left corner
        +  rectMode(CENTER);
        +}
        +
        +function draw() {
        +  background(102);
        +
        +  //Slowly increase 'a' and then animate 's' with
        +  //a smooth cyclical motion by finding the cosine of 'a'
        +  a = a + 0.04;
        +  s = cos(a) * 2;
        +
        +  //Translate our rectangle from the origin to the middle of
        +  //the canvas, then scale it with 's'
        +  translate(width / 2, height / 2);
        +  scale(s);
        +  fill(51);
        +  rect(0, 0, 50, 50);
        +
        +  //Translate and scale are accumulating, so this translate
        +  //moves the second rectangle further right than the first
        +  //and the scale is getting doubled. Note that cosine is
        +  //making 's' both negative and positive, thus it cycles
        +  //from left to right.
        +  translate(75, 0);
        +  fill(255);
        +  scale(s);
        +  rect(0, 0, 50, 50);
        +}
        diff --git a/src/data/examples/ko/18_Transform/02_Rotate.js b/src/data/examples/ko/18_Transform/02_Rotate.js
        new file mode 100644
        index 0000000000..d25d8de8f9
        --- /dev/null
        +++ b/src/data/examples/ko/18_Transform/02_Rotate.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 회전(Rotate)
        + * @description Z축을 기준으로 사각형 회전시킵니다.
        + * 원하는 결과를 얻기 위해, 0부터 PI*2(즉, TWO_PI, 약 6.28)에 해당하는,
        + * rotate 함수 속 각도 매개 변수를 보냅니다.
        + * 각도를 도(0-360) 단위로 표현하고 싶다면, radians() 메소드를 통해 변환하면 됩니다.
        + * 예: scale(radians(90))은 선언문 scale(PI/2)과 동일합니다.
        + * 이 예제에서, 모든 짝수 초마다 jitter(떨림)가 회전에 더해집니다.
        + * 홀수 초에는 마지막 jitter값으로 결정된 속도에 따라
        + * 시계 방향 또는 반시계 방향으로 회전합니다.
        + */
        +
        +let angle = 0.0;
        +let jitter = 0.0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  fill(255);
        +  //중심으로부터 사각형을 그리고,
        +  //사각형이 중심을 기준으로 회전하도록 만들기
        +  rectMode(CENTER);
        +}
        +
        +function draw() {
        +  background(51);
        +
        +  // 짝수 초(0, 2, 4, 6...)동안 회전에
        +  // jitter(떨림) 더하기
        +  if (second() % 2 === 0) {
        +    jitter = random(-0.1, 0.1);
        +  }
        +  // 가장 마지막 jitter값을 사용해 각도값 증가시키기
        +  angle = angle + jitter;
        +  // 떨림이 없는 경우, 코싸인을 사용해 부드러운 시계 방향 및 반시계 방향 모션 받기
        +  let c = cos(angle);
        +  //도형을 캔버스의 중앙으로 이동시키기
        +  translate(width / 2, height / 2);
        +  //최종 회전 적용하기
        +  rotate(c);
        +  rect(0, 0, 180, 180);
        +}
        diff --git a/src/data/examples/ko/18_Transform/03_Arm.js b/src/data/examples/ko/18_Transform/03_Arm.js
        new file mode 100644
        index 0000000000..f1e4e4db91
        --- /dev/null
        +++ b/src/data/examples/ko/18_Transform/03_Arm.js
        @@ -0,0 +1,47 @@
        +/*
        + * @name 팔모양
        + * @description 이 예제는 변환 행렬을 사용하여 팔모양을 만듭니다.
        + * 각 선분의 각도는 mouseX 및 mouseY 위치로 조정됩니다.
        + * 첫 번째 선분에 적용된 변환은 두 번째 선분에도 적용됩니다.
        + * 두 선분 모두 동일한 push() 및 pop() 행렬 그룹에 속하기 때문입니다.
        + */
        +
        +let x, y;
        +let angle1 = 0.0;
        +let angle2 = 0.0;
        +let segLength = 100;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  strokeWeight(30);
        +
        +  //반 투명한 선 그리기
        +  stroke(255, 160);
        +
        +  //팔의 "어깨" 위치를 캔버스 중앙에 위치시키기
        +  x = width * 0.5;
        +  y = height * 0.5;
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  //마우스 위치에 따라 선분의 각도 바꾸기
        +  angle1 = (mouseX / float(width) - 0.5) * -TWO_PI;
        +  angle2 = (mouseY / float(height) - 0.5) * PI;
        +
        +  // push와 pop을 사용해 변환을 "contain"하기
        +  // 사용자 정의 함수를 사용해 선분을 그려도
        +  // 변환 내용이 축적되는 걸 볼 수 있습니다.
        +  push();
        +  segment(x, y, angle1);
        +  segment(segLength, 0, angle2);
        +  pop();
        +}
        +
        +// 선분을 그리기 위한 사용자 정의 함수
        +function segment(x, y, a) {
        +  translate(x, y);
        +  rotate(a);
        +  line(0, 0, segLength, 0);
        +}
        diff --git a/src/data/examples/ko/19_Typography/00_Letters.js b/src/data/examples/ko/19_Typography/00_Letters.js
        new file mode 100644
        index 0000000000..f9084ab958
        --- /dev/null
        +++ b/src/data/examples/ko/19_Typography/00_Letters.js
        @@ -0,0 +1,64 @@
        +/*
        + * @name 글자
        + * @description 폰트를 불러와 글자 속성을 설정하면, 화면에 글자를 그릴 수 있습니다.
        + * 이 예제에서는 for 반복문과 유니코드 참조 번호를 사용하여,
        + * 그리드 속 글자들로 캔버스를 자동으로 채웁니다.
        + * 이 중, 모음들만 선택되어 특정 색상이 부여됩니다.
        + */
        +let font,
        +  fontsize = 32;
        +
        +function preload() {
        +  // setup()과 draw()를 호출하기에 앞서,
        +  // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
        +  font = loadFont('assets/SourceSansPro-Regular.otf');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 텍스트 속성 설정
        +  textFont(font);
        +  textSize(fontsize);
        +  textAlign(CENTER, CENTER);
        +}
        +
        +function draw() {
        +  background(160);
        +
        +  // 글자 간, 그리고 글자와 좌측 및 상단 간의 margin(여백) 설정
        +  let gap = 52;
        +  let margin = 10;
        +  translate(margin * 4, margin * 4);
        +
        +  // 원하는 글자에서 시작하도록 카운터 설정
        +  // 이 예제에서는 유니코드 35, 즉 # 기호입니다.
        +  let counter = 35;
        +
        +  // 캔버스에 공간이 확보되는 한 반복하기
        +  for (let y = 0; y < height - gap; y += gap) {
        +    for (let x = 0; x < width - gap; x += gap) {
        +      // 카운터를 사용해 유니코드 번호로 개별 글자를 검색
        +      let letter = char(counter);
        +
        +      // 모음과 기타 글자들에 각각 다른 색상 더하기
        +      if (
        +        letter === 'A' ||
        +        letter === 'E' ||
        +        letter === 'I' ||
        +        letter === 'O' ||
        +        letter === 'U'
        +      ) {
        +        fill('#ed225d');
        +      } else {
        +        fill(255);
        +      }
        +
        +      // 화면에 글자 그리기
        +      text(letter, x, y);
        +
        +      // 카운터 증가시키기
        +      counter++;
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/19_Typography/01_Words.js b/src/data/examples/ko/19_Typography/01_Words.js
        new file mode 100644
        index 0000000000..725cb82229
        --- /dev/null
        +++ b/src/data/examples/ko/19_Typography/01_Words.js
        @@ -0,0 +1,58 @@
        +/*
        + * @name 단어
        + * @description text()함수는 화면에 단어를 쓸 때 사용됩니다.
        + * textAlign()함수로 단어들을 왼쪽, 가운데, 또는 오른쪽 정렬할 수 있으며, 
        + * 도형과 마찬가지로, 단어들 역시 fill()로 그 색을 채울 수 있습니다.
        + */
        +let font,
        +  fontsize = 40;
        +
        +function preload() {
        +  // setup()과 draw()를 호출하기에 앞서,
        +  // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
        +  font = loadFont('assets/SourceSansPro-Regular.otf');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 텍스트 속성 설정
        +  textFont(font);
        +  textSize(fontsize);
        +  textAlign(CENTER, CENTER);
        +}
        +
        +function draw() {
        +  background(160);
        +
        +  // 텍스트를 오른쪽 정렬하고
        +  // 캔버스의 좌측 1/3 영역에서 drawWords() 실행하기
        +  textAlign(RIGHT);
        +  drawWords(width * 0.25);
        +
        +  // 텍스트를 가운데 정렬하고
        +  // 캔버스의 가운데 영역에서 drawWords() 실행하기
        +  textAlign(CENTER);
        +  drawWords(width * 0.5);
        +
        +  // 텍스트를 왼쪽 정렬하고
        +  // 캔버스의 우측 1/3 영역에서 drawWords() 실행하기
        +  textAlign(LEFT);
        +  drawWords(width * 0.75);
        +}
        +
        +function drawWords(x) {
        +  // text() 함수에는 세 개의 매개 변수가 필요합니다:
        +  // 그려질 텍스트, 가로 위치, 그리고 세로 위치
        +  fill(0);
        +  text('ichi', x, 80);
        +
        +  fill(65);
        +  text('ni', x, 150);
        +
        +  fill(190);
        +  text('san', x, 220);
        +
        +  fill(255);
        +  text('shi', x, 290);
        +}
        diff --git a/src/data/examples/ko/20_3D/00_geometries.js b/src/data/examples/ko/20_3D/00_geometries.js
        new file mode 100644
        index 0000000000..59a9b03459
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/00_geometries.js
        @@ -0,0 +1,60 @@
        +/*
        + * @name 기하
        + * @description 현재 p5에는 여섯 개의 3D 기초 조형이 있습니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +}
        +
        +function draw() {
        +  background(250);
        +
        +  translate(-240, -100, 0);
        +  normalMaterial();
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  plane(70);
        +  pop();
        +
        +  translate(240, 0, 0);
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  box(70, 70, 70);
        +  pop();
        +
        +  translate(240, 0, 0);
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  cylinder(70, 70);
        +  pop();
        +
        +  translate(-240 * 2, 200, 0);
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  cone(70, 70);
        +  pop();
        +
        +  translate(240, 0, 0);
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  torus(70, 20);
        +  pop();
        +
        +  translate(240, 0, 0);
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  sphere(70);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        new file mode 100644
        index 0000000000..f92bbc0423
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        @@ -0,0 +1,28 @@
        +/*
        + * @name 3D속 싸인 코싸인
        + * @description 싸인, 코싸인, 그리고 push / pop 함수는 3D에도 적용됩니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +}
        +
        +function draw() {
        +  background(250);
        +  rotateY(frameCount * 0.01);
        +
        +  for (let j = 0; j < 5; j++) {
        +    push();
        +    for (let i = 0; i < 80; i++) {
        +      translate(
        +        sin(frameCount * 0.001 + j) * 100,
        +        sin(frameCount * 0.001 + j) * 100,
        +        i * 0.1
        +      );
        +      rotateZ(frameCount * 0.002);
        +      push();
        +      sphere(8, 6, 4);
        +      pop();
        +    }
        +    pop();
        +  }
        +}
        diff --git a/src/data/examples/ko/20_3D/02_multiple_lights.js b/src/data/examples/ko/20_3D/02_multiple_lights.js
        new file mode 100644
        index 0000000000..1491c79a43
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/02_multiple_lights.js
        @@ -0,0 +1,30 @@
        +/*
        + * @name 복수의 조명들
        + * @description 한 스케치 위에 여러 종류의 조명을 사용할 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let locX = mouseX - height / 2;
        +  let locY = mouseY - width / 2;
        +
        +  ambientLight(50);
        +  directionalLight(255, 0, 0, 0.25, 0.25, 0);
        +  pointLight(0, 0, 255, locX, locY, 250);
        +
        +  push();
        +  translate(-width / 4, 0, 0);
        +  rotateZ(frameCount * 0.02);
        +  rotateX(frameCount * 0.02);
        +  specularMaterial(250);
        +  box(100, 100, 100);
        +  pop();
        +
        +  translate(width / 4, 0, 0);
        +  ambientMaterial(250);
        +  sphere(120, 64);
        +}
        diff --git a/src/data/examples/ko/20_3D/03_materials.js b/src/data/examples/ko/20_3D/03_materials.js
        new file mode 100644
        index 0000000000..571219eee0
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/03_materials.js
        @@ -0,0 +1,65 @@
        +/*
        + * @name 재질(Materials)
        + * @description 지원되는 재질은 다섯 가지 입니다.
        + * 각각은 조명에 다르게 반응합니다.
        + * 마우스를 움직여 빛의 위치를 바꿔보세요.
        + */
        +let img;
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +  img = loadImage('assets/cat.jpg');
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  let locX = mouseX - height / 2;
        +  let locY = mouseY - width / 2;
        +
        +  ambientLight(60, 60, 60);
        +  pointLight(255, 255, 255, locX, locY, 100);
        +
        +  push();
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  texture(img);
        +  box(80);
        +  pop();
        +
        +  push();
        +  translate(-width / 4, -height / 4, 0);
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  fill(250, 0, 0);
        +  torus(80, 20, 64, 64);
        +  pop();
        +
        +  push();
        +  translate(width / 4, -height / 4, 0);
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  normalMaterial();
        +  torus(80, 20, 64, 64);
        +  pop();
        +
        +  push();
        +  translate(-width / 4, height / 4, 0);
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  ambientMaterial(250);
        +  torus(80, 20, 64, 64);
        +  pop();
        +
        +  push();
        +  translate(width / 4, height / 4, 0);
        +  rotateZ(frameCount * 0.01);
        +  rotateX(frameCount * 0.01);
        +  rotateY(frameCount * 0.01);
        +  specularMaterial(250);
        +  torus(80, 20, 64, 64);
        +  pop();
        +}
        diff --git a/src/data/examples/ko/20_3D/04_textures.js b/src/data/examples/ko/20_3D/04_textures.js
        new file mode 100644
        index 0000000000..a09c9d2128
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/04_textures.js
        @@ -0,0 +1,40 @@
        +/*
        + * @name 텍스쳐
        + * @description 이미지와 비디오가 텍스쳐를 지원합니다.
        + */
        +// 비디오 출처: https://vimeo.com/90312869
        +let img;
        +let vid;
        +let theta = 0;
        +
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +
        +  img = loadImage('assets/cat.jpg');
        +  vid = createVideo(['assets/360video_256crop_v2.mp4']);
        +  vid.elt.muted = true;
        +  vid.loop();
        +  vid.hide();
        +}
        +
        +function draw() {
        +  background(250);
        +  translate(-220, 0, 0);
        +  push();
        +  rotateZ(theta * mouseX * 0.001);
        +  rotateX(theta * mouseX * 0.001);
        +  rotateY(theta * mouseX * 0.001);
        +  //이미지를 텍스쳐로 전달하기
        +  texture(vid);
        +  sphere(150);
        +  pop();
        +  translate(440, 0, 0);
        +  push();
        +  rotateZ(theta * 0.1);
        +  rotateX(theta * 0.1);
        +  rotateY(theta * 0.1);
        +  texture(img);
        +  box(100, 100, 100);
        +  pop();
        +  theta += 0.05;
        +}
        diff --git a/src/data/examples/ko/20_3D/07_orbit_control.js b/src/data/examples/ko/20_3D/07_orbit_control.js
        new file mode 100644
        index 0000000000..7c45043100
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/07_orbit_control.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 궤도 제어
        + * @description 궤도 제어(Orbit Control)를 사용해 월드를 드래그하거나 움직일 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +}
        +
        +function draw() {
        +  background(250);
        +  let radius = width * 1.5;
        +
        +  //월드를 움직이도록 드래그
        +  orbitControl();
        +
        +  normalMaterial();
        +  translate(0, 0, -600);
        +  for (let i = 0; i <= 12; i++) {
        +    for (let j = 0; j <= 12; j++) {
        +      push();
        +      let a = (j / 12) * PI;
        +      let b = (i / 12) * PI;
        +      translate(
        +        sin(2 * a) * radius * sin(b),
        +        (cos(b) * radius) / 2,
        +        cos(2 * a) * radius * sin(b)
        +      );
        +      if (j % 2 === 0) {
        +        cone(30, 30);
        +      } else {
        +        box(30, 30, 30);
        +      }
        +      pop();
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/21_Input/00_Clock.js b/src/data/examples/ko/21_Input/00_Clock.js
        new file mode 100644
        index 0000000000..7d9b53c902
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/00_Clock.js
        @@ -0,0 +1,62 @@
        +/*
        + * @name 시계
        + * @description second(), minute(), 그리고 hour()함수를 사용하여
        + * 현재 시간을 읽어올 수 있습니다.
        + * 이 예제에서는 sin()과 cos()값이 시침, 분침, 초침의 위치를 정합니다.
        + */
        +let cx, cy;
        +let secondsRadius;
        +let minutesRadius;
        +let hoursRadius;
        +let clockDiameter;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  stroke(255);
        +
        +  let radius = min(width, height) / 2;
        +  secondsRadius = radius * 0.71;
        +  minutesRadius = radius * 0.6;
        +  hoursRadius = radius * 0.5;
        +  clockDiameter = radius * 1.7;
        +
        +  cx = width / 2;
        +  cy = height / 2;
        +}
        +
        +function draw() {
        +  background(230);
        +
        +  // 시계 배경 그리기
        +  noStroke();
        +  fill(244, 122, 158);
        +  ellipse(cx, cy, clockDiameter + 25, clockDiameter + 25);
        +  fill(237, 34, 93);
        +  ellipse(cx, cy, clockDiameter, clockDiameter);
        +
        +  // sin()과 cos()의 각도는 3시 정각에서 시작;
        +  // HALF_PI를 뺄셈하여 상단에서부터 시작하도록 설정
        +  let s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
        +  let m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI;
        +  let h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI;
        +
        +  // 시계침들 그리기
        +  stroke(255);
        +  strokeWeight(1);
        +  line(cx, cy, cx + cos(s) * secondsRadius, cy + sin(s) * secondsRadius);
        +  strokeWeight(2);
        +  line(cx, cy, cx + cos(m) * minutesRadius, cy + sin(m) * minutesRadius);
        +  strokeWeight(4);
        +  line(cx, cy, cx + cos(h) * hoursRadius, cy + sin(h) * hoursRadius);
        +
        +  // 분침 그리기
        +  strokeWeight(2);
        +  beginShape(POINTS);
        +  for (let a = 0; a < 360; a += 6) {
        +    let angle = radians(a);
        +    let x = cx + cos(angle) * secondsRadius;
        +    let y = cy + sin(angle) * secondsRadius;
        +    vertex(x, y);
        +  }
        +  endShape();
        +}
        diff --git a/src/data/examples/ko/21_Input/01_Constrain.js b/src/data/examples/ko/21_Input/01_Constrain.js
        new file mode 100644
        index 0000000000..5aff15a043
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/01_Constrain.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 제한
        + * @description 화면 위로 마우스를 움직이면 동그라미가 움직이지만,
        + * 박스 안에서만 움직이도록 제한되어 있습니다.
        + */
        +let mx = 1;
        +let my = 1;
        +let easing = 0.05;
        +let radius = 24;
        +let edge = 100;
        +let inner = edge + radius;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  ellipseMode(RADIUS);
        +  rectMode(CORNERS);
        +}
        +
        +function draw() {
        +  background(230);
        +
        +  if (abs(mouseX - mx) > 0.1) {
        +    mx = mx + (mouseX - mx) * easing;
        +  }
        +  if (abs(mouseY - my) > 0.1) {
        +    my = my + (mouseY - my) * easing;
        +  }
        +
        +  mx = constrain(mx, inner, width - inner);
        +  my = constrain(my, inner, height - inner);
        +  fill(237, 34, 93);
        +  rect(edge, edge, width - edge, height - edge);
        +  fill(255);
        +  ellipse(mx, my, radius, radius);
        +}
        diff --git a/src/data/examples/ko/21_Input/02_Easing.js b/src/data/examples/ko/21_Input/02_Easing.js
        new file mode 100644
        index 0000000000..d84bae3c2a
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/02_Easing.js
        @@ -0,0 +1,28 @@
        +/*
        + * @name 이징(Easing)
        + * @description 화면 위로 마우스 커서를 움직이면 기호가 따라옵니다.
        + * 애니메이션의 매 프레임 사이에, 프로그램은 기호와 마우스 커서 간의 거리를 계산합니다.
        + * 만약 그 거리가 1픽셀보다 크다면, 기호는 현재 위치로부터 커서의 위치를 향해 
        + * 일정 거리(0.05)를 이동합니다.
        + */
        +let x = 1;
        +let y = 1;
        +let easing = 0.05;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(237, 34, 93);
        +  let targetX = mouseX;
        +  let dx = targetX - x;
        +  x += dx * easing;
        +
        +  let targetY = mouseY;
        +  let dy = targetY - y;
        +  y += dy * easing;
        +
        +  ellipse(x, y, 66, 66);
        +}
        diff --git a/src/data/examples/ko/21_Input/03_Keyboard.js b/src/data/examples/ko/21_Input/03_Keyboard.js
        new file mode 100644
        index 0000000000..643e11c539
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/03_Keyboard.js
        @@ -0,0 +1,38 @@
        +/*
        + * @name 키보드
        + * @description 이미지를 클릭하여 포커스를 주고
        + * 키보드 입력을 통해 화면에 모양을 만듭니다.
        + * 각 자판은 고유의 식별 번호를 갖습니다. 
        + * 이 번호들은 도형의 화면 상 위치를 정합니다.
        + */
        +let rectWidth;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  background(230);
        +  rectWidth = width / 4;
        +}
        +
        +function draw() {
        +  // draw()를 여기에 작성하여 키보드 입력을 기다리는 동안 반복되게 합니다.
        +}
        +
        +function keyPressed() {
        +  let keyIndex = -1;
        +  if (key >= 'a' && key <= 'z') {
        +    keyIndex = key.charCodeAt(0) - 'a'.charCodeAt(0);
        +  }
        +  if (keyIndex === -1) {
        +    // 글자 자판이 아닐 경우, 화면을 비웁니다.
        +    background(230);
        +  } else {
        +    // 글자 자판일 경우, 사각면을 채웁니다.
        +    randFill_r = Math.floor(Math.random() * 255 + 1);
        +    randFill_g = Math.floor(Math.random() * 255 + 1);
        +    randFill_b = Math.floor(Math.random() * 255 + 1);
        +    fill(randFill_r, randFill_g, randFill_b);
        +    let x = map(keyIndex, 0, 25, 0, width - rectWidth);
        +    rect(x, 0, rectWidth, height);
        +  }
        +}
        diff --git a/src/data/examples/ko/21_Input/04_Mouse1D.js b/src/data/examples/ko/21_Input/04_Mouse1D.js
        new file mode 100644
        index 0000000000..0ca0d20e8e
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/04_Mouse1D.js
        @@ -0,0 +1,23 @@
        +/*
        + * @name 1D 마우스
        + * @description 마우스를 좌우로 움직여 균형점을 이동해보세요. 
        + * mouseX 변수로 사각형의 크기와 색상 모두를 조정할 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  rectMode(CENTER);
        +}
        +
        +function draw() {
        +  background(230);
        +
        +  let r1 = map(mouseX, 0, width, 0, height);
        +  let r2 = height - r1;
        +
        +  fill(237, 34, 93, r1);
        +  rect(width / 2 + r1 / 2, height / 2, r1, r1);
        +
        +  fill(237, 34, 93, r2);
        +  rect(width / 2 - r2 / 2, height / 2, r2, r2);
        +}
        diff --git a/src/data/examples/ko/21_Input/05_Mouse2D.js b/src/data/examples/ko/21_Input/05_Mouse2D.js
        new file mode 100644
        index 0000000000..72f1513be4
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/05_Mouse2D.js
        @@ -0,0 +1,19 @@
        +/*
        + * @name 2D 마우스
        + * @description 마우스를 움직이면 각 상자의 위치와 크기가 바뀝니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  rectMode(CENTER);
        +}
        +
        +function draw() {
        +  background(230);
        +  fill(244, 122, 158);
        +  rect(mouseX, height / 2, mouseY / 2 + 10, mouseY / 2 + 10);
        +  fill(237, 34, 93);
        +  let inverseX = width - mouseX;
        +  let inverseY = height - mouseY;
        +  rect(inverseX, height / 2, inverseY / 2 + 10, inverseY / 2 + 10);
        +}
        diff --git a/src/data/examples/ko/21_Input/06_MouseIsPressed.js b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        new file mode 100644
        index 0000000000..b29e306fec
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        @@ -0,0 +1,20 @@
        +/*
        + * @name 마우스 버튼
        + * @description 마우스를 움직여 도형의 위치를 바꿔보세요.
        + * 마우스 버튼을 눌러 색을 반전시킬 수 있습니다.
        + */
        +function setup() {
        +  createCanvas(720, 400);
        +  background(230);
        +  strokeWeight(2);
        +}
        +
        +function draw() {
        +  if (mouseIsPressed) {
        +    stroke(255);
        +  } else {
        +    stroke(237, 34, 93);
        +  }
        +  line(mouseX - 66, mouseY, mouseX + 66, mouseY);
        +  line(mouseX, mouseY - 66, mouseX, mouseY + 66);
        +}
        diff --git a/src/data/examples/ko/21_Input/07_Mouse_Functions.js b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        new file mode 100644
        index 0000000000..c64853119c
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        @@ -0,0 +1,66 @@
        +/*
        + * @name 마우스 기능
        + * @description 상자를 클릭한 뒤 화면 위에서 드래그 해보세요.
        + */
        +let bx;
        +let by;
        +let boxSize = 75;
        +let overBox = false;
        +let locked = false;
        +let xOffset = 0.0;
        +let yOffset = 0.0;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  bx = width / 2.0;
        +  by = height / 2.0;
        +  rectMode(RADIUS);
        +  strokeWeight(2);
        +}
        +
        +function draw() {
        +  background(237, 34, 93);
        +
        +  // 상자 위에 커서가 있는지를 테스트
        +  if (
        +    mouseX > bx - boxSize &&
        +    mouseX < bx + boxSize &&
        +    mouseY > by - boxSize &&
        +    mouseY < by + boxSize
        +  ) {
        +    overBox = true;
        +    if (!locked) {
        +      stroke(255);
        +      fill(244, 122, 158);
        +    }
        +  } else {
        +    stroke(156, 39, 176);
        +    fill(244, 122, 158);
        +    overBox = false;
        +  }
        +
        +  // 상자 그리기
        +  rect(bx, by, boxSize, boxSize);
        +}
        +
        +function mousePressed() {
        +  if (overBox) {
        +    locked = true;
        +    fill(255, 255, 255);
        +  } else {
        +    locked = false;
        +  }
        +  xOffset = mouseX - bx;
        +  yOffset = mouseY - by;
        +}
        +
        +function mouseDragged() {
        +  if (locked) {
        +    bx = mouseX - xOffset;
        +    by = mouseY - yOffset;
        +  }
        +}
        +
        +function mouseReleased() {
        +  locked = false;
        +}
        diff --git a/src/data/examples/ko/21_Input/08_Mouse_Signals.js b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        new file mode 100644
        index 0000000000..694d9e8aae
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        @@ -0,0 +1,51 @@
        +/*
        + * @name 마우스 신호
        + * @description 마우스를 움직이고 클릭하여 신호를 만들어보세요.
        + * 상단의 행은 "mouseX", 가운데 행은 "mouseY",
        + * 하단의 행은 "mouseIsPressed"에 대한 신호입니다.
        +  */
        +let xvals = [];
        +let yvals = [];
        +let bvals = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  strokeWeight(2);
        +}
        +
        +function draw() {
        +  background(237, 34, 93);
        +
        +  for (let i = 1; i < width; i++) {
        +    xvals[i - 1] = xvals[i];
        +    yvals[i - 1] = yvals[i];
        +    bvals[i - 1] = bvals[i];
        +  }
        +  // 배열의 마지막에 새로운 값들 더하기
        +  xvals[width - 1] = mouseX;
        +  yvals[width - 1] = mouseY;
        +
        +  if (mouseIsPressed) {
        +    bvals[width - 1] = 0;
        +  } else {
        +    bvals[width - 1] = 255;
        +  }
        +
        +  fill(255);
        +  noStroke();
        +  rect(0, height / 3, width, height / 3 + 1);
        +
        +  for (let i = 1; i < width; i++) {
        +    stroke(255);
        +    point(i, xvals[i] / 3);
        +    stroke(0);
        +    point(i, height / 3 + yvals[i] / 3);
        +    stroke(255);
        +    line(
        +      i,
        +      (2 * height) / 3 + bvals[i] / 3,
        +      i,
        +      (2 * height) / 3 + bvals[i - 1] / 3
        +    );
        +  }
        +}
        diff --git a/src/data/examples/ko/21_Input/09_Storing_Input.js b/src/data/examples/ko/21_Input/09_Storing_Input.js
        new file mode 100644
        index 0000000000..ea88476c2f
        --- /dev/null
        +++ b/src/data/examples/ko/21_Input/09_Storing_Input.js
        @@ -0,0 +1,36 @@
        +/*
        + * @name 입력값 저장
        + * @description 화면 위로 마우스를 움직여 원들의 위치를 바꿔보세요.
        + * 마우스의 위치값들은 배열에 기록되고 매 프레임마다 재생됩니다.
        + * 각 프레임이 재생되는 사이, 가장 새로운 값이 배열의 마지막에 더해지고
        + * 가장 오래된 값은 삭제됩니다.
        + */
        +let num = 60;
        +let mx = [];
        +let my = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  noStroke();
        +  fill(255, 153);
        +  for (let i = 0; i < num; i++) {
        +    mx.push(i);
        +    my.push(i);
        +  }
        +}
        +
        +function draw() {
        +  background(237, 34, 93);
        +
        +  // 각 프레임마다 다른 입력값을 이용해 배열을 순환
        +  // 이처럼 모듈로(%)를 사용하면 모든 값들을 이동시키는 것보다 빠릅니다.
        +  let which = frameCount % num;
        +  mx[which] = mouseX;
        +  my[which] = mouseY;
        +
        +  for (let i = 0; i < num; i++) {
        +    // which+1은 가장 작은 값 (동시에, 배열에서 가장 오래된 값)
        +    let index = (which + 1 + i) % num;
        +    ellipse(mx[index], my[index], i, i);
        +  }
        +}
        diff --git a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        new file mode 100644
        index 0000000000..251a3b0c8a
        --- /dev/null
        +++ b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        @@ -0,0 +1,104 @@
        +/*
        + * @name 저장된 JSON 불러오기
        + * @description Bubble 클래스를 만들고, JSON 파일의 데이터를 사용해 버블 여러 개를 인스턴스화합니다.
        + * 그리고, 그 결과물을 화면에 띄웁니다.
        + * 웹 브라우저마다 파일 저장 위치가 다르기 때문에,
        + * 프로세싱(Processing)의 예제와는 달리 saveJSON을 사용하지 않습니다.<br><br>
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)의 <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON 예제</a> 참고
        + */
        +
        +// Bubble 클래스
        +class Bubble {
        +  constructor(x, y, diameter, name) {
        +    this.x = x;
        +    this.y = y;
        +    this.diameter = diameter;
        +    this.radius = diameter / 2;
        +    this.name = name;
        +
        +    this.over = false;
        +  }
        +
        +  // 마우스가 버블 위에 있는지 확인
        +  rollover(px, py) {
        +    let d = dist(px, py, this.x, this.y);
        +    this.over = d < this.radius;
        +  }
        +
        +  // 버블을 화면에 보이기
        +  display() {
        +    stroke(0);
        +    strokeWeight(0.8);
        +    noFill();
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +    if (this.over) {
        +      fill(0);
        +      textAlign(CENTER);
        +      text(this.name, this.x, this.y + this.radius + 20);
        +    }
        +  }
        +}
        +
        +let data = {}; // loadJSON 호출의 결과물을 담는 전역 객체
        +let bubbles = []; // 모든 버블 객체를 담는 전역 배열
        +
        +// 비동기 데이터 로딩을 preload에 담아 setup이 실행되기 전 완료시킴
        +function preload() {
        +  data = loadJSON('assets/bubbles.json');
        +}
        +
        +// 저장된 Bubble 데이터를 Bubble 객체로 전환
        +function loadData() {
        +  let bubbleData = data['bubbles'];
        +  for (let i = 0; i < bubbleData.length; i++) {
        +    // 배열 속 각 객체 받아오기
        +    let bubble = bubbleData[i];
        +    // position 객체 받아오기
        +    let position = bubble['position'];
        +    // 위치로부터 x,y 받아오기
        +    let x = position['x'];
        +    let y = position['y'];
        +
        +    // Get diameter and label
        +    let diameter = bubble['diameter'];
        +    let label = bubble['label'];
        +
        +    // 배열에 객체 담기
        +    bubbles.push(new Bubble(x, y, diameter, label));
        +  }
        +}
        +
        +// 마우스가 클릭될 때마다 새로운 Bubble 만들기
        +function mousePressed() {
        +  // Bubble에 지름과 레이블 더하기
        +  let diameter = random(40, 80);
        +  let label = 'New Label';
        +
        +  // 배열에 새로운 JSON bubble 객체 더하기
        +  bubbles.push(new Bubble(mouseX, mouseY, diameter, label));
        +
        +  // 버블이 너무 많을 경우 개수 제거하기
        +  if (bubbles.length > 10) {
        +    bubbles.shift(); // 배열의 첫 번째 항목 제거하기
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  loadData();
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  // 모든 버블들 화면에 보이기
        +  for (let i = 0; i < bubbles.length; i++) {
        +    bubbles[i].display();
        +    bubbles[i].rollover(mouseX, mouseY);
        +  }
        +
        +  // 하단에서의 레이블 방향들
        +  textAlign(LEFT);
        +  fill(0);
        +  text('Click to add bubbles.', 10, height - 10);
        +}
        diff --git a/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
        new file mode 100644
        index 0000000000..c497516da3
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
        @@ -0,0 +1,25 @@
        +/*
        + * @name 사운드 불러오기/재생
        + * @description preload()중 사운드 불러오기. 캔버스가 클릭될 때마다 소리를 재생합니다.
        + * <br><br><p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p><br><br>
        + */
        +let song;
        +
        +function setup() {
        +  song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
        +  createCanvas(720, 200);
        +  background(255, 0, 0);
        +}
        +
        +function mousePressed() {
        +  if (song.isPlaying()) {
        +    // .isPlaying()은 불리언 값을 반환합니다.
        +    song.stop();
        +    background(255, 0, 0);
        +  } else {
        +    song.play();
        +    background(0, 255, 0);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/01_Preload_Sound.js b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        new file mode 100644
        index 0000000000..38120ffaaa
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        @@ -0,0 +1,35 @@
        +/*
        + * @name 사운드 파일 미리 불러오기
        + * @description preload()에서 loadSound()를 호출하여,
        + * setup()이 호출되기 전에 미리 사운드 파일을 불러오도록 합니다.
        + * 이 때, preload()에서 loadSound()를 호출하는 것이 가장 좋은 방법입니다.
        + * 그렇지 않을 경우, 스케치에서 사운드 재생을 원하는 시점에 파일이 불러지지 않을 수 있습니다.
        + *
        + * <br><br><p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +
        +let song;
        +
        +function preload() {
        +  song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
        +}
        +
        +function setup() {
        +  createCanvas(710, 200);
        +  song.loop(); // 이제 노래 파일이 setup()에서 재생될 준비가 되었습니다.
        +               //preload에서 이미 한 차례 불러왔기 때문입니다.
        +  background(0, 255, 0);
        +}
        +
        +function mousePressed() {
        +  if (song.isPlaying()) {
        +    // .isPlaying()은 불리언 값을 반환합니다.
        +    song.pause(); // .play()는 .pause() 지점에서 다시 시작합니다.
        +    background(255, 0, 0);
        +  } else {
        +    song.play();
        +    background(0, 255, 0);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/02_soundFormats.js b/src/data/examples/ko/33_Sound/02_soundFormats.js
        new file mode 100644
        index 0000000000..7416963a36
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/02_soundFormats.js
        @@ -0,0 +1,50 @@
        +/**
        + *  @name 사운드 확장자
        + *  @description <p>특허 문제로 인해, 모든 웹 브라우저가 지원하는
        + *  단일의 사운드 파일 형식은 존재하지 않습니다. 
        + *  예를 들어, 
        + *  <a href="http://caniuse.com/#feat=mp3">mp3</a>의 경우, OSX나 윈도우즈의
        + *  주요 브라우저 최신 버전에서 지원하긴 하지만, 일부 운영 체제나 브라우저에서는
        + *  사용하지 못할 수 있습니다.</p>
        + *
        + *  <p>사운드 파일의 완전한 호환성을 보장하기 위해, 동일한 사운드 파일을 
        + *  여러가지 형식으로 스케치에 포함시킬 수 있습니다. 'sound.mp3'나 'sound.ogg'가 그 예입니다.
        + *  (Ogg는 mp3의 대안형 오픈 소스입니다.) <a href="http://media.io/">media.io</a>
        + *  에서 오디오 파일을 웹-친화적인 형식으로 무료 변환할 수 있습니다.</p>.
        + *
        + *  <p>soundFormats() 메소드는 현재 스케치에 포함된 사운드 파일의 형식들을 loadSound에게 지정합니다.
        + *  그러면, loadSound는 지정된 형식들 중 클라이언트의 웹 브라우저가 지원하는
        + *  첫번째 형식을 불러오도록 시도할 것입니다.</p>
        + *
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
        +let song;
        +
        +function preload() {
        +  // .ogg와 .mp3 파일 모두를 스케치에 포함시키기
        +  soundFormats('ogg', 'mp3');
        +
        +  // 만약 mp3를 이 브라우저가 지원하지 않는다면,
        +  // loadSound는 스케치에 포함된 형식인 ogg 파일을 불러옵니다.
        +  song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
        +}
        +
        +function setup() {
        +  createCanvas(710, 200);
        +
        +  // preload()중에 사운드 파일을 미리 불러와, setup()에서 재생할 수 있도록 준비
        +  song.play();
        +  background(0, 255, 0);
        +}
        +
        +function mousePressed() {
        +  if (song.isPlaying()) {
        +    // .isPlaying()은 불리언 값을 반환합니다.
        +    song.pause();
        +    background(255, 0, 0);
        +  } else {
        +    song.play(); // playback은 pause(일시정지) 지점에서 다시 재생합니다.
        +    background(0, 255, 0);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/03_Play_Mode.js b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        new file mode 100644
        index 0000000000..accdf51bc2
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        @@ -0,0 +1,42 @@
        +/*
        + * @name 재생 모드
        + * @description
        + * <p>'sustain' 모드에서는 사운드가 겹쳐서 재생됩니다.
        + * 'restart' 모드에서는 사운드가 멈췄다가 다시 재생합니다.
        + * 마우스 클릭으로 사운드 파일을 재생해보세요.
        + * 동시에 여러 사운드를 재생해보세요! 아무 자판을 눌러 재생 모드를 변경합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let playMode = 'sustain';
        +let sample;
        +
        +function setup() {
        +  createCanvas(710, 50);
        +  soundFormats('mp3', 'ogg');
        +  sample = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');
        +}
        +
        +function draw() {
        +  background(255, 255, 0);
        +  let str = 'Click here to play! Press key to toggle play mode.';
        +  str += ' Current Play Mode: ' + playMode + '.';
        +  text(str, 10, height / 2);
        +}
        +
        +function mouseClicked() {
        +  sample.play();
        +}
        +function keyPressed(k) {
        +  togglePlayMode();
        +}
        +
        +function togglePlayMode() {
        +  if (playMode === 'sustain') {
        +    playMode = 'restart';
        +  } else {
        +    playMode = 'sustain';
        +  }
        +  sample.playMode(playMode);
        +}
        diff --git a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        new file mode 100644
        index 0000000000..0f07dd1a6a
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        @@ -0,0 +1,34 @@
        +/*
        + * @name 사운드 패닝
        + * @description <p>마우스를 클릭해 사운드를 재생하세요.
        + * 공의 위치는 마우스의 위치와 더불어, 사운드의 패닝과도 관련됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + *
        + */
        +let ball = {};
        +let soundFile;
        +
        +function preload() {
        +  soundFormats('mp3', 'ogg');
        +  soundFile = loadSound('assets/beatbox.ogg');
        +}
        +
        +function setup() {
        +  createCanvas(710, 100);
        +}
        +
        +function draw() {
        +  background(0);
        +  ball.x = constrain(mouseX, 0, width);
        +  ellipse(ball.x, height / 2, 100, 100);
        +}
        +
        +function mousePressed() {
        +  // 공의 x 위치를 패닝 각도에 맵핑하기
        +  // -1.0 (좌) 과 1.0 (우) 사이
        +  let panning = map(ball.x, 0, width, -1.0, 1.0);
        +  soundFile.pan(panning);
        +  soundFile.play();
        +}
        diff --git a/src/data/examples/ko/33_Sound/05_Sound_Effect.js b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        new file mode 100644
        index 0000000000..7f9b5e65a3
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        @@ -0,0 +1,68 @@
        +/*
        + * @name 사운드 효과
        + * @description <p>마우스로 원 안쪽을 누르면 사운드 효과가 재생됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +// 다니엘 쉬프만(Daniel Shiffman)의 Learning Processing을 적용
        +// http://www.learningprocessing.com
        +// 초인종 샘플 출처: freesound.org에서 Corsica_S 제작,
        +// Creative Commons BY 3.0
        +
        +// "doorbell(초인종)"을 설명하는 클래스 (실제로 버튼처럼 작동)
        +class Doorbell {
        +  constructor(x_, y_, r_) {
        +    // 위치와 크기
        +    this.x = x_;
        +    this.y = y_;
        +    this.r = r_;
        +  }
        +  // doorbell 안에 마우스 점이 있나요? (마우스 롤오버 등에 사용)
        +  contains(mx, my) {
        +    return dist(mx, my, this.x, this.y) < this.r;
        +  }
        +
        +  // doorbell을 보여주세요. (색상 부분은 하드코딩이네요. 더 나은 방법이 있을거에요.)
        +  display(mx, my) {
        +    if (this.contains(mx, my)) {
        +      fill(100);
        +    } else {
        +      fill(175);
        +    }
        +    stroke(0);
        +    strokeWeight(4);
        +    ellipse(this.x, this.y, this.r, this.r);
        +  }
        +}
        +
        +// 사운드 파일 객체
        +let dingdong;
        +
        +// 초인종 객체 (사운드를 트리거)
        +let doorbell;
        +
        +function setup() {
        +  createCanvas(200, 200);
        +
        +  // 사운드 파일 불러오기
        +  // 스케치에 MP3와 OGG 버전을 포함시킵니다.
        +  soundFormats('mp3', 'ogg');
        +  dingdong = loadSound('assets/doorbell.mp3');
        +
        +  // 새로운 초인종 만들기
        +  doorbell = new Doorbell(width / 2, height / 2, 64);
        +}
        +
        +function draw() {
        +  background(255);
        +  // 초인종 보이기
        +  doorbell.display(mouseX, mouseY);
        +}
        +
        +function mousePressed() {
        +  // 사용자가 초인종을 클릭하면, 사운드 재생하기!
        +  if (doorbell.contains(mouseX, mouseY)) {
        +    dingdong.play();
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        new file mode 100644
        index 0000000000..5edc06eb21
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        @@ -0,0 +1,48 @@
        +/*
        + * @name 재생 속도
        + * @description <p>사운드 파일을 불러와 재생 속도와 볼륨을 mouseY에 맵핑합니다.
        + * 여기서 재생 속도란, 웹 오디오가 사운드 파일 정보를 처리하는 속도를 말합니다.
        + * 재생 속도가 느리면 사운드의 지속 시간을 늘릴 뿐 아니라,
        + * 느린 주파수에서 재생되어 음고(pitch)를 감소시킵니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +// 사운드 파일 객체
        +let song;
        +
        +function preload() {
        +  // 사운드 파일 불러오기
        +  song = loadSound('assets/Damscray_DancingTiger.mp3');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  // 사운드 무한 반복하기
        +  // (뭐, 적어도 stop()이 호출되기 전까지요)
        +  song.loop();
        +}
        +
        +function draw() {
        +  background(200);
        +
        +  // 볼륨 범위를 0 과 1.0 사이로 설정
        +  let volume = map(mouseX, 0, width, 0, 1);
        +  volume = constrain(volume, 0, 1);
        +  song.amp(volume);
        +
        +  // 재생 속도 범위를 0.1 과 4 사이로 설정
        +  // 재생 속도를 변경하면 음고 또한 달라집니다.
        +  let speed = map(mouseY, 0.1, height, 0, 2);
        +  speed = constrain(speed, 0.01, 4);
        +  song.rate(speed);
        +
        +  // 원을 그려 어떤 일이 일어나는지 확인하기
        +  stroke(0);
        +  fill(51, 100);
        +  ellipse(mouseX, 100, 48, 48);
        +  stroke(0);
        +  fill(51, 100);
        +  ellipse(100, mouseY, 48, 48);
        +}
        diff --git a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        new file mode 100644
        index 0000000000..91c2e4e994
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        @@ -0,0 +1,47 @@
        +/**
        + * @name 진폭 측정
        + * @description <p>p5.Amplitude로 사운드의 진폭을 분석합니다.</p>
        + *
        + *  <p><b>진폭(amplitude)</b>은 진동의 크기를 말합니다.
        + *  사운드는 진동이므로, 볼륨/음량과 밀접한 관계를 갖습니다.</p>
        + *
        + * <p><code>getLevel()</code> 메소드는 짧은 시간 동안 수집된
        + * 진폭값(1024 샘플)을 배열에 담습니다.
        + * 그 다음, 이 값들의 <b>제곱 평균 제곱근(RMS)</b>을 반환합니다.</p>
        + *
        + * <p>디지털 오디오의 본래 진폭값은 -1.0과 1.0 사이입니다.
        + * 하지만, RMS는 제곱이므로 항상 양수입니다.
        + * 또한, RMS는 초당 44,000배의 속도에서 샘플링된 순간 진폭 판독값을 사용하는 대신
        + * 시간에 따른 평균값(이 경우, 1024 샘플)을 사용하여, 진폭을 듣는 방식을 더욱 잘 나타냅니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let song, analyzer;
        +
        +function preload() {
        +  song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
        +}
        +
        +function setup() {
        +  createCanvas(710, 200);
        +  song.loop();
        +
        +  // 새로운 진폭 분석기 생성
        +  analyzer = new p5.Amplitude();
        +
        +  // 볼륨 분석기에 입력값 패치하기
        +  analyzer.setInput(song);
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  // 평균 진폭값(RMS) 받아오기
        +  let rms = analyzer.getLevel();
        +  fill(127);
        +  stroke(0);
        +
        +  // 볼륨과 비례한 크기의 타원 그리기
        +  ellipse(width / 2, height / 2, 10 + rms * 200, 10 + rms * 200);
        +}
        diff --git a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        new file mode 100644
        index 0000000000..2132861e7d
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        @@ -0,0 +1,50 @@
        +/**
        + *  @name 노이즈 드럼 엔벨로프
        + *  @description  <p> 화이트 노이즈는 주파수 영역의 모든 부분에서
        + *  동일한 에너지를 갖는, 임의의 오디오 신호입니다</p>
        + *  <p>엔벨로프(envelope)는 시간/값의 쌍으로 정의되는
        + *  일련의 페이드를 말합니다.</p>
        + *  <p>이 예제에서는, p5.Env로 출력된 진폭을 제어하여
        + *  p5.Noise를 마치 드럼처럼 "재생"합니다.
        + *  p5.Amplitude는 스케치에 포함된 모든 사운드들의 레벨을 가져오며,
        + *  작동 중인 엔벨로프를 이 값으로서 초록색 사각형으로 표현합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        + */
        +let noise, env, analyzer;
        +
        +function setup() {
        +  createCanvas(710, 200);
        +  noise = new p5.Noise(); // 그 외 타입들은 '갈색'과 '분홍'을 포함
        +  noise.start();
        +
        +  // 노이즈 볼륨에 0 곱하기
        +  // (노이즈 재생 전까지 조용하기 위해서요!)
        +  noise.amp(0);
        +
        +  env = new p5.Env();
        +  // 어택 시간, 감쇠 시간, 지속 속도, 릴리즈 시간 설정
        +  env.setADSR(0.001, 0.1, 0.2, 0.1);
        +  // 어택 레벨, 릴리즈 레벨 설정
        +  env.setRange(1, 0);
        +
        +  // setInput()메소드로 입력값을 지정하지 않는 이상,
        +  // p5.Amplitude는 스케치에 포함된 모든 사운드를 분석할 것입니다.
        +  analyzer = new p5.Amplitude();
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // p5.Amplitude analyzer(분석 장치)로부터 볼륨 판독값 받아오기
        +  let level = analyzer.getLevel();
        +
        +  // 레벨값을 사용하여 초록색 사각형 그리기
        +  let levelHeight = map(level, 0, 0.4, 0, height);
        +  fill(100, 250, 100);
        +  rect(0, height, width, -levelHeight);
        +}
        +
        +function mousePressed() {
        +  env.play(noise);
        +}
        diff --git a/src/data/examples/ko/33_Sound/09_Note_Envelope.js b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        new file mode 100644
        index 0000000000..853814b982
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        @@ -0,0 +1,59 @@
        +/**
        + *  @name 음계 엔벨로프
        + *  @description  <p>엔벨로프(envelope)는 시간/값의 쌍으로 정의되는
        + *  일련의 페이드를 말합니다.
        + *  이 예제에서 엔벨로프는 오실레이터의 출력 진폭을 제어하여 
        + *  음계를 "재생"하는 데 사용됩니다.<br/><br/>
        + *  p5.Oscillator은 내부 웹 오디오 GainNode(p5.Oscillator.output)
        + *  를 거쳐 그 출력 내용을 전송합니다.
        + *  이 노드는 기본값으로 상수 0.5를 갖는데, osc.amp()메소드로 재설정할 수 있습니다.
        + *  또는 이 예제에서처럼, 엔벨로프가 직접 노드를 제어하여
        + *  마치 볼륨을 조정하듯 진폭을 조정할 수 있습니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        + */
        +let osc, envelope, fft;
        +
        +let scaleArray = [60, 62, 64, 65, 67, 69, 71, 72];
        +let note = 0;
        +
        +function setup() {
        +  createCanvas(710, 200);
        +  osc = new p5.SinOsc();
        +
        +  // 엔벨로프 인스턴스화
        +  envelope = new p5.Env();
        +
        +  // 어택 시간, 감쇠 시간, 지속 속도, 릴리즈 시간 설정
        +  envelope.setADSR(0.001, 0.5, 0.1, 0.5);
        +
        +  // 어택 레벨, 릴리즈 레벨 설정
        +  envelope.setRange(1, 0);
        +
        +  osc.start();
        +
        +  fft = new p5.FFT();
        +  noStroke();
        +}
        +
        +function draw() {
        +  background(20);
        +
        +  if (frameCount % 60 === 0 || frameCount === 1) {
        +    let midiValue = scaleArray[note];
        +    let freqValue = midiToFreq(midiValue);
        +    osc.freq(freqValue);
        +
        +    envelope.play(osc, 0, 0.1);
        +    note = (note + 1) % scaleArray.length;
        +  }
        +
        +  // 캔버스에 FFT.analyze() 주파수 분석 내용 기입
        +  let spectrum = fft.analyze();
        +  for (let i = 0; i < spectrum.length / 20; i++) {
        +    fill(spectrum[i], spectrum[i] / 10, 0);
        +    let x = map(i, 0, spectrum.length / 20, 0, width);
        +    let h = map(spectrum[i], 0, 255, 0, height);
        +    rect(x, height, spectrum.length / 20, -h);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        new file mode 100644
        index 0000000000..434bd0a2b1
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        @@ -0,0 +1,39 @@
        +/*
        + * @name 오실레이터 주파수
        + * @description <p>FFT를 사용하여 오실레이터를 제어하고 그 파형을 봅니다.
        + * MouseX는 주파수에, mouseY는 진폭에 매핑됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        + */
        +let osc, fft;
        +
        +function setup() {
        +  createCanvas(720, 256);
        +
        +  osc = new p5.TriOsc(); // 주파수와 종류 설정
        +  osc.amp(0.5);
        +
        +  fft = new p5.FFT();
        +  osc.start();
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  let waveform = fft.waveform(); // 파형 분석하기
        +  beginShape();
        +  strokeWeight(5);
        +  for (let i = 0; i < waveform.length; i++) {
        +    let x = map(i, 0, waveform.length, 0, width);
        +    let y = map(waveform[i], -1, 1, height, 0);
        +    vertex(x, y);
        +  }
        +  endShape();
        +
        +  // 오실레이터 주파수를 mouseX에 따라 변경
        +  let freq = map(mouseX, 0, width, 40, 880);
        +  osc.freq(freq);
        +
        +  let amp = map(mouseY, 0, height, 1, 0.01);
        +  osc.amp(amp);
        +}
        diff --git a/src/data/examples/ko/33_Sound/11_Live_Input.js b/src/data/examples/ko/33_Sound/11_Live_Input.js
        new file mode 100644
        index 0000000000..dc3fefa8e4
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/11_Live_Input.js
        @@ -0,0 +1,33 @@
        +/**
        + * @name 마이크 입력
        + * @description <p>컴퓨터의 마이크를 통해 오디오 입력을 받습니다.
        + * 마이크에 소리를 내어 타원이 떠오르게 해보세요.</p>
        + * <p>주의: p5.AudioIn에는 p5.Amplitude 객체가 포함되어, 별도의
        + * p5.Amplitude를 생성하지 않고도 p5.AudioIn에서 getLevel을 호출할 수 있습니다.</p>
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
        +let mic;
        +
        +function setup() {
        +  createCanvas(710, 200);
        +
        +  // 오디오 입력 생성하기
        +  mic = new p5.AudioIn();
        +
        +  // 오디오 입력 시작하기
        +  // 그 기본값은 .connect()(즉, 컴퓨터 스피커에 연결)되지 "않은" 상태입니다.
        +  mic.start();
        +}
        +
        +function draw() {
        +  background(200);
        +
        +  // 전체 볼륨(0과 1.0 사이) 받아오기
        +  let vol = mic.getLevel();
        +  fill(127);
        +  stroke(0);
        +
        +  // 마이크 소리의 볼륨에 따라 떠있는 높이가 변하는 타원 그리기
        +  let h = map(vol, 0, 1, height, 0);
        +  ellipse(width / 2, h - 25, 50, 50);
        +}
        diff --git a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        new file mode 100644
        index 0000000000..a3582f809e
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        @@ -0,0 +1,30 @@
        +/**
        + * @name 주파수 스펙트럼
        + * @description <p>실시간 오디오 입력을 통해 주파수 스펙트럼을 시각화합니다.</p>
        + * <p><em><span class="small"> To run this example locally, you will need the
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
        + */
        +let mic, fft;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  noFill();
        +
        +  mic = new p5.AudioIn();
        +  mic.start();
        +  fft = new p5.FFT();
        +  fft.setInput(mic);
        +}
        +
        +function draw() {
        +  background(200);
        +
        +  let spectrum = fft.analyze();
        +
        +  beginShape();
        +  for (i = 0; i < spectrum.length; i++) {
        +    vertex(i, map(spectrum[i], 0, 255, height, 0));
        +  }
        +  endShape();
        +}
        diff --git a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        new file mode 100644
        index 0000000000..46e98c93d5
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        @@ -0,0 +1,48 @@
        +/**
        + * @name 마이크 임계값
        + * @description <p>입력된 오디오의 볼륨이 임계값을 초과하면
        + * 특정 이벤트(이 경우, 사각형 그리기)가 발생합니다.</p>
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +// 다니엘 쉬프만(Daniel Shiffman)저 Learning Processing을 적용
        +// learningprocessing.com
        +let input;
        +let analyzer;
        +
        +function setup() {
        +  createCanvas(710, 200);
        +  background(255);
        +
        +  // 오디오 입력 생성하기
        +  input = new p5.AudioIn();
        +
        +  input.start();
        +}
        +
        +function draw() {
        +  // 전체 볼륨(0과 1.0 사이) 받아오기
        +  let volume = input.getLevel();
        +
        +  // 만약 볼륨 > 0.1 이라면, 임의의 위치에 사각형 한 개가 그려집니다.
        +  // 볼륨이 커질수록, 사각형도 커집니다.
        +  let threshold = 0.1;
        +  if (volume > threshold) {
        +    stroke(0);
        +    fill(0, 100);
        +    rect(random(40, width), random(height), volume * 50, volume * 50);
        +  }
        +
        +  // 전체 볼륨 범위를 막대 그래프로 나타내고 임계값의 위치에는 선 하나 긋기
        +  let y = map(volume, 0, 1, height, 0);
        +  let ythreshold = map(threshold, 0, 1, height, 0);
        +
        +  noStroke();
        +  fill(175);
        +  rect(0, 0, 20, height);
        +  // 그 다음, 볼륨값을 보여주는 검정 사각형을 그래프 위에 그리기
        +  fill(0);
        +  rect(0, y, 20, y);
        +  stroke(0);
        +  line(0, ythreshold, 19, ythreshold);
        +}
        diff --git a/src/data/examples/ko/33_Sound/14_Filter_LowPass.js b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js
        new file mode 100644
        index 0000000000..863cb259bc
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js
        @@ -0,0 +1,60 @@
        +/**
        + *  @name 로우패스 필터
        + *  @description p5.SoundFile에 p5.LowPass 필터를 적용합니다.
        + *  FFT를 사용해 사운드를 시각화해보세요.
        + *  mouseX를 필터의 차단 주파수에, mouseY를 밴드패스 필터의 울림/폭에 맵핑합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let soundFile;
        +let fft;
        +
        +let filter, filterFreq, filterRes;
        +
        +function preload() {
        +  soundFormats('mp3', 'ogg');
        +  soundFile = loadSound('assets/beat');
        +}
        +
        +function setup() {
        +  createCanvas(710, 256);
        +  fill(255, 40, 255);
        +
        +  // loop the sound file
        +  soundFile.loop();
        +
        +  filter = new p5.LowPass();
        +
        +  // Disconnect soundfile from master output.
        +  // Then, connect it to the filter, so that we only hear the filtered sound
        +  soundFile.disconnect();
        +  soundFile.connect(filter);
        +
        +  fft = new p5.FFT();
        +}
        +
        +function draw() {
        +  background(30);
        +
        +  // Map mouseX to a the cutoff frequency from the lowest
        +  // frequency (10Hz) to the highest (22050Hz) that humans can hear
        +  filterFreq = map(mouseX, 0, width, 10, 22050);
        +
        +  // Map mouseY to resonance (volume boost) at the cutoff frequency
        +  filterRes = map(mouseY, 0, height, 15, 5);
        +
        +  // set filter parameters
        +  filter.set(filterFreq, filterRes);
        +
        +  // Draw every value in the FFT spectrum analysis where
        +  // x = lowest (10Hz) to highest (22050Hz) frequencies,
        +  // h = energy (amplitude / volume) at that frequency
        +  let spectrum = fft.analyze();
        +  noStroke();
        +  for (let i = 0; i < spectrum.length; i++) {
        +    let x = map(i, 0, spectrum.length, 0, width);
        +    let h = -height + map(spectrum[i], 0, 255, height, 0);
        +    rect(x, height, width / spectrum.length, h);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/15_Filter_BandPass.js b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js
        new file mode 100644
        index 0000000000..125fda5795
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js
        @@ -0,0 +1,49 @@
        +/**
        + *  @name 밴드패스 필터
        + *  @description 화이트 노이즈에 p5.BandPass 필터를 적용합니다.
        + *  FFT를 사용해 사운드를 시각화해보세요.
        + *  mouseX를 필터의 밴드패스(대역) 주파수에, mouseY를 밴드패스 필터의 울림/폭에 맵핑합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let noise;
        +let fft;
        +let filter, filterFreq, filterWidth;
        +
        +function setup() {
        +  createCanvas(710, 256);
        +  fill(255, 40, 255);
        +
        +  filter = new p5.BandPass();
        +
        +  noise = new p5.Noise();
        +
        +  noise.disconnect(); // 마스터 출력과 사운드 파일 연결 해제...
        +  filter.process(noise); // ...그리고 필터에 연결하여 밴드패스만 들리게하기
        +  noise.start();
        +
        +  fft = new p5.FFT();
        +}
        +
        +function draw() {
        +  background(30);
        +
        +  // mouseX를 FFT 스펙트럼 범위(10Hz-22050Hz)에 해당하는 밴드패스 주파수에 맵핑하기
        +  filterFreq = map(mouseX, 0, width, 10, 22050);
        +  // mouseY를 울림/폭에 맵핑하기
        +  filterWidth = map(mouseY, 0, height, 0, 90);
        +  // 필터 매개 변수들 설정
        +  filter.set(filterFreq, filterWidth);
        +
        +  // FFT 스펙트럼 분석 중 x와 h가 아래와 같은 모든 값들 그리기:
        +  // x = 최저(10Hz)~최고(22050Hz) 주파수,
        +  // h = 해당 주파수에서의 에너지 / 진폭
        +  let spectrum = fft.analyze();
        +  noStroke();
        +  for (let i = 0; i < spectrum.length; i++) {
        +    let x = map(i, 0, spectrum.length, 0, width);
        +    let h = -height + map(spectrum[i], 0, 255, height, 0);
        +    rect(x, height, width / spectrum.length, h);
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/16_Delay.js b/src/data/examples/ko/33_Sound/16_Delay.js
        new file mode 100644
        index 0000000000..f18120992f
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/16_Delay.js
        @@ -0,0 +1,56 @@
        +/**
        + *  @name 딜레이 필터
        + *  @description
        + *  마우스를 클릭하여 p5.Delay로 처리된 사운드 파일을 들어보세요.
        + *  MouseX는 p5.Delay필터의 주파수를 조정합니다.
        + *  MouseY는 p5.Delay필터의 시간과 울림 정도를 조정합니다.
        + *  Amplitude(진폭) 객체로 출력된 사운드의 볼륨을 시각화해보세요.
        + *
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +
        +let soundFile, analyzer, delay;
        +
        +function preload() {
        +  soundFormats('ogg', 'mp3');
        +  soundFile = loadSound('assets/beatbox.mp3');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +
        +  soundFile.disconnect(); // 여기선 딜레이만 들을 수 있습니다.
        +
        +  delay = new p5.Delay();
        +  delay.process(soundFile, 0.12, 0.7, 2300);
        +  delay.setType('pingPong'); // 스테레오 효과
        +
        +  analyzer = new p5.Amplitude();
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // p5.Amplitude 분석 장치의 볼륨 판독 내용 받아오기
        +  let level = analyzer.getLevel();
        +
        +  // 레벨을 사용하여 초록색 사각형 그리기
        +  let levelHeight = map(level, 0, 0.1, 0, height);
        +  fill(100, 250, 100);
        +  rect(0, height, width, -levelHeight);
        +
        +  let filterFreq = map(mouseX, 0, width, 60, 15000);
        +  filterFreq = constrain(filterFreq, 60, 15000);
        +  let filterRes = map(mouseY, 0, height, 3, 0.01);
        +  filterRes = constrain(filterRes, 0.01, 3);
        +  delay.filter(filterFreq, filterRes);
        +  let delTime = map(mouseY, 0, width, 0.2, 0.01);
        +  delTime = constrain(delTime, 0.01, 0.2);
        +  delay.delayTime(delTime);
        +}
        +
        +function mousePressed() {
        +  soundFile.play();
        +}
        diff --git a/src/data/examples/ko/33_Sound/17_Reverb.js b/src/data/examples/ko/33_Sound/17_Reverb.js
        new file mode 100644
        index 0000000000..f27a1c5d20
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/17_Reverb.js
        @@ -0,0 +1,36 @@
        +/**
        + *  @name 리버브
        + *  @description 리버브(reverb)는 사운드에 깊이감과 공간감을 더합니다.
        + *  이 예제에서 노이즈는 reverb로 처리됩니다.
        + *
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let sound, reverb;
        +
        +function preload() {
        +  soundFormats('mp3', 'ogg');
        +  soundFile = loadSound('assets/Damscray_DancingTiger');
        +
        +  // 기본값으로 설정된 연결 상태를 해제하여
        +  // reverb.process를 통해서만 사운드를 들을 수 있도록 처리합니다.
        +  soundFile.disconnect();
        +}
        +
        +function setup() {
        +  createCanvas(720, 100);
        +  background(0);
        +
        +  reverb = new p5.Reverb();
        +
        +  // 6초의 reverbTime(리버브 시간)과 0.2%의 decayRate(감쇠 속도)를 갖는
        +  // 리버브에 사운드 파일 연결하기 
        +  reverb.process(soundFile, 6, 0.2);
        +
        +  reverb.amp(4); // 턴잇업!
        +}
        +
        +function mousePressed() {
        +  soundFile.play();
        +}
        diff --git a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        new file mode 100644
        index 0000000000..51fa1b3416
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        @@ -0,0 +1,84 @@
        +/**
        + * @name 컨볼루션 리버브
        + * @description <p>The p5.Convolver
        + * p5.Convolver는 컨볼루션을 사용하여 실제 공간 사운드를 재현합니다. 
        + * 컨볼루션은 임펄스 응답(즉, 반향하는 공간의 사운드)으로 해당 공간의 사운드를 재생성합니다.
        + * 컨볼루션으로 처리된 소리를 재생하려면 클릭하세요.
        + * 매번 클릭할 때마다, 서로 다른 임펄스 응답으로 재생성된 사운드를 들을 수 있습니다.
        + * 임펄스 응답만 재생하려면 아무 키나 누르세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + * 컨볼루션 샘플들은 <a href="https://www.freesound.org/people/recordinghopkins/">
        + * recordinghopkins</a>가 제작한 크리에이티브 커먼즈(CC)입니다.</span></p>
        + */
        +let sound, env, cVerb, fft;
        +let currentIR = 0;
        +let rawImpulse;
        +
        +function preload() {
        +  // 모든 임펄스/사운드들의 MP3 및 OGG 버전을 이 스케치에 포함시킵니다.
        +  soundFormats('ogg', 'mp3');
        +
        +  // p5.Convolver 생성하기
        +  cVerb = createConvolver('assets/bx-spring');
        +
        +  // bx-spring에 더해, cVerb.impulses 배열에 임펄스 응답 추가하기
        +  cVerb.addImpulse('assets/small-plate');
        +  cVerb.addImpulse('assets/drum');
        +  cVerb.addImpulse('assets/beatbox');
        +  cVerb.addImpulse('assets/concrete-tunnel');
        +
        +  // p5.ConvultionReverb로 처리될 사운드 불러오기 
        +  sound = loadSound('assets/Damscray_DancingTiger');
        +}
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  rawImpulse = loadSound('assets/' + cVerb.impulses[currentIR].name);
        +
        +  // 마스터 출력으로부터 연결 해제하고...
        +  sound.disconnect();
        +  // ... cVerb로 처리하여
        +  // 오직 리버브만 들을 수 있도록 합니다.
        +  cVerb.process(sound);
        +
        +  fft = new p5.FFT();
        +}
        +
        +function draw() {
        +  background(30);
        +  fill(0, 255, 40);
        +
        +  let spectrum = fft.analyze();
        +
        +  // frequencySpectrum 배열에 있는 모든 값들을 사각형으로 그리기
        +  noStroke();
        +  for (let i = 0; i < spectrum.length; i++) {
        +    let x = map(i, 0, spectrum.length, 0, width);
        +    let h = -height + map(spectrum[i], 0, 255, height, 0);
        +    rect(x, height, width / spectrum.length, h);
        +  }
        +}
        +
        +function mousePressed() {
        +  // cVerb.impulses 배열 반복하기
        +  currentIR++;
        +  if (currentIR >= cVerb.impulses.length) {
        +    currentIR = 0;
        +  }
        +  cVerb.toggleImpulse(currentIR);
        +
        +  // 임펄스를 거쳐 사운드 재생하기
        +  sound.play();
        +
        +  // 현재 임펄스 응답 이름 보이기(파일 경로)
        +  println('Convolution Impulse Response: ' + cVerb.impulses[currentIR].name);
        +
        +  rawImpulse.setPath('assets/' + cVerb.impulses[currentIR].name);
        +}
        +
        +// 임펄스 재생하기(컨볼루션 없이)
        +function keyPressed() {
        +  rawImpulse.play();
        +}
        diff --git a/src/data/examples/ko/33_Sound/19_Record_Save.js b/src/data/examples/ko/33_Sound/19_Record_Save.js
        new file mode 100644
        index 0000000000..5d11d49f9b
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/19_Record_Save.js
        @@ -0,0 +1,57 @@
        +/**
        + * @name 오디오 녹음/저장
        + * @description 
        + * 사운드를 녹음하고 재생한 뒤, 클라이언트 컴퓨터에 .wav 파일로 저장하세요
        + * 이 예제에서는 총 세 개의 객체가 필요합니다: p5.AudioIn(마이크/사운드 소스),
        + * p5.SoundRecorder(사운드 녹음), 그리고 p5.SoundFile(재생/저장)
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + */
        +let mic, recorder, soundFile;
        +
        +let state = 0; // 마우스 버튼이 눌리면 녹음, 정지, 재생 순으로 상태가 변합니다.
        +
        +function setup() {
        +  createCanvas(400, 400);
        +  background(200);
        +  fill(0);
        +  text('Enable mic and click the mouse to begin recording', 20, 20);
        +
        +  // AudioIn 생성하기
        +  mic = new p5.AudioIn();
        +
        +  // 녹음 기능을 제대로 작동시키려면, 사용자가 브라우저 마이크를 수동으로 활성화해야 됩니다!
        +  mic.start();
        +
        +  // 사운드 녹음기 생성하기
        +  recorder = new p5.SoundRecorder();
        +
        +  // 마이크를 녹음기에 연결
        +  recorder.setInput(mic);
        +
        +  // 녹음된 사운드를 재생할 빈 사운드 파일 생성
        +  soundFile = new p5.SoundFile();
        +}
        +
        +function mousePressed() {
        +  // '.enabled' 불리언을 사용하여 사용자의 마이크 활성화 여부 확인(그렇지 않을 경우, 침묵 상태를 녹음하게 됩니다!)
        +  if (state === 0 && mic.enabled) {
        +    // p5.SoundFile에 녹음하라고 녹음기에 지시하기. 이 파일은 녹음 사운드를 재생하는 데에 쓰입니다.
        +    recorder.record(soundFile);
        +
        +    background(255, 0, 0);
        +    text('Recording now! Click to stop.', 20, 20);
        +    state++;
        +  } else if (state === 1) {
        +    recorder.stop(); // 녹음기를 멈추고, 결과물을 soundFile에 보내기
        +
        +    background(0, 255, 0);
        +    text('Recording stopped. Click to play & save', 20, 20);
        +    state++;
        +  } else if (state === 2) {
        +    soundFile.play(); // 결과물 재생하기!
        +    saveSound(soundFile, 'mySound.wav'); // 파일 저장하기
        +    state++;
        +  }
        +}
        diff --git a/src/data/examples/ko/33_Sound/21_FreqModulation.js b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        new file mode 100644
        index 0000000000..f4cdb7945f
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        @@ -0,0 +1,143 @@
        +/**
        + * @name 주파수 변조(FM)
        + * @description <p> 주파수 변조(Frequancy Modulator, FM)는 강력한 합성 방식입니다.
        + * 아주 간단히 말하자면, FM은 반송파와 변조기라는 두 개의 오실레이터를 포함합니다.
        + * 변조기의 파형이 최소 및 최대 진폭 값 사이에서 진동하면, 그 순간의 값이 반송파 주파수에 추가(즉, "변조")됩니다</p>
        + * <p><b>반송파</b>는, 우리가 일반적으로 음고(pitch)라 부르는, 가청 주파수에서 진동합니다.
        + * 이 예제의 경우, "A3"음과 동일한 220Hz의 사인파 오실레이터입니다.
        + * 모든 p5.Oscillator들은 그 기본값으로 반송파가 마스터 출력에 연결되어 있습니다.
        + * <p>이 예제에서 우리는 <b>변조기</b>를 마스터 출력과 <code>연결 해제</code>하고,
        + * 대신 다음을 사용하여 반송파 주파수에 연결합니다: <code>carrier.freq(modulator)</code>.
        + * 이는 변조기의 출력 진폭을 반송파 주파수에 추가합니다.</p>
        + * <p>
        + * <b>변조 깊이</b>는 반송파 주파수가 변조된 정도를 묘사합니다.
        + * 이는 변조기의 진폭을 기반으로 합니다.
        + * 변조기는 반송파 주파수에 추가될, 진폭 값들의 연속적인 스트림을 생성합니다. 
        + * 진폭이 0이면 묵음이 발생하므로 변조가 적용되지 않습니다. 
        + * 진폭이 1.0이면 출력값의 범위가 +1.0과 -1.0 사이로 조정됩니다.
        + * 이는 스피커로 전송되는 사운드의 표준 범위이기도 합니다.
        + * 하지만, FM에서는 변조기의 출력을 반송파 주파수로 전송하는데,
        + * 반송파 주파수에서는 + 1Hz / -1Hz 변조를 거의 찾아보기 힘듭니다. 
        + * 따라서, 변조기의 진폭("깊이")을 스피커로 보내는 값보다 훨씬 높은 숫자로 증가시키는 게 일반적입니다.</p>
        + * <p><b>변조 주파수</b>는 변조 속도를 나타냅니다.
        + * 변조 주파수가 20Hz보다 낮으면, 우리는 주파수를 음고가 아닌 비트와 리듬으로서 듣게 됩니다.
        + * 예를 들어, 오페라 보컬의 "비브라토" 효과를 따라하고자, 깊이 20에서 7.5Hz를 시도해보세요.
        + * 이를 위한 용어는 저주파수 오실레이터(Low Frequency Oscillator, LFO)입니다.
        + * 더 높은 주파수로 설정된 변조기는 여러가지 흥미로운 효과들을 만들 수 있습니다.
        + * 특히, 주파수가 반송파 신호와 화음을 이룰 경우 그렇습니다.
        + * 그 예로, 변조기의 주파수가 반송파 주파수의 절반 또는 두 배일 때 발생하는 사운드를 들어세요.
        + * 이는 존 차우닝(John Chowning)이 1960년대에 개발한 "FM 합성" 개념의 근간이기도 합니다.
        + * FM 합성은 1980년대에 이르러 사운드 합성을 변혁시킨 바 있으며, 놋쇠나 종소리를 합성하는 데에 자주 사용됩니다. *
        + *
        + * <p>이 예제에서는,</p><p>
        + * - MouseX가 변조 깊이(즉, 변조기의 진폭)를 -150부터 150까지 조정합니다.
        + * 변조기 진폭이 0(즉, 가운데)으로 설정되면, 아무런 변조 효과가 발생하지 않습니다.
        + * 숫자의 절대값이 커질수록, 효과가 커집니다.
        + * 변조기 파형이 마치 사각형 <code>[]</code>, 싸인 <code>~</code>
        + * 또는 삼각형 <code>/\</code>과 같이 대칭일 경우, 음수의 진폭과 양수의 진폭은 동일합니다.
        + * 하지만 이 예제 속 변조기는 마치 이러한 모양 / 의 톱니처럼 생긴 비대칭적인 파형을 갖습니다.
        + * 여기에 음수를 곱하면, 파형이 마치 이러한 모양 \ 처럼 반대로 바뀝니다. 
        + * 그 차이를 명확히 관찰하려면, 주파수를 낮춰보세요.
        + * </p>
        + * <p>- MouseY는 변조기의 주파수를 0부터 112Hz까지 조정합니다.
        + * 가청 범위(약 20hz에서 시작) 이하 및 이상 영역에서의 변조기 주파수를 비교해보세요.
        + * 특히, 반송파 주파수(220hz이므로 1/2, 1/3, 1/4 등으로 나눠보세요)와 화음을 이루는 상태에서요! *
        + *
        + * <p><em><span class="small">로컬 프로젝트에서 이 예제를 실행하려면,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>
        + * 를 추가해야 됩니다.</em></span></p>
        + */
        +
        +let carrier; // 이것이 바로 우리가 듣게될 오실레이터입니다.
        +let modulator; // 이 오실레이터가 반송파 주파수를 변조할 것입니다.
        +
        +let analyzer; // 이것을 사용해 파형을 시각화합니다.
        +
        +// 반송파 주파수 사전 변조
        +let carrierBaseFreq = 220;
        +
        +// 변조기의 최저/최고 범위
        +let modMaxFreq = 112;
        +let modMinFreq = 0;
        +let modMaxDepth = 150;
        +let modMinDepth = -150;
        +
        +function setup() {
        +  let cnv = createCanvas(800, 400);
        +  noFill();
        +
        +  carrier = new p5.Oscillator('sine');
        +  carrier.amp(0); // 진폭 설정
        +  carrier.freq(carrierBaseFreq); // 주파수 설정
        +  carrier.start(); // 오실레이팅 시작
        +
        +  // 종류를 'square(사각형)', 'sine(싸인)' 또는 'triangle(삼각형)'으로 바꿔보세요!
        +  modulator = new p5.Oscillator('sawtooth');
        +  modulator.start();
        +
        +  // 반송파 주파수를 변조하기 위해 변조기의 출력값 더하기
        +  modulator.disconnect();
        +  carrier.freq(modulator);
        +
        +  // 오디오 분석을 위해 FFT 생성하기
        +  analyzer = new p5.FFT();
        +
        +  // 마우스 오버 / 스타트 터치 시, 반송파 페이드 인/아웃
        +  toggleAudio(cnv);
        +}
        +
        +function draw() {
        +  background(30);
        +
        +
        +  // 최대 및 최소 주파수 사이의 변조기 주파수에 mouseY를 매핑하기
        +  let modFreq = map(mouseY, height, 0, modMinFreq, modMaxFreq);
        +  modulator.freq(modFreq);
        +
        +  // 변조기의 진폭 바꾸기
        +  // 음수의 amp는 톱니 파형을 반대로 뒤집고, 두드리는 듯한 사운드를 만듭니다.
        +  //
        +  let modDepth = map(mouseX, 0, width, modMinDepth, modMaxDepth);
        +  modulator.amp(modDepth);
        +
        +  // 파형 분석하기
        +  waveform = analyzer.waveform();
        +
        +  // 파형 그리기
        +  stroke(255);
        +  strokeWeight(10);
        +  beginShape();
        +  for (let i = 0; i < waveform.length; i++) {
        +    let x = map(i, 0, waveform.length, 0, width);
        +    let y = map(waveform[i], -1, 1, -height / 2, height / 2);
        +    vertex(x, y + height / 2);
        +  }
        +  endShape();
        +
        +  strokeWeight(1);
        +  // 어떤 일이 일어나는 지에 대한 설명을 추가합니다.
        +  text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20);
        +  text(
        +    'Modulator Amplitude (Modulation Depth): ' + modDepth.toFixed(3),
        +    20,
        +    40
        +  );
        +  text(
        +    'Carrier Frequency (pre-modulation): ' + carrierBaseFreq + ' Hz',
        +    width / 2,
        +    20
        +  );
        +}
        +
        +// 사운드 토글을 위한 helper 함수
        +function toggleAudio(cnv) {
        +  cnv.mouseOver(function() {
        +    carrier.amp(1.0, 0.01);
        +  });
        +  cnv.touchStarted(function() {
        +    carrier.amp(1.0, 0.01);
        +  });
        +  cnv.mouseOut(function() {
        +    carrier.amp(0.0, 1.0);
        +  });
        +}
        diff --git a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        new file mode 100644
        index 0000000000..a45481d22d
        --- /dev/null
        +++ b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        @@ -0,0 +1,91 @@
        +/**
        + * @name 진폭 변조(AM)
        + * @description <p>진폭 변조(Amplitude Modulation, AM)은
        + * 반송파와 변조기라는 두 개의 오실레이터를 포함하고, 이는 반송파의 진폭을 조정합니다.</p>
        + *
        + * <p>반송파는 일반적으로 가청 주파수(예. 440Hz)에 설정됩니다.
        + * 그리고, 그 기본값으로 마스터 출력에 연결되어 있습니다.a
        + * carrier.amp는 0으로 설정되어 있는데, 이는 변조기로 진폭을 조정하기 위해서입니다.</p>
        + *
        + * <p>이 예제에서 변조기는 마스터 출력과 연결이 해제되어 있습니다.
        + * 대신, 다음을 통해 반송파의 진폭에 연결되어 있습니다: carrier.amp(변조기).</p>
        + *
        + * <p>이 예제에서는,</p>
        + * <p>- MouseX가 변조기의 진폭을 0부터 1까지 조정합니다.
        + * 변조기 진폭이 0으로 설정되면, 아무런 변조 효과가 발생하지 않습니다.</p>
        + *
        + * <p>- MouseY는 변조기의 주파수를 0부터 20hz까지 조정합니다.
        + * 이 범위는 인간이 들을 수 있는 주파수보다 낮으므로, 우리는 변조 사운드를 리듬으로서 듣게됩니다.
        + * 이 범위를 사용해 마치 풍금 소리와같은 효과를 만들 수 있습니다.
        + * 링 변조는 진폭 변조의 한 종류로, 원본 반송파 신호가 존재하지 않고, 더 빠른 주파수를 변조합니다.</p>
        + *
        + * <p><em><span class="small">로컬 프로젝트에서 이 예제를 실행하려면,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>
        + * 를 추가해야 됩니다.</em></span></p>
        + */
        +let carrier; // 이것이 바로 우리가 듣게될 오실레이터입니다.
        +let modulator; // 이 오실레이터가 반송파 주파수를 변조할 것입니다.
        +let fft; // 이것을 사용해 파형을 시각화합니다.
        +
        +function setup() {
        +  createCanvas(800, 400);
        +  noFill();
        +  background(30); // 알파값
        +
        +  carrier = new p5.Oscillator(); // 기본값으로, 마스터 출력에 연결된 상태입니다.
        +  carrier.freq(340);
        +  carrier.amp(0);
        +  // 반송파의 amp는 기본값으로 0을 가져, 변조기에게 완전한 제어 권한을 부여합니다.
        +
        +  carrier.start();
        +
        +  modulator = new p5.Oscillator('triangle');
        +  modulator.disconnect(); // 변조기를 마스터 출력과 연결 해제합니다.
        +  modulator.freq(5);
        +  modulator.amp(1);
        +  modulator.start();
        +
        +  // 변조기를 사용해 반송파의 진폭을 변조하기
        +  // 추가적으로, 신호도 조정할 수 있습니다.
        +  carrier.amp(modulator.scale(-1, 1, 1, -1));
        +
        +  // 오디오 분석을 위해 FFT 생성하기
        +  fft = new p5.FFT();
        +}
        +
        +function draw() {
        +  background(30, 30, 30, 100); // 알파값
        +
        +  // 0과 20hz 사이의 변조기 주파수에 mouseY를 매핑하기
        +  let modFreq = map(mouseY, 0, height, 20, 0);
        +  modulator.freq(modFreq);
        +
        +  let modAmp = map(mouseX, 0, width, 0, 1);
        +  modulator.amp(modAmp, 0.01); // 페이드 타임을 0.1로 조정하여 페이딩을 부드럽게 만들기
        +
        +  // 파형 분석하기
        +  waveform = fft.waveform();
        +
        +  // 파형 그리기
        +  drawWaveform();
        +
        +  drawText(modFreq, modAmp);
        +}
        +
        +function drawWaveform() {
        +  stroke(240);
        +  strokeWeight(4);
        +  beginShape();
        +  for (let i = 0; i < waveform.length; i++) {
        +    let x = map(i, 0, waveform.length, 0, width);
        +    let y = map(waveform[i], -1, 1, -height / 2, height / 2);
        +    vertex(x, y + height / 2);
        +  }
        +  endShape();
        +}
        +
        +function drawText(modFreq, modAmp) {
        +  strokeWeight(1);
        +  text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20);
        +  text('Modulator Amplitude: ' + modAmp.toFixed(3), 20, 40);
        +}
        diff --git a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        new file mode 100644
        index 0000000000..21a6518ad2
        --- /dev/null
        +++ b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        @@ -0,0 +1,58 @@
        +/*
        + * @name 가속 공 바운스
        + * @description accelerationX와 accelerationY 값을 활용해 타원을 움직이고, 캔버스의 경계에 닿았을 때 튕기도록 만듭니다.
        + */
        +
        +// 위치 변수들
        +let x = 0;
        +let y = 0;
        +
        +// 속도 변수들
        +let vx = 0;
        +let vy = 0;
        +
        +// 가속 변수들
        +let ax = 0;
        +let ay = 0;
        +
        +let vMultiplier = 0.007;
        +let bMultiplier = 0.6;
        +
        +function setup() {
        +  createCanvas(displayWidth, displayHeight);
        +  fill(0);
        +}
        +
        +function draw() {
        +  background(255);
        +  ballMove();
        +  ellipse(x, y, 30, 30);
        +}
        +
        +function ballMove() {
        +  ax = accelerationX;
        +  ay = accelerationY;
        +
        +  vx = vx + ay;
        +  vy = vy + ax;
        +  y = y + vy * vMultiplier;
        +  x = x + vx * vMultiplier;
        +
        +  // 캔버스의 경계에 닿았을 때 튕기기
        +  if (x < 0) {
        +    x = 0;
        +    vx = -vx * bMultiplier;
        +  }
        +  if (y < 0) {
        +    y = 0;
        +    vy = -vy * bMultiplier;
        +  }
        +  if (x > width - 20) {
        +    x = width - 20;
        +    vx = -vx * bMultiplier;
        +  }
        +  if (y > height - 20) {
        +    y = height - 20;
        +    vy = -vy * bMultiplier;
        +  }
        +}
        diff --git a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        new file mode 100644
        index 0000000000..de4f128884
        --- /dev/null
        +++ b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        @@ -0,0 +1,15 @@
        +/*
        + * @name 간단한 드로잉
        + * @description mouseX, mouseY, pmouseX, pmouseY 값을 사용하여 스크린을 터치했을 때 그려지도록 합니다.
        + */
        +
        +function setup() {
        +  createCanvas(displayWidth, displayHeight);
        +  strokeWeight(10);
        +  stroke(0);
        +}
        +
        +function touchMoved() {
        +  line(mouseX, mouseY, pmouseX, pmouseY);
        +  return false;
        +}
        diff --git a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        new file mode 100644
        index 0000000000..cecd1bed76
        --- /dev/null
        +++ b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        @@ -0,0 +1,24 @@
        +/*
        + * @name 가속도 색상
        + * @description deviceMoved()를 사용해 모바일 기기의 회전을 감지합니다. 배경의 RGB 색상값은 각각 accelerationX, accelerationY, accelerationZ 값에 매핑됩니다.
        + */
        +
        +let r, g, b;
        +
        +function setup() {
        +  createCanvas(displayWidth, displayHeight);
        +  r = random(50, 255);
        +  g = random(0, 200);
        +  b = random(50, 255);
        +}
        +
        +function draw() {
        +  background(r, g, b);
        +  console.log('draw');
        +}
        +
        +function deviceMoved() {
        +  r = map(accelerationX, -90, 90, 100, 175);
        +  g = map(accelerationY, -90, 90, 100, 200);
        +  b = map(accelerationZ, -90, 90, 100, 200);
        +}
        diff --git a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        new file mode 100644
        index 0000000000..6d93cda8f3
        --- /dev/null
        +++ b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        @@ -0,0 +1,116 @@
        +/*
        + * @name 공 흔들고 튕기기
        + * @description Ball 클래스를 생성하고 복수의 객체를 인스턴스화한 뒤, 화면 위에서 움직여보세요.
        + * 공이 캔버스의 경계에 닿으면 튕깁니다. 
        + * accelerationX와 accelerationY의 총 변화를 기반으로 흔들림을 감지하고,
        + * 그러한 감지를 기반으로 객체의 속도를 높이거나 줄입니다.
        + */
        +
        +let balls = [];
        +
        +let threshold = 30;
        +let accChangeX = 0;
        +let accChangeY = 0;
        +let accChangeT = 0;
        +
        +function setup() {
        +  createCanvas(displayWidth, displayHeight);
        +
        +  for (let i = 0; i < 20; i++) {
        +    balls.push(new Ball());
        +  }
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  for (let i = 0; i < balls.length; i++) {
        +    balls[i].move();
        +    balls[i].display();
        +  }
        +
        +  checkForShake();
        +}
        +
        +function checkForShake() {
        +  // accelerationX and accelerationY의 총 변화 계산
        +  accChangeX = abs(accelerationX - pAccelerationX);
        +  accChangeY = abs(accelerationY - pAccelerationY);
        +  accChangeT = accChangeX + accChangeY;
        +  // 만약 흔들린다면,
        +  if (accChangeT >= threshold) {
        +    for (let i = 0; i < balls.length; i++) {
        +      balls[i].shake();
        +      balls[i].turn();
        +    }
        +  }
        +  // 만약 흔들리지 않는다면,
        +  else {
        +    for (let i = 0; i < balls.length; i++) {
        +      balls[i].stopShake();
        +      balls[i].turn();
        +      balls[i].move();
        +    }
        +  }
        +}
        +
        +// Ball 클래스
        +class Ball {
        +  constructor() {
        +    this.x = random(width);
        +    this.y = random(height);
        +    this.diameter = random(10, 30);
        +    this.xspeed = random(-2, 2);
        +    this.yspeed = random(-2, 2);
        +    this.oxspeed = this.xspeed;
        +    this.oyspeed = this.yspeed;
        +    this.direction = 0.7;
        +  }
        +
        +  move() {
        +    this.x += this.xspeed * this.direction;
        +    this.y += this.yspeed * this.direction;
        +  }
        +
        +  // 캔버스 경계에 닿았을 때 공 튀기기
        +  turn() {
        +    if (this.x < 0) {
        +      this.x = 0;
        +      this.direction = -this.direction;
        +    } else if (this.y < 0) {
        +      this.y = 0;
        +      this.direction = -this.direction;
        +    } else if (this.x > width - 20) {
        +      this.x = width - 20;
        +      this.direction = -this.direction;
        +    } else if (this.y > height - 20) {
        +      this.y = height - 20;
        +      this.direction = -this.direction;
        +    }
        +  }
        +
        +  // accerlerationX 값의 변화를 기반으로
        +  // xspeed와 yspeed에 더하기
        +  shake() {
        +    this.xspeed += random(5, accChangeX / 3);
        +    this.yspeed += random(5, accChangeX / 3);
        +  }
        +
        +  // 점점 느려지기
        +  stopShake() {
        +    if (this.xspeed > this.oxspeed) {
        +      this.xspeed -= 0.6;
        +    } else {
        +      this.xspeed = this.oxspeed;
        +    }
        +    if (this.yspeed > this.oyspeed) {
        +      this.yspeed -= 0.6;
        +    } else {
        +      this.yspeed = this.oyspeed;
        +    }
        +  }
        +
        +  display() {
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +  }
        +}
        diff --git a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        new file mode 100644
        index 0000000000..7479b4c77c
        --- /dev/null
        +++ b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        @@ -0,0 +1,15 @@
        +/*
        + * @name 기울어진 3D상자
        + * @description 모바일 기기를 이용해 상자를 기울게 만듭니다.
        + */
        +function setup() {
        +  createCanvas(displayWidth, displayHeight, WEBGL);
        +}
        +
        +function draw() {
        +  background(250);
        +  normalMaterial();
        +  rotateX(accelerationX * 0.01);
        +  rotateY(accelerationY * 0.01);
        +  box(100, 100, 100);
        +}
        diff --git a/src/data/examples/ko/90_Hello_P5/01_shapes.js b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        new file mode 100644
        index 0000000000..308d10ed3e
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        @@ -0,0 +1,28 @@
        +/*
        + * @name 간단한 도형들
        + * @description 이 예제는 원, 사각형, 삼각형, 그리고 꽃 모양을 포함합니다.
        + */
        +function setup() {
        +  // 캔버스 만들기
        +  createCanvas(720, 400);
        +  background(200);
        +
        +  // 색상 설정하기
        +  fill(204, 101, 192, 127);
        +  stroke(127, 63, 120);
        +
        +  // 사각형 한 개
        +  rect(40, 120, 120, 40);
        +  // 타원 한 개
        +  ellipse(240, 240, 80, 80);
        +  // 삼각형 한 개
        +  triangle(300, 100, 320, 100, 310, 80);
        +
        +  // 간단한 꽃 그리기
        +  translate(580, 200);
        +  noStroke();
        +  for (let i = 0; i < 10; i ++) {
        +    ellipse(0, 30, 20, 80);
        +    rotate(PI/5);
        +  }
        +}
        diff --git a/src/data/examples/ko/90_Hello_P5/02_interactivity.js b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        new file mode 100644
        index 0000000000..95c1733fec
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        @@ -0,0 +1,40 @@
        +/*
        + * @name 인터랙티비티 1
        + * @frame 720,425
        + * @description 원을 클릭하면 색상이 바뀝니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>.
        + * </em>를 추가해야 됩니다.</p>
        + */
        +
        +// 빨강(r), 초록(g), 파랑(b) 색상값들
        +let r, g, b;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  // 임의의 색상 고르기
        +  r = random(255);
        +  g = random(255);
        +  b = random(255);
        +}
        +
        +function draw() {
        +  background(127);
        +  // 원 그리기
        +  strokeWeight(2);
        +  stroke(r, g, b);
        +  fill(r, g, b, 127);
        +  ellipse(360, 200, 200, 200);
        +}
        +
        +// 사용자가 마우스를 클릭했을 때,
        +function mousePressed() {
        +  // 마우스가 원의 안쪽에 있는지 확인하기
        +  let d = dist(mouseX, mouseY, 360, 200);
        +  if (d < 100) {
        +    // 새로운 임의의 색상 고르기
        +    r = random(255);
        +    g = random(255);
        +    b = random(255);
        +  }
        +}
        diff --git a/src/data/examples/ko/90_Hello_P5/03_interactivity.js b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        new file mode 100644
        index 0000000000..08af063d3b
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        @@ -0,0 +1,29 @@
        +/*
        + * @name Interactivity 2
        + * @frame 720,425
        + * @description The circle changes color when you move the slider.
        + * You will need to include the 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        + * for this example to work in your own project.
        + */
        +
        +// A HTML range slider
        +let slider;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  // hue, saturation, and brightness
        +  colorMode(HSB, 255);
        +  // slider has a range between 0 and 255 with a starting value of 127
        +  slider = createSlider(0, 255, 127);
        +}
        +
        +function draw() {
        +  background(127);
        +  strokeWeight(2);
        +
        +  // Set the hue according to the slider
        +  stroke(slider.value(), 255, 255);
        +  fill(slider.value(), 255, 255, 127);
        +  ellipse(360, 200, 200, 200);
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/90_Hello_P5/04_animate.js b/src/data/examples/ko/90_Hello_P5/04_animate.js
        new file mode 100644
        index 0000000000..f746dd15ea
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/04_animate.js
        @@ -0,0 +1,33 @@
        +/*
        + * @name 애니메이션
        + * @description 원이 움직입니다.
        + */
        +// 원의 위치를 알기 위해
        +let x, y;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  // 화면 가운데에서 시작하기
        +  x = width / 2;
        +  y = height;
        +}
        +
        +function draw() {
        +  background(200);
        +  
        +  // 원 그리기
        +  stroke(50);
        +  fill(100);
        +  ellipse(x, y, 24, 24);
        +  
        +  // 가로축에서 무작위로 흔들리기
        +  x = x + random(-1, 1);
        +  // 일정 속도로 위를 향해 움직이기
        +  y = y - 1;
        +  
        +  // 화면 하단으로 리셋
        +  if (y < 0) {
        +    y = height;
        +  }
        +}
        +
        diff --git a/src/data/examples/ko/90_Hello_P5/04_flocking.js b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        new file mode 100644
        index 0000000000..a5b5c9600b
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        @@ -0,0 +1,186 @@
        +/*
        + * @name 플로킹
        + * @description 크레이그 레이놀즈(Craig Reynolds)의
        + * <a href="http://www.red3d.com/cwr/">"군집(Flocking)" 행위</a>를 묘사합니다.<br>
        + * (규칙: 응집, 분리, 정렬)<br>
        + * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
        + */
        +let boids = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +
        +  // 시스템에 초기 개체(boid) 더하기
        +  for (let i = 0; i < 100; i++) {
        +    boids[i] = new Boid(random(width), random(height));
        +  }
        +}
        +
        +function draw() {
        +  background(51);
        +  // 모든 개체 실행하기
        +  for (let i = 0; i < boids.length; i++) {
        +    boids[i].run(boids);
        +  }
        +}
        +
        +// Boid 클래스
        +// Separation(분리), Cohesion(응집), Alignment(정렬)을 위한 메소드 추가하기
        +class Boid {
        +  constructor(x, y) {
        +    this.acceleration = createVector(0, 0);
        +    this.velocity = p5.Vector.random2D();
        +    this.position = createVector(x, y);
        +    this.r = 3.0;
        +    this.maxspeed = 3;    // 최고 속도
        +    this.maxforce = 0.05; // 최고 조타력
        +  }
        +
        +  run(boids) {
        +    this.flock(boids);
        +    this.update();
        +    this.borders();
        +    this.render();
        +  }
        +  
        +  // Force는 acceleration에 담깁니다.
        +  applyForce(force) {
        +    this.acceleration.add(force);
        +  }
        +  
        +  // 세 가지 규칙을 기반으로 새로운 accerlation(가속도)를 축적합니다.
        +  flock(boids) {
        +    let sep = this.separate(boids); // 분리
        +    let ali = this.align(boids);    // 정렬
        +    let coh = this.cohesion(boids); // 응집
        +    // 세 힘들을 임의로 가중하기
        +    sep.mult(2.5);
        +    ali.mult(1.0);
        +    coh.mult(1.0);
        +    // 가속도에 force 벡터 더하기
        +    this.applyForce(sep);
        +    this.applyForce(ali);
        +    this.applyForce(coh);
        +  }
        +  
        +  // 위치 업데이트를 위한 메소드
        +  update() {
        +    // 속도 업데이트
        +    this.velocity.add(this.acceleration);
        +    // 속도 제한
        +    this.velocity.limit(this.maxspeed);
        +    this.position.add(this.velocity);
        +    // 매 사이클마다 acceleration을 0으로 리셋하기
        +    this.acceleration.mult(0);
        +  }
        +  
        +  // 목표점을 향한 조타력을 계산하고 적용하는 메소드
        +  // STEER(조타력) = DESIRED(목표점) - VELOCITY(속도)
        +  seek(target) {
        +    let desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
        +  // desired를 표준화하고 최대 속도로 조정
        +    desired.normalize();
        +    desired.mult(this.maxspeed);
        +    // Steering = Desired minus Velocity
        +    let steer = p5.Vector.sub(desired, this.velocity);
        +    steer.limit(this.maxforce); // 최대 조타력으로 제한
        +    return steer;
        +  }
        +  
        +  // 개체(boid)를 원형으로 그리기
        +  render() {
        +    fill(127, 127);
        +    stroke(200);
        +    ellipse(this.position.x, this.position.y, 16, 16);
        +  }
        +  
        +  // Wraparound
        +  borders() {
        +    if (this.position.x < -this.r) this.position.x = width + this.r;
        +    if (this.position.y < -this.r) this.position.y = height + this.r;
        +    if (this.position.x > width + this.r) this.position.x = -this.r;
        +    if (this.position.y > height + this.r) this.position.y = -this.r;
        +  }
        +  
        +  // 분리 Seperation
        +  // 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
        +  separate(boids) {
        +    let desiredseparation = 25.0;
        +    let steer = createVector(0, 0);
        +    let count = 0;
        +    // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
        +    for (let i = 0; i < boids.length; i++) {
        +      let d = p5.Vector.dist(this.position, boids[i].position);
        +      // 만약 그 거리가 0보다 크고 임의의 값보다 작다면(0은 개체의 현위치)
        +      if ((d > 0) && (d < desiredseparation)) {
        +        // 인근의 개체로부터 떨어진 지점을 향하는 벡터 계산
        +        let diff = p5.Vector.sub(this.position, boids[i].position);
        +        diff.normalize();
        +        diff.div(d); // 거리에 따른 가중
        +        steer.add(diff);
        +        count++; // 개체수 카운트
        +      }
        +    }
        +    // 평균 -- 얼마로 나눌 것인가
        +    if (count > 0) {
        +      steer.div(count);
        +    }
        +  
        +    // 벡터가 0보다 크다면,
        +    if (steer.mag() > 0) {
        +      // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
        +      steer.normalize();
        +      steer.mult(this.maxspeed);
        +      steer.sub(this.velocity);
        +      steer.limit(this.maxforce);
        +    }
        +    return steer;
        +  }
        +  
        +  // 배열 Alignment
        +  // 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
        +  align(boids) {
        +    let neighbordist = 50;
        +    let sum = createVector(0, 0);
        +    let count = 0;
        +    for (let i = 0; i < boids.length; i++) {
        +      let d = p5.Vector.dist(this.position, boids[i].position);
        +      if ((d > 0) && (d < neighbordist)) {
        +        sum.add(boids[i].velocity);
        +        count++;
        +      }
        +    }
        +    if (count > 0) {
        +      sum.div(count);
        +      sum.normalize();
        +      sum.mult(this.maxspeed);
        +      let steer = p5.Vector.sub(sum, this.velocity);
        +      steer.limit(this.maxforce);
        +      return steer;
        +    } else {
        +      return createVector(0, 0);
        +    }
        +  }
        +  
        +  // 응집 Cohesion
        +  // 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
        +  cohesion(boids) {
        +    let neighbordist = 50;
        +    let sum = createVector(0, 0); // 빈 벡터값으로 시작하여 모든 위치들을 축적
        +    let count = 0;
        +    for (let i = 0; i < boids.length; i++) {
        +      let d = p5.Vector.dist(this.position, boids[i].position);
        +      if ((d > 0) && (d < neighbordist)) {
        +        sum.add(boids[i].position); // 위치 추가
        +        count++;
        +      }
        +    }
        +    if (count > 0) {
        +      sum.div(count);
        +      return this.seek(sum); // 해당 위치를 향해 조타
        +    } else {
        +      return createVector(0, 0);
        +    }
        +  }  
        +}
        +
        diff --git a/src/data/examples/ko/90_Hello_P5/05_weather.js b/src/data/examples/ko/90_Hello_P5/05_weather.js
        new file mode 100644
        index 0000000000..b415a3c4d7
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/05_weather.js
        @@ -0,0 +1,73 @@
        +/*
        + * @name 날씨
        + * @frame 720,280
        + * @description 이 예제는 apixu.com로부터 JSON 날씨 데이터를 받아옵니다.
        + * 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가해야 됩니다.
        +*/
        +
        +// 풍향 벡터
        +let wind;
        +// 원의 위치
        +let position;
        +
        +function setup() {
        +  createCanvas(720, 200);
        +  // apixu.com에 데이터 요청하기
        +  let url = 'https://api.apixu.com/v1/current.json?key=513d8003c8b348f1a2461629162106&q=NYC';
        +  loadJSON(url, gotWeather);
        +  // 화면의 가운데에서 원그리기 시작
        +  position = createVector(width/2, height/2);
        +  // 바람은 (0,0)에서 시작
        +  wind = createVector();
        +}
        +
        +function draw() {
        +  background(200);
        +
        +  // 이 섹션에서는 풍향을 나타내는 화살표를 그립니다.
        +  push();
        +  translate(32, height - 32);
        +  // 바람의 각도에 따라 회전하기
        +  rotate(wind.heading() + PI/2);
        +  noStroke();
        +  fill(255);
        +  ellipse(0, 0, 48, 48);
        +
        +  stroke(45, 123, 182);
        +  strokeWeight(3);
        +  line(0, -16, 0, 16);
        +
        +  noStroke();
        +  fill(45, 123, 182);
        +  triangle(0, -18, -6, -10, 6, -10);
        +  pop();
        +  
        +  // 풍향에 따라 움직이기
        +  position.add(wind);
        +  
        +  stroke(0);
        +  fill(51);
        +  ellipse(position.x, position.y, 16, 16);
        +
        +  if (position.x > width)  position.x = 0;
        +  if (position.x < 0)      position.x = width;
        +  if (position.y > height) position.y = 0;
        +  if (position.y < 0)      position.y = height;
        +}
        +
        +function gotWeather(weather) {
        +  
        +  // 각도 받아오기 (래디언으로 변환)
        +  let angle = radians(Number(weather.current.wind_degree));
        +  // 풍속 받아오기
        +  let windmag = Number(weather.current.wind_mph);
        +  
        +  // HTML요소로 화면에 보이기
        +  let temperatureDiv = createDiv(floor(weather.current.temp_f) + '&deg;');
        +  let windDiv = createDiv("WIND " + windmag + " <small>MPH</small>");
        +  
        +  // 벡터 생성하기
        +  wind = p5.Vector.fromAngle(angle);
        +}
        diff --git a/src/data/examples/ko/90_Hello_P5/06_drawing.js b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        new file mode 100644
        index 0000000000..db309cbd67
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        @@ -0,0 +1,132 @@
        +/*
        +* @name 드로잉
        +* @description 제너레이티브 페인팅 프로그램입니다.
        +*/
        +
        +// 모든 경로
        +let paths = [];
        +// 지금 페인팅을 하고 있나요?
        +let painting = false;
        +// 다음 원까지 걸리는 시간
        +let next = 0;
        +// 현재 및 이전 위치
        +let current;
        +let previous;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  current = createVector(0,0);
        +  previous = createVector(0,0);
        +};
        +
        +function draw() {
        +  background(200);
        +  
        +  // 새로운 점을 만들어 봅시다.
        +  if (millis() > next && painting) {
        +
        +    // 마우스 위치 받아오기     
        +    current.x = mouseX;
        +    current.y = mouseY;
        +
        +    // 새로운 파티클의 힘은 마우스의 움직임에 기반을 둡니다.
        +    let force = p5.Vector.sub(current, previous);
        +    force.mult(0.05);
        +
        +    // 새로운 파티클 더하기
        +    paths[paths.length - 1].add(current, force);
        +    
        +    // 다음 원의 시간 정하기 
        +    next = millis() + random(100);
        +
        +    // 더 많은 마우스값 저장하기
        +    previous.x = current.x;
        +    previous.y = current.y;
        +  }
        +
        +  // 모든 경로 그리기
        +  for( let i = 0; i < paths.length; i++) {
        +    paths[i].update();
        +    paths[i].display();
        +  }
        +}
        +
        +// 시작하기
        +function mousePressed() {
        +  next = 0;
        +  painting = true;
        +  previous.x = mouseX;
        +  previous.y = mouseY;
        +  paths.push(new Path());
        +}
        +
        +// 정지
        +function mouseReleased() {
        +  painting = false;
        +}
        +
        +// Path(경로)는 파티클들의 목록입니다.
        +class Path {
        +  constructor() {
        +    this.particles = [];
        +    this.hue = random(100);
        +  }
        +
        +  add(position, force) {
        +    // 새로운 파티클을 그 위치, 힘, 색조값과 함께 추가하기
        +    this.particles.push(new Particle(position, force, this.hue));
        +  }
        +  
        +  // 파티클 길이 화면에 보이기
        +  update() {  
        +    for (let i = 0; i < this.particles.length; i++) {
        +      this.particles[i].update();
        +    }
        +  }  
        +  
        +  // 파티클 길이 화면에 보이기
        +  display() {    
        +    // 뒤로 반복하기
        +    for (let i = this.particles.length - 1; i >= 0; i--) {
        +      // 만약 제거해야 된다면,
        +      if (this.particles[i].lifespan <= 0) {
        +        this.particles.splice(i, 1);
        +      // 그렇지 않다면, 화면에 보이기
        +      } else {
        +        this.particles[i].display(this.particles[i+1]);
        +      }
        +    }
        +  
        +  }  
        +}
        +
        +// 경로 위 파티클들
        +class Particle {
        +  constructor(position, force, hue) {
        +    this.position = createVector(position.x, position.y);
        +    this.velocity = createVector(force.x, force.y);
        +    this.drag = 0.95;
        +    this.lifespan = 255;
        +  }
        +
        +  update() {
        +    // Move it
        +    this.position.add(this.velocity);
        +    // Slow it down
        +    this.velocity.mult(this.drag);
        +    // Fade it out
        +    this.lifespan--;
        +  }
        +
        +  // 파티클을 그리고 선으로 잇기
        +  // 다른 파티클을 향해 선그리기
        +  display(other) {
        +    stroke(0, this.lifespan);
        +    fill(0, this.lifespan/2);    
        +    ellipse(this.position.x,this.position.y, 8, 8);    
        +    // 선을 그려야 한다면,
        +    if (other) {
        +      line(this.position.x, this.position.y, other.position.x, other.position.y);
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/90_Hello_P5/07_song.js b/src/data/examples/ko/90_Hello_P5/07_song.js
        new file mode 100644
        index 0000000000..2b0473ab23
        --- /dev/null
        +++ b/src/data/examples/ko/90_Hello_P5/07_song.js
        @@ -0,0 +1,119 @@
        +/*
        + * @name 노래
        + * @frame 720, 430
        + * @description 노래를 재생하세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.Sound 라이브러리</a>.
        + * </em>를 추가해야 됩니다.</p>
        + */
        +// MIDI 음계의 음표들
        +let notes = [ 60, 62, 64, 65, 67, 69, 71];
        +
        +// 노래를 자동 재생하기 위한 처리
        +let index = 0;
        +let song = [
        +  { note: 4, duration: 400, display: "D" },
        +  { note: 0, duration: 200, display: "G" },
        +  { note: 1, duration: 200, display: "A" },
        +  { note: 2, duration: 200, display: "B" },
        +  { note: 3, duration: 200, display: "C" },
        +  { note: 4, duration: 400, display: "D" },
        +  { note: 0, duration: 400, display: "G" },
        +  { note: 0, duration: 400, display: "G" }
        +];
        +let trigger = 0;
        +let autoplay = false;
        +let osc;
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  let div = createDiv("Click to play notes or ")
        +  div.id("instructions");
        +  let button = createButton("play song automatically.");
        +  button.parent("instructions");
        +  // 자동 재생 트리거하기
        +  button.mousePressed(function() {
        +    if (!autoplay) {
        +      index = 0;
        +      autoplay = true;
        +    }
        +  });
        +
        +  // 삼각형 오실레이터
        +  osc = new p5.TriOsc();
        +  // 무음 시작
        +  osc.start();
        +  osc.amp(0);
        +}
        +
        +// 음표를 재생하기 위한 함수
        +function playNote(note, duration) {
        +  osc.freq(midiToFreq(note));
        +  // 음표를 페이드인하기
        +  osc.fade(0.5,0.2);
        +
        +  // 만약 재생 시간을 설정한다면, 페이드 아웃
        +  if (duration) {
        +    setTimeout(function() {
        +      osc.fade(0,0.2);
        +    }, duration-50);
        +  }
        +}
        +
        +function draw() {
        +
        +  // 만약 현재 자동 재생 중이고 다음 음표를 재생할 때가 되었다면,
        +  if (autoplay && millis() > trigger){
        +    playNote(notes[song[index].note], song[index].duration);
        +    trigger = millis() + song[index].duration;
        +    // 다음 음표로 이동하기
        +    index ++;
        +  // 끝에 다다랐다면, 자동 재생 중지
        +  } else if (index >= song.length) {
        +    autoplay = false;
        +  }
        +
        +
        +  // 키보드 긜기
        +
        +  // 각 건반의 너비
        +  let w = width / notes.length;
        +  for (let i = 0; i < notes.length; i++) {
        +    let x = i * w;
        +    // 마우스가 건반 위에 있다면,
        +    if (mouseX > x && mouseX < x + w && mouseY < height) {
        +      // 마우스를 클릭 중이라면,
        +      if (mouseIsPressed) {
        +        fill(100,255,200);
        +      // 또는 마우스가 건반 위를 롤오버 중이라면,
        +      } else {
        +        fill(127);
        +      }
        +    } else {
        +      fill(200);
        +    }
        +
        +    // 또는, 노래가 재생 중이라면 하이라이트를 줍니다.  
        +    if (autoplay && i === song[index-1].note) {
        +      fill(100,255,200);
        +    }
        +
        +    // 건반 그리기
        +    rect(x, 0, w-1, height-1);
        +  }
        +
        +}
        +
        +// 클릭하면,
        +function mousePressed(event) {
        +  if(event.button == 0 && event.clientX < width && event.clientY < height) {
        +    // 건반 인덱스에 마우스를 매핑하기
        +    let key = floor(map(mouseX, 0, width, 0, notes.length));
        +    playNote(notes[key]);
        +  }
        +}
        +
        +// 마우스 버튼을 놓으면 페이드 아웃하기
        +function mouseReleased() {
        +  osc.fade(0,0.5);
        +}
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        new file mode 100644
        index 0000000000..a7ff79dfc1
        --- /dev/null
        +++ b/src/data/ko.yml
        @@ -0,0 +1,669 @@
        +Skip-To-Content: "Skip to content"
        +Language-Settings: "언어 설정"
        +Sidebar-Title: "사이트 둘러보기"
        +Home: "홈"
        +Editor: "에디터"
        +Download: "다운로드"
        +Donate: "기부하기"
        +Start: "시작하기"
        +Reference: "레퍼런스"
        +Libraries: "라이브러리"
        +Learn: "배우기"
        +Examples: "예제"
        +Books: "출판물"
        +Community: "커뮤니티"
        +Contribute: "함께하기"
        +Forum: "포럼"
        +Showcase: "쇼케이스"
        +
        +footerxh1: "Credits"
        +footer1: "p5.js는 로렌 맥카시 "
        +footer2: " 가 창안하고 협력자 커뮤니티와 함께 개발하였습니다. 지원: 프로세싱 재단 "
        +footer3: "과 "
        +footer4: " 아이덴티티 및 그래픽 디자인: "
        +
        +tagline1: "프로세싱의 즐거움에 자바스크립트의 매력을 곱하다*"
        +tagline2: "프로세싱의 간편함에 자바스크립트의 유연성을 곱하다*"
        +tagline3: "프로세싱의 직관성에 자바스크립트의 강력함을 곱하다*"
        +tagline4: "프로세싱의 창조성에 자바스크립트의 역동성을 곱하다*"
        +tagline5: "프로세싱 커뮤니티에 자바스크립트 커뮤니티를 곱하다*"
        +tagline6: "프로세싱의 강력함에 자바스크립트의 범용성을 곱하다*"
        +
        +home:
        +  start-creating: "p5 에디터로 프로젝트 시작하기"
        +  p1xh1: "안녕하세요!"
        +  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 특히, 예술가, 디자이너, 교육자, 초심자, 그리고 모두에게 접근성이 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공됩니다. 이는 소프트웨어와 그 학습 도구들이 누구에게나 열려있어야 한다는 생각에 기반합니다."
        +  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 오브젝트를 사용할 수 있습니다."
        +  p2xh2: "커뮤니티"
        +  p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        +  p2x2: "p5.js는 "
        +  p2x3: " (프로세싱)을 오늘날의 웹에 맞게 해석한 버전이라 볼 수 있습니다. p5의 행사와 모임은 "
        +  p2x4: " (프로세싱 재단)의 지원을 받아 개최됩니다."
        +  p2x5: ""
        +  p2x6: "커뮤니티"
        +  p2x7: "에 대해 더 알아보세요."
        +
        +  p3xh2: "시작하기"
        +  p3xp1: "온라인 에디터인 "
        +  p3xp2: "에서 나만의 첫 스케치를 그려보세요! "
        +  p3xp3: "시작하기"
        +  p3xp4: "에서 p5 스케치에 대해 알아보고, "
        +  p3xp5: "레퍼런스"
        +  p3xp6: "로 더욱 많은 기능을 확인해보세요."
        +
        +  p4xh2: "함께하기"
        +  p4xp1: "p5.js와 커뮤니티에 기여할 수 있는 방법은 다양합니다:"
        +  p4xp2: "함께하는 방법"
        +  p4xp3: "나의 창작 프로젝트 공유하기"
        +  p4xp4: "p5 워크숍 또는 수업 운영하기"
        +  p4xp5: "행사 또는 모임 주관하기"
        +  p4xp6: "코딩 개발로 기여하기"
        +
        +  sketch_by: "by"
        +  sketch_info: "홈페이지 스케치는 9학년 그레이스 오버그펠(Grace Obergfell)의 작품을 만들었습니다."
        +  sketch_info_link: "6월 8일 CC Fest NYC, 학생과 선생님들을 포용하는 무료 코딩 행사"
        +
        +copyright:
        +  copyright-title: "저작권"
        +  copyright1: "p5.js 라이브러리는 무료 소프트웨어입니다."
        +  copyright2: " Free Software Foundation의 조항(version 2.1.)에 따라 재배포 및 수정할 수 있습니다."
        +  copyright3: "The Reference for the language is under a "
        +  copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited."
        +
        +get started:
        +  get-started-title: "시작하기"
        +  get-started1: "p5.js 프로젝트를 설정하고 나의 첫 스케치를 만드는 방법을 소개합니다."
        +  get-started2: ""
        +  get-started3: "p5.js 웹에디터"
        +  get-started4: "로 스케치를 만들고 싶다면 이 곳을 클릭하세요:"
        +  get-started5: "나의 첫 스케치"
        +  download-title: "다운로드 & 파일 설정"
        +  download1: " "
        +  download2: "p5.js complete"
        +  download3: "와 함께 제공되는 빈 예제 프로젝트를 이용해 쉽게 테스트 해보세요."
        +  download4: "그 중 index.html 파일에는 p5.js 링크가 적혀있습니다. 로딩 시간을 단축하려면 이 p5.js 링크를 간략 버전인 p5.min.js로 아래와 같이 변경하면 됩니다. "
        +  download5: "또는, p5.js 파일의 온라인 링크를 입력하는 방법도 있습니다. p5.js의 모든 버전은 CDN (Content Delivery Network)에 저장되어 있으며, 버전 히스토리는 여기서 확인할 수 있습니다: "
        +  download6: ". 링크를 다음과 같이 변경해보세요:"
        +  download7: "아래는 HTML 페이지 샘플입니다:"
        +  download8: "위의 HTML 페이지 템플릿을 코드펜(CodePen)에 복사, 붙여넣기하여 프로젝트를 시작하는 것도 한 방법입니다: "
        +  download9: "."
        +  environment-title: "개발 환경"
        +  environment1: "여러분이 원하는 그 어떠한 "
        +  environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor"
        +  environment2: "코드 에디터"
        +  environment3: "도 p5.js를 위해 사용할 수 있습니다. 아래에 "
        +  environment4: " 에디터를 설정하는 방법이 있습니다.  추천하는 또다른 에디터: "
        +  environment5: ", "
        +  environment6: " p5 웹에디터를 이용하지 않는 스크린 리더(screen reader)라면, 다음의 에디터를 고려해보세요: "
        +  environment7: " 나 "
        +  environment8: "먼저, Sublime Text 2 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, html 파일과 js 파일이 위치한 폴더를 선택하세요. 폴더 이름과 폴더에 포함된 파일 리스트가 좌측 사이드바에 보일 것입니다."
        +  environment9: "sketch.js 파일을 선택하면, 우측 편집 영역에서 파일이 열립니다. "
        +  environment10: "Sublime 에디터에서 p5 템플릿 코드를 편집 중인 화면"
        +  environment11: "index.html 파일을 브라우저에서 열어볼까요? 파일 관리 시스템에서 index.html 파일을 더블 클릭하거나 브라우저 주소창에 다음을 입력하세요:"
        +  environment12: "file:///the/file/path/to/your/html"
        +  environment13: " "
        +  your-first-sketch-title: "나의 첫 스케치"
        +  your-first-sketch-intro1: "프로세싱(Processing) 유저라면 다음의 페이지를 읽어보세요: "
        +  your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        +  your-first-sketch-intro3: "Processing에서 p5.js로 변환하기 튜토리얼"
        +  your-first-sketch-intro4: "에디터에 다음을 입력하세요:"
        +  your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다: \"좌층 상단 모서리에서 아래로 50px, 오른쪽으로 50px 떨어진 점을 중심으로 삼는 타원을 그린다. 타원의 폭과 높이는 모두 80px로 한다.\" "
        +  your-first-sketch3: "스케치를 저장하고 브라우저 페이지에서 새로고침을 해보세요. 입력한 코드에 문제가 없는 한, 다음과 같은 화면을 볼 수 있습니다:"
        +  your-first-sketch4: "주의: 스크린 리더를 사용하는 경우, p5 웹에디터에서 Accessible Outputs를 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: "
        +  your-first-sketch5: "스크린 리더에서 p5를 사용하는 방법"
        +  your-first-sketch6: " , "
        +  your-first-sketch7: "접근성 라이브러리란?"
        +  your-first-sketch8: "캔버스에 폭과 높이가 50인 타원이 x 80, y 80의 위치에 그려져있다"
        +  your-first-sketch9: "코드를 잘못 입력할 경우 화면에 아무것도 나타나지 않을 수 있습니다. 예제 코드를 정확히 따라 썼는지 확인해 보세요. 숫자는 (괄호) 안에 포함하고, 각 숫자는 쉼표(,)로 구분해야 하며, 각 라인은 세미 콜론(;)으로 끝나야 합니다"
        +  your-first-sketch10: "프로그래밍 언어를 처음 접할 때 겪는 어려움 중 하나는 문법이 매우 까다롭다는 것입니다. 브라우저는 우리가 표현하고자 바가 무엇인지 스스로 이해할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감합니다. 처음에는 이런 문법이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바 스크립트 '콘솔'을 제공합니다. 크롬(Chrome)의 경우, 보기 > 개발자 > 자바 스크립트 콘솔을 클릭하여 '콘솔'을 활성화할 수 있습니다."
        +  your-first-sketch11: "이제 한층 더 재밌는 스케치를 만들어볼까요! 지난 예제의 코드를 에디터에서 삭제하고 아래의 코드를 입력해 보세요:"
        +  your-first-sketch12: "이제 프로그램은 폭 640px, 높이 480px의 캔버스를 생성하고, 마우스 커서 위치에서 흰 원을 그리기 시작합니다. 마우스 버튼을 누르고 있을 때는 원의 색이 검정색으로 바뀝니다. 마우스 위치에 대한 설명은 나중에 더 하기로 하고, 지금은 마우스를 움직이고 클릭하며 스케치의 변화를 살펴보세요."
        +  your-first-sketch13: "캔버스에 마우스 궤적을 따라 여러개의 원이 그려져있다"
        +  first-sketch-heading1: "타원과 코드 스니펫(snippet)"
        +  first-sketch-heading2: "Note for 스크린리더 사용자를 위한"
        +  first-sketch-heading3: "인터랙션과 코드 스니펫(snippet)"
        +  what-next-title: "다음 단계"
        +  processing-transition1: "Processing을 p5.js로 전환하는 방법과 둘 간의 차이점이 궁금하다면, "
        +  processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        +  processing-transition3: "Processing에서 p5.js로 변환하기 튜토리얼"
        +  processing-transition4: "을 읽어보세요."
        +  reference1: "p5.js에 대한 전체 문서를 보려면 "
        +  reference2: "레퍼런스"
        +  reference3: "를 읽어보세요."
        +  learn1: "더 많은 학습 자료가 필요하다면 "
        +  learn2: "배우기"
        +  learn3: " 페이지와 "
        +  learn4: "예제"
        +  learn5: " 페이지를 살펴보세요."
        +  learn6: "스크린 리더 모드로 p5를 사용하고 싶다면, 다음 페이지를 읽어보세요: "
        +  learn7: "스크린 리더상 p5 사용하기 튜토리얼"
        +  book1: "본 튜토리얼의 일부는 로렌 맥카시(Lauren McCarthy), 캐시 리스(Casey Reas), 벤 프라이(Ben Fry), 오라일리(O'Reilly) 저 Getting Started with p5.js 에서 발췌하였습니다. / Make 2015. Copyright "
        +
        +download:
        +  Download: "다운로드"
        +  download-intro: "안녕하세요! 이 페이지는 온라인에서 바로 사용가능한 웹에디터와 각종 다운로드 링크를 소개합니다. 초심자에게 꼭 필요한 자료부터 숙련된 개발자를 위한 리소스 모두를 포괄합니다."
        +  editor-title: "에디터"
        +  p5.js-editor: "p5.js 에디터"
        +  p5.js-editor-intro: "아래의 링크는 온라인 p5.js 에디터로 연결됩니다."
        +  editor-includes: "별도 설치가 필요없는 p5.js 웹에디터로 지금 바로 코딩을 시작해보세요!"
        +  complete-library-title: "모든 라이브러리"
        +  complete-library-intro1: "아래의 링크는 p5.js 라이브러리 파일, p5.sound, 그리고 예제 프로젝트를 포함합니다. "
        +  complete-library-intro2: "시작하기"
        +  complete-library-intro3: "에서 p5.js 프로젝트 설정 방법을 알아보세요."
        +  p5.js-complete: "모든 라이브러리"
        +  includes-1: "포함 사항:"
        +  includes-2: "p5.js, p5.sound.js, 예시 프로젝트 1개"
        +  includes-3: "Version "
        +  single-files-title: "개별 라이브러리"
        +  single-files-intro: "개별 라이브러리 파일입니다. "
        +  single-file: "개별 라이브러리: "
        +  p5.js-uncompressed: "개별 파일"
        +  compressed: "압축 버전"
        +  link: "링크: "
        +  statically-hosted-file: "정적 호스팅 파일"
        +  etc-title: "Github 리소스"
        +  older-releases: "이전 버전 (구버전 및 변경 로그)"
        +  github-repository: "코드 저장소 (GitHub)"
        +  report-bugs: "이슈, 버그, 에러 보고하기"
        +  supported-browsers: "지원 브라우저 "
        +
        +  support-title: "p5.js를 후원해주세요!"
        +  support-options: "기부 방법"
        +  support-1: "p5.js는 무료 오픈 소스 소프트웨어입니다. p5.js는 다양성을 향해 늘 열려있고 이를 포용하는 커뮤니티를 지향합니다. "
        +  support-2: "프로세싱 재단 멤버십 가입"
        +  support-3: "을 통해 개인, 스튜디오, 또는 교육 기관 단위로 기부하거나, 또는 "
        +  support-4: "멤버십 가입 생략"
        +  support-5: " 후 기부할 수 있습니다."
        +  support-6: "개인"
        +  support-7: "$25"
        +  support-8: "스튜디오"
        +  support-9: "$250"
        +  support-10: "교육 기관"
        +  support-11: "$5/학생1인 또는 $500"
        +  support-12: "여러분의 멤버십 기부금은 소프트웨어(p5.js, Processing, Processing.py, Processing for Android Processing for ARM devices)와 코딩 예제 및 튜토리얼 등의 교육 자료 개발, "
        +  support-13: "펠로우십"
        +  support-14: ", 그리고 "
        +  support-15: "커뮤니티 행사"
        +  support-16: "를 지원하는 데에 사용됩니다. 여러분의 도움이 필요합니다!"
        +  support-17: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-18: "프로세싱 재단 펠로우 Saskia Freeke이 런던에서 주관한 Liberation x Processing workshops (이미지 저작권: Code Liberation Foundation)"
        +  support-19: "SPFC와 함께한 Learning to Teach, Teaching to Learn 컨퍼런스 (이미지 저작권: Kira Simon-Kennedy)"
        +  support-20: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
        +  support-21: "Signing Coders p5.js workshop에서의 최태윤(Taeyoon Choi)과 미국 수어(ASL) 해설자 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-22: "구글 썸머 오브 코드(Google Summer of Code) 킥오프 행사 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-23: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
        +  support-24: "최태윤의 수어 기반 p5.js workshop에서 진행을 돕는 Luisa Pereira와 송예슬Yeseul Song (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-25: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-26: "프로세싱 재단 펠로우 Digital Citizens Lab가 International Center of Photography에서 주최한 STEM teaching 패널 (이미지 저작권: International Center of Photography)"
        +  support-27: "칠레 산티아고에서 Aarón Montoya-Moraga가 진행한 p5.js workshop (이미지 저작권: Aarón Montoya-Moraga.)"
        +  support-28: "Claire Kearney-Volpe helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        +  support-29: "프로세싱 재단 펠로우 DIY Girls가 미국 로스 엔젤레스(Los Angeles)에서 진행한 크리에이티브 코딩 프로그램 (이미지 저작권: DIY Girls)"
        +  support-30: "프로세싱 재단 펠로우 Digital Citizens Lab"
        +  support-31: "UCLA DMA와 NYU ITP 간의 동서-해안 p5.js 모임"
        +  support-32: "프로세싱 재단"
        +  support-33: "은 10여년 간의 프로세싱 소프트웨어(Processing Software) 개발 활동을 거쳐, 2012년에 설립되었습니다. 프로세싱 재단의 사명은 시각 예술계에서의 소프트웨어 리터러시와 기술 관련 분야에서의 시각적 리터러시를 증진하고, 나아가 이 두 분야에 대한 보다 많은 사람들의 접근성을 향상하는 데에 있습니다. 우리는 다양한 이해와 배경을 가진 사람들, 특히 코딩 학습을 위한 툴이나 자원에 대한 접근성이 없는 이들이 크리에이티브 코딩을 배울 수 있도록 돕는 것에 목표를 둡니다."
        +  support-17-alt: ""
        +  support-18-alt: ""
        +  support-19-alt: ""
        +  support-20-alt: ""
        +  support-21-alt: ""
        +  support-22-alt: ""
        +  support-23-alt: ""
        +  support-24-alt: ""
        +  support-25-alt: ""
        +  support-26-alt: ""
        +  support-27-alt: ""
        +  support-28-alt: ""
        +  support-29-alt: ""
        +  support-30-alt: ""
        +  support-31-alt: ""
        +
        +learn:
        +  learn-title: "배우기"
        +  learn1: "주제별 깊이있고 순차적인 설명과 튜토리얼을 제공합니다. p5.js 함수에 대해 종류별로 알고싶다면 "
        +  learn2: "예제"
        +  learn3: "를 클릭하세요."
        +  introduction-to-p5js-title: "p5.js 소개"
        +  hello-p5js-title: "Hello p5.js"
        +  hello-p5js: "이 영상을 통해 p5.js 라이브러리가 무엇인지, 또 어떻게 활용할 수 있을지 알아보세요."
        +  getting-started-title: "시작하기"
        +  getting-started: "p5.js에 오신 것을 환영합니다. <br> 이 섹션은 p5.js 프로젝트 설정을 위한 기본적인 내용들을 다룹니다."
        +  p5js-overview-title: "p5.js 주요 기능"
        +  p5js-overview: "p5.js 주요 기능에 대한 개괄 설명을 확인하세요."
        +  p5js-processing-title: "p5.js와 Processing"
        +  p5js-processing: "p5와 Processing 간의 주요 차이점, 그리고 호환 방법을 알아보세요."
        +  p5-screen-reader-title: "p5와 스크린 리더"
        +  p5-screen-reader: "스크린 리더를 위한 p5 설정 방법을 알아보세요."
        +  using-local-server-title: "로컬 서버 사용하기"
        +  using-local-server: "맥 OSX, 윈도우, 리눅스 상에서 로컬 서버 설정하기"
        +  p5js-wiki-title: "p5.js 위키(wiki)"
        +  p5js-wiki: "커뮤니티의 기여로 제작된 레퍼런스와 튜토리얼"
        +  connecting-p5js-title: "p5.js에 연결하기"
        +  creating-libraries-title: "라이브러리 만들기"
        +  creating-libraries: "p5.js 추가 라이브러리 만들기"
        +  nodejs-and-socketio-title: "node.js와 socket.io"
        +  nodejs-and-socketio: "p5.js로 node.js 서버 사용하기, socket.io로 연결, 통신하기"
        +  programming-topics-title: "프로그래밍 주제"
        +  beyond-the-canvas-title: "캔버스 너머서"
        +  beyond-the-canvas: "페이지상 캔버스 너머의 요소들 만들고 조작하기"
        +  3d-webgl-title: "3D/WebGL"
        +  3d-webgl: "WebGL 모드 기반의 고급 그래픽 개발하기"
        +  color-title: "색상"
        +  color: "디지털 색상 소개"
        +  coordinate-system-and-shapes-title: "좌표와 도형"
        +  coordinate-system-and-shapes: "좌표계를 활용하여 간단한 도형 그리기"
        +  interactivity-title: "인터랙션"
        +  interactivity: "마우스 및 키보드 인터랙션 소개"
        +  program-flow-title: "프로그램 흐름(flow)"
        +  program-flow: "p5.js에서 프로그램 플로우 조정하는 법 소개"
        +  curves-title: "곡선"
        +  curves: "p5.js상의 곡선 3가지 소개: 아치형 곡선, 스플라인 곡선, 베지어 곡선"
        +  becoming-a-better-programmer-title: "더 나은 프로그래머 되기"
        +  debugging-title: "디버깅"
        +  debugging: "모두를 위한 디버깅 필드 가이드"
        +  optimizing-title: "ps.js 성능 최적화"
        +  optimizing: "더 빠르고 부드러운 코딩을 위한 최적화 팁"
        +  test-driven-development-title: "유닛 테스팅 및 테스트 기반 개발"
        +  test-driven-development: "설치로 인한 고통에서 벗어나세요. 유닛 테스팅이란 무엇이고 어떻게 사용하는가? 제작: 앤디 티몬스(Andy Timmons)"
        +  contributing-to-the-community-title: "커뮤니티에 함께하기"
        +  development-title: "개발"
        +  development: "개발 기여 시작하기 및 둘러보기"
        +  looking-inside-title: "p5 들여다보기"
        +  looking-inside: "p5.js 개발용 파일 구조 및 도구에 대한 친절한 소개. 제작: 루이자 페레이라(Luisa Pereira)"
        +  writing-tutorial-title: "튜토리얼 만들기"
        +  writing-tutorial: "프로그래밍 튜토리얼 제작 가이드."
        +  writing-a-tutorial-title: "p5.js 튜토리얼 기여를 위한 가이드"
        +  writing-a-tutorial-author: "이 튜토리얼은 테가 브레인(Tega Brain)이 제작하였습니다."
        +  writing-a-tutorial-1: "p5.js 튜토리얼 기여는 이에 열정을 느끼는 교육자와 모든분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 기여 방법 등에 대한 내용을 다룹니다."
        +  writing-a-tutorial-2: "새로운 튜토리얼을 제안하거나, 튜토리얼 준비 및 기여에 대한 가이드라인 제작을 환영합니다."
        +  writing-a-tutorial-how-start-title: "커뮤니티 기여 시작하기:"
        +  writing-a-tutorial-how-start-1: "우선, 제안하려는 튜토리얼이 현재 진행 중인 내용들과 겹치는 지의 여부를 이 "
        +  writing-a-tutorial-how-start-2: "스프레드시트"
        +  writing-a-tutorial-how-start-3: "에서 확인하세요. 만약 제안하고자 하는 튜토리얼 주제가 현재 진행 중인 것이라면, 해당 주제의 마무리 또는 p5.js 웹사이트 공개 작업에 참여할 수 있고 관련해서는 아래의 이메일로 연락을 주시면 감사하겠습니다. "
        +  writing-a-tutorial-how-start-4: "제안하려는 튜토리얼이 스프레드시트 리스트에 포함되지 않는다면, 튜토리얼에 대한 간략한 설명을 education@p5js.org로 보내주세요."
        +  writing-a-tutorial-how-prepare-title: "p5.js 튜토리얼 온라인 공개 준비하기:"
        +  writing-a-tutorial-how-prepare-1: "튜토리얼을 p5.js 웹사이트상 공개할 준비가 되었다면, 다음의 단계를 따라주세요."
        +  writing-a-tutorial-how-prepare-2: "튜토리얼 콘텐츠를 이 "
        +  writing-a-tutorial-how-prepare-3: "기본 구조"
        +  writing-a-tutorial-how-prepare-4: "에 따라 tutorial-name.hbs 파일로 변환해주세요. 콘텐츠에는 아래와 같은 헤더(header)가 반드시 포함되어야 합니다:"
        +  writing-a-tutorial-how-prepare-5: "튜토리얼을 포함한 폴더는 p5js 웹사이트 상 'tutorials' 폴더에 배치됩니다. index.hbs 파일은 "
        +  writing-a-tutorial-how-prepare-6: "p5.js 튜토리얼 랜딩 페이지"
        +  writing-a-tutorial-how-prepare-7: "에 해당하며, test-tutorial.hbs 파일은 테스트 튜토리얼입니다."
        +  writing-a-tutorial-how-prepare-8: "모든 콘텐츠는 페이지상"
        +  writing-a-tutorial-how-prepare-9: "태그에 포함되어야하며, &lt;h1&gt; 와 &lt;h2&gt; 태그, 그리고 &lt;p&gt; 문단 태그로서 문서 형식이 정의되어야 합니다. 형식 예시는 다음의 페이지에서 확인해보세요:  "
        +  writing-a-tutorial-how-prepare-10: "테스트 튜토리얼"
        +  writing-a-tutorial-how-prepare-11: "튜토리얼이 이미지 파일을 포함할 경우, p5 웹사이트의 에셋(assets) 폴더에 배치됩니다. 파일 경로는 아래와 같이 src/assets/learn/test-tutorial/images에 해당합니다."
        +  writing-a-tutorial-how-prepare-12: "페이지의 HTML에 형식을 맞추기 위해 다음의 태그를 사용하세요:"
        +  writing-a-tutorial-embedding-title: "웹페이지에 p5.js 스케치 올리기(embedding)"
        +  writing-a-tutorial-embedding-1: "p5.js를 사용한다는 것은 튜토리얼 설명을 위해 예제에 각종 애니메이션, 인터랙션, 그리고 수정 기능을 포함할 수 있음을 뜻합니다. 이 경우, 튜토리얼 예제는 p5.js 스케치의 형태로 준비되어야하며, 튜토리얼 페이지상 다음의 두가지 방식으로 임베드될 수 있습니다."
        +  writing-a-tutorial-embedding-2: "만약 튜토리얼 예제가 p5.js 웹페이지의"
        +  writing-a-tutorial-embedding-3: "레퍼런스"
        +  writing-a-tutorial-embedding-4: "와 같이 코드를 수정할 수 있는 형태라면, p5js 위젯을 사용하여 HTML 페이지에 임베드할 수 있습니다."
        +  writing-a-tutorial-embedding-5: "이 가이드"
        +  writing-a-tutorial-embedding-6: "를 따라 위젯으로 p5js를 임베드하는 방법에 대해 알아보세요. 가이드는"
        +  writing-a-tutorial-embedding-7: "가 작성하였습니다. 이러한 사례에 해당하는 튜토리얼이 작동하는 모습은 "
        +  writing-a-tutorial-embedding-8: "테스트 튜토리얼 페이지"
        +  writing-a-tutorial-embedding-9: "에서 확인할 수 있습니다."
        +  writing-a-tutorial-embedding-10: "튜토리얼 예제가 애니메이션 그리고/또는 인터랙션을 포함하나 코드 수정 기능을 포함하지 않는다면, 다음과 같이 iframe을 사용하여 p5.js 스케치를 페이지상 임베드할 수 있습니다."
        +  writing-a-tutorial-iframe-title: "iframe을 사용하여 p5 스케치 임베드하기"
        +  writing-a-tutorial-iframe-1: "iframe은 한 페이지상 다른 페이지를 보기 위해 만드는 창문틀과도 같습니다. 이 창문틀을 따라 페이지상의 다른 내용들로부터 구분되는 셈이지요. 이 경우, p5.js 스케치를 포함한 index.html를 보여주는 창문틀의 역할을 합니다. "
        +  writing-a-tutorial-iframe-2: "스크린샷에 보이듯, p5 웹사이트 /src/assets/learn 폴더에 스케치의 이름을 딴 별도의 폴더를 새로이 생성하여 여러분의 튜토리얼용 p5 스케치를 올리세요. 이 경로를 통해 iframe에서 보여줄 모든 이미지와 p5 스케치가 저장됩니다."
        +  writing-a-tutorial-iframe-3: "여러분의 p5 예제를 포함한 폴더의 하위에는 sketch.js 파일과 embed.html 파일이 반드시 있어야 합니다."
        +  writing-a-tutorial-iframe-4: "embed.html 파일이 웹사이트의 p5 라이브러리와도 일치하는지를 확인하세요. 만약, 여러분의 파일 구조가 위와 같다면 p5.js 라이브러리 경로는 \"../../../js/p5.min.js\" 일것 입니다."
        +  writing-a-tutorial-iframe-5: "그리고나면, 튜토리얼 콘텐츠를 담고 있는 .hbs 파일상 p5js index 파일을 iframe의 형태로 임베드할 수 있습니다. iframe 임베드를 위한 코드는 다음과 같습니다: "
        +  writing-a-tutorial-iframe-6: "iframe 서식 바꾸기:  "
        +  writing-a-tutorial-iframe-7: "iframe을 이용한 무제 스케치 작동 확인하기: "
        +  writing-a-tutorial-iframe-8: "위의 스케치가 p5 site에 임베드된 모습:  "
        +  writing-a-tutorial-iframe-9: "한가지 주의해야할 점은, iframe의 사이즈는 반드시 직접 조정해야된다는 것입니다. 특히, 튜토리얼 콘텐츠의 크기가 규격화된 경우 그러합니다."
        +  writing-a-tutorial-iframe-10: "또한, p5.js 라이브러리 파일 연결 링크는 튜토리얼 콘텐츠가 포함되어있는 .eps 페이지가 아닌, 스케치를 렌더링하는 별도의 html 페이지에 위치합니다. (이 경우, 해당 html 페이지의 명칭은 embed.html입니다.)"
        +  writing-a-tutorial-iframe-11: "p5.js 스케치를 임베드하는 방법에 대해 더 알고 싶다면 다음의 링크를 확인하세요: "
        +  writing-a-tutorial-embed-iframe-12: "링크"
        +  writing-a-tutorial-finishing-title: "마무리하기"
        +  writing-a-tutorial-finishing-1: "앞서 언급된 메일을 통해 튜토리얼 콘텐츠 확인을 마쳤다면, p5.js-website repository를 Fork 하세요. 그리고 상기된 방법에 따라 콘텐츠를 준비하고 풀 리퀘스트(pull request)를 하여, 여러분의 기여 내용이 웹사이트에 공개될 수 있도록 하세요!"
        +  writing-a-tutorial-finishing-2: "감사합니다!"
        +  color-description1: "이 튜토리얼은 다니엘 쉬프만(Daniel Shiffman) 저, 모건 카우프만(Morgan Kaufmann) 출판 도서 Learning Processing에서 발췌하였습니다 © 2008 Elsevier Inc. 또한, 발췌본은 켈리 장(Kelly Chang)에 의해 p5로 옮겨졌습니다. 오류를 발견하거나 의견을 남기고 싶다면 "
        +  color-description2: "언제든 알려주세요."
        +  color-p1x1: "디지털 세상에서 색상에 대해 이야기할 땐, 아주 정밀한 표현이 필요합니다. 아쉽게도, \"푸른빛의 초록색 원을 만들 수 있어?\" 와 같은 표현은 통하지 않습니다. 이 곳에서 색상은 언제나 숫자와 범위값에 의해 정의됩니다. 간단한 예시로 시작해볼까요. 검정색, 하얀색, 또는 회색 음영. 0은 검정색을, 255은 하얀색을, 그리고 그 사이에 존재하는 50, 87, 162, 209와 같은 다른 숫자들은 흑과 백 사이의 회색 음영을 뜻합니다."
        +  color-p2x1: "모양을 그리기에 앞서 테두리"
        +  color-p2x2: " 와 면채우기"
        +  color-p2x3: " 함수를 사용하면 색상을 지정할 수 있습니다. 또, 배경"
        +  color-p2x4: " 함수를 통해 윈도우창의 배경색을 지정할 수 있습니다. 한 번 예시를 볼까요."
        +  color-code1: "background(255);    // 배경색을 하얀색으로 정하기 \n stroke(0);          // 테두리(stroke)색을 검정색으로 정하기 \n fill(150);          // 면(fill)색을 회색으로 정하기 \n rect(50,50,75,100); // 사각형 그리기"
        +  color-p3x1: "테두리(Stroke)나 면채우기(fill)는 다음의 함수를 통해 제거할 수 있습니다: "
        +  color-p3x2: " 과"
        +  color-p3x3: ". 본능적으로 우리는 \"stroke(0)\" 를 통해 테두리를 제거할 수 있을 거라 생각하지만, 코딩 언어의 세계에서 0은 \"아무것도 없음\"이 아니라, 검정색을 지칭합니다. "
        +  color-p3x4: " 과 "
        +  color-p3x5: "를 사용하면 선도 색상도, 아무것도 보이지 않을 거에요!"
        +  color-p4x1: "또한, 두개의 도형을 그릴 때 p5.js는 가장 마지막 줄에 지정된 stroke와 fill을 반영합니다. 코드를 위에서부터 아래로 읽고 수행하기 때문이지요."
        +  color-rgb-title: "RGB 색상"
        +  color-rgb-p1x1: "어린 시절 손가락으로 물감을 섞어본 기억이 있나요? 세가지의 \"원색\"을 사용하면, 그 어떠한 색상도 만들어 낼 수 있었지요. 여러가지 물감을 섞다보면 진흙빛의 갈색이 탄생하기도 합니다. 물감을 더할 수록 색이 어두워지고요. 디지털 색상들 역시 삼원색을 섞는 원리를 바탕으로 만들어졌지만, 물감과는 또다르게 작동합니다. 먼저, 디지털 색상에서의 삼원색은 빨강(red), 초록(green), 파랑(blue) (일명, \"RGB\" 색상)을 뜻합니다. 또, 화면상 보이는 색상은 기본적으로 물감이 아닌 빛의 조합입니다. 따라서, 색상이 조합되는 방식이 다른 것이지요."
        +  color-rgb-li1: "빨강 + 초록 = 노랑"
        +  color-rgb-li2: "빨강 + 파랑 = 보라"
        +  color-rgb-li3: "초록 + 파랑 = 청록"
        +  color-rgb-li4: "빨강 + 초록 + 파랑 = 하양"
        +  color-rgb-li5: "무채색 = 검정"
        +  color-rgb-p2x1: "이는 디지털 색상을 밝은 빛으로서 가정하는 데에서 비롯된 것인데, 색상 범위를 조정하여 원하는 색을 만들 수 있습니다. 예를 들어, 빨강색에 초록색, 파랑색을 더하면 회색이 됩니다. 그리고 약간의 빨강색에 약간의 파랑색을 더하면 어두운 보라색이 됩니다. RGB 색상을 더 많이 프로그래밍하고 실험할수록, 손가락으로 물감을 휘젔던 색상 본능만큼 디지털 색상에 따른 본능 역시 커질 것입니다. 한편, 우리는 \"빨강색 적당하게 쓰고 여기에 약간의 파란색을 섞어줘\"라는 식으로도 말할 수 없습니다. 반드시 정확한 양을 지정해야합니다. 회색 음영과 마찬가지로, 각각의 색상 요소는 0(색상 0가지)부터 255(최대한 많은 색상 수)에 이르는 범위 내에서 표현됩니다. 그리고 R, G, B의 순서에 따라 정렬됩니다. 이번엔 좀 더 일반적인 색상에 대해 알아볼까요"
        +  color-transparency-title: "색상 투명도"
        +  color-transparency-p1x1: "R, G, B값에 더해, 각 색상을 구성하는 네 번째 요소가 있습니다. 일명 \"알파(alpha)값\"인데요, 알파는 색상의 투명도를 말하고, 한 도형 위에 다른 도형을 얹을시 겹치는 지점을 보이게 할 때 유용하겠지요? 한 이미지에 대한 여러 알파값들을 통칭 \"알파 채널(alpha channel)\"이라 부르기도 합니다."
        +  color-transparency-p2x1: "픽셀은 그 자체로는 투명하지 않아요. 다만, 여러가지 색상을 섞어 마치 투명해보이는 듯한 착시현상을 만드는 것이지요. 이처럼 p5.js는 한 색상값과 다른 색상값들 간의 비율차를 이용하여 마치 이들이 섞인것처럼 보이게 만든답니다. (만약 여러분이 \"장밋빛\" 안경을 프로그래밍하고자 했다면 바로 이 지점부터 이해하고 넘어가면 되겠지요?)"
        +  color-transparency-p3x1: "알파값은 0부터 255 사이 조정가능합니다. 0은 완전히 투명한 상태(즉, 0% 투명도)이고 255는 완전히 불투명한 상태(즉, 100% 투명도)입니다."
        +  color-custom-ranges-title: "색상 조정 범위"
        +  color-custom-ranges-p1x1: " p5.js에서 다룰 수 있는 색채는 0부터 255까지에 이르는 RGB뿐만이 아닙니다. 사실 우리가 원하는대로 그 범위를 조정할 수도 있지요! 예를 들어, 색상 범위를 마치 퍼센티지처럼 0부터 100으로 설정할 수도 있습니다. 색상 범위 커스터마이징은 다음의 간단한 함수를 통해 가능합니다:"
        +  color-custom-ranges-p2x1: "위의 함수는: \"난 RGB색상에 대해 조정하고싶고, 그 색상 범위는 0부터 100으로 설정하고 싶어\"라고 말하는 것입니다."
        +  color-custom-ranges-p3x1: "조금 더 복잡하긴 하지만, 아래와 같은 방법을 통해 R, G, B 각 색상별로도 조정 범위를 설정할 수 있습니다:"
        +  color-custom-ranges-p4x1: "위의 내용은 \"빨강(R)은 0부터 100까지, 초록(G)은 0부터 500가지, 파랑(B)은 0부터 10까지, 그리고 투명도는 0부터 255까지 설정하고 싶어\"라고 말하는 것이지요."
        +  color-custom-ranges-p5x1: "여러분은 사실상 RGB값 설정만으로도 프로그래밍에 필요한 모든 색상을 누릴 수 있을텐데요, 마지막으로 RGB 외에 조정할 수 있는 색상 요소인 HSB(색조 Hue, 채도 Saturation, 밝기 Brightness)를 소개합니다"
        +  color-custom-ranges-li1x1: "색조 Hue"
        +  color-custom-ranges-li1x2: "—색상의 종류, 기본 범위 0부터 255까지"
        +  color-custom-ranges-li2x1: "채도 Saturation"
        +  color-custom-ranges-li2x2: "—색상의 생생함 정도, 기본 범위 0부터 255까지"
        +  color-custom-ranges-li3x1: "밝기 Brightness"
        +  color-custom-ranges-li3x2: "—(당연히) 색상의 밝은 정도, 기본 범위 0부터 255까지"
        +  color-custom-ranges-p6x1: "이 "
        +  color-custom-ranges-p6x2: " 함수를 이용하여 HSB값 범위 또한 설정할 수 있습니다. 어떤 사람들은 색조(Hue)를 0부터 360까지 설정하거나(위의 사진처럼 360도의 둥근 색상띠가 생각나지요), 채도와 밝기는 0부터 100까지 설정(0-100% 퍼센티지와 유비되지요)하는 것을 선호하기도 합니다."
        +  coordinate-system-description1: "이 튜토리얼은 다니엘 쉬프만(Daniel Shiffman)저, 모건 카우프만(Morgan Kaufmann) 출판 도서 "
        +  coordinate-system-description2: "Learning Processing"
        +  coordinate-system-description3: " 에서 발췌하였습니다.by © 2008 Elsevier Inc. All rights reserved. 또한 발췌본은 알렉스 이쑤안 쑤(Alex Yixuan Xu)에 의해 p5로 옮겨졌습니다. 오류를 발견하거나 의견을 남기고 싶다면 "
        +  coordinate-system-description4: "언제든 알려주세요"
        +  coordinate-system-description5: "."
        +  coordinate-system-description-title: "좌표와 도형"
        +  coordinate-system-description-p1x1: "p5로 프로그래밍을 시작하기 전에, 먼저 중학교 2학년 시절의 우리를 떠올리며 연습장에 선 하나를 그려볼까요? 두 개의 점을 그린 뒤 그 사이를 연결하면 하나의 선분이 탄생합니다. 연습장 위 이 두개의 점과 둘간을 연결하는 선. 바로 여기가 우리의 시작점입니다."
        +  coordinate-system-description-p2x1: "여기 점A(1,0)과 점B(4,5) 사이의 선 하나가 보입니다. 만약 똑같은 선을 친구가 그릴 수 있게하려면 \"1콤마 0에서 시작하는 점에서부터 4콤마 5를 향해 선을 그려죠\"라고 말하겠지요. 이제 그 친구가 컴퓨터라고 가정해볼까요? 우리의 컴퓨터 친구도 똑같은 선을 그리게 하려면 위와 동일한 문장을 입력하면 됩니다. 좀 더 구체적인 형식을 갖춰 컴퓨터 친구에게 말을 건네볼까요?"
        +  coordinate-system-description-p3x1: "코딩 문법에 대해 익숙하지 않더라도 위 문장의 뜻을 어느정도 감잡을 수 있습니다. 우리는 일명 \"함수\"라 불리는 명령문을 통해 컴퓨터와 대화하는 셈입니다. 여기서 \"line\"은 선을 그리는 함수입니다. 여기에 더해, 우리는 이 함수 내에서 구체적인 인수(argument)를 지시할 수 있습니다. 예를 들어, 점 A (1,0)부터 점 B (4,5)까지라는 인수를 함수 괄호 안에 포함 시킨 것이지요. 코드 한 줄을 하나의 문장으로 본다면, 함수는 동사(verb)이고 인수는 목적어(object)인 셈입니다. 단, 코드는 문장과 달리 마침표가 아니라 \"세미콜론(;)\"으로 끝나는 점 주의하세요!"
        +  coordinate-system-description-p4x1: "컴퓨터 화면은 그저 좀 더 멋진 모양새를 갖춘 연습장과도 같습니다. 화면상의 각 픽셀은 x값(가로)과 y값(세로)이라는 두개의 숫자가 합쳐진, 하나의 좌표값과도 같습니다. 그리고 이 좌표로 화면이라는 공간 내의 위치를 정하지요. 이제 우리는 이 픽셀 좌표값에 모양과 색상을 더하면 됩니다."
        +  coordinate-system-description-p5x1: "*** 한가지 주의사항! 우리가 중학교 2학년 때 배운 \"직교 좌표계\"는 (0,0)을 중심에 두고, y축을 그 중심에서 위로, 그리고 x축을 중심으로부터 오른쪽을 향해 뻗어나갑니다(양수일 경우엔 이러하고, 음수일 경우 각각 아래와 왼쪽을 향하지요.) 하지만, 컴퓨터 화면 속 픽셀 좌표계에서의 y축은 그 반대로 적용됩니다. 픽셀 좌표계의 (0,0)은 화면상 좌측 최상단에 위치하고, y값이 증가할 수록 아래를 향해 내려옵니다. x값은 그대로 오른쪽을 향해 증가합니다."
        +  coordinate-system-simple-shapes-title: "간단한 도형"
        +  coordinate-system-simple-shapes-p1x1: "여러분이 앞으로 마주할 p5 기반 프로그래밍 예제들은 본질적으로 시각적이고 조형적입니다. 다음 예제들의 핵심은 모양을 그리고 픽셀을 설정하는 데에 있습니다. 4개의 기본 도형을 살펴보며 시작해볼까요!"
        +  coordinate-system-simple-shapes-p2x1: "위의 모양들을 그리기 위해 필요한 위치와 크기(그 다음, 색상까지도) 정보가 무엇일지 고민해볼까요. 아래의 도식들을 보면, 우리는 먼저 너비 100 픽셀 그리고 높이 100 픽셀에 해당하는 창을 만듭니다."
        +  coordinate-system-simple-shapes-p3x1: "점그리기를 뜻하는 "
        +  coordinate-system-simple-shapes-p3x2: " 함수는 우리가 그릴 수 있는 가장 쉬운 모양이자, 좋은 시작점이 됩니다. 점을 그리기 위해 우리는 x와 y 좌표값만 정하면 되지요."
        +  coordinate-system-simple-shapes-p4x1: "선그리기를 뜻하는 "
        +  coordinate-system-simple-shapes-p4x2: " 함수 역시 아주 어렵진 않습니다. 선을 그리기 위해 우리는 (x1,y1)과 (x2,y2)라는 두개의 좌표값만 필요합니다:"
        +  coordinate-system-simple-shapes-p5x1: "사각형 그리기 함수인 "
        +  coordinate-system-simple-shapes-p5x2: "의 경우 조금 복잡해집니다. p5에서 사각형은 그것이 그려지기 시작하는 상단 좌측의 좌표값과 더불어 너비(width)와 높이(height)를 정하는 숫자들이 필요합니다."
        +  coordinate-system-simple-shapes-p6x1: "사각형을 그리는 또 다른 방법으로, 중앙값, 너비(width), 높이값(height) 설정하기가 있습니다. 이 경우, 먼저 상단의 setup() 함수에 센터 "
        +  coordinate-system-simple-shapes-p6x2: " 모드를 불러오고, 그 뒤에 사각형의 중앙값, 너비, 높이값을 지정해야 합니다. p5는 대문자와 소문자 구분에 민감하니 주의하세요!"
        +  coordinate-system-simple-shapes-p7x1: "마지막으로, 점 두 개 만으로 사각형을 그리는 방법도 있습니다. 바로, 상단 좌측 코너와 하단 우측 코너의 좌표를 지정하는 것이지요. 여기서 우리가 setup() 함수에 포함시킬 모드는 코너 "
        +  coordinate-system-simple-shapes-p7x2: " 입니다. 그 결과물은 위의 예제와 동일합니다."
        +  coordinate-system-simple-shapes-p8x1: "사각형 그리기에 익숙해졌다면, 타원그리기 "
        +  coordinate-system-simple-shapes-p8x2: " 는 식은죽 먹기지요. 타원을 그리는 원리는 "
        +  coordinate-system-simple-shapes-p8x3: " 와 거의 동일하나, 다만 동일한 좌표값을 가진 사각형의 경계선 안쪽에 그려진다는 점에서 차이가 있습니다. "
        +  coordinate-system-simple-shapes-p8x4: " 함수의 기본 모드 설정은 센터 "
        +  coordinate-system-simple-shapes-p8x5: "에 해당합니다. 코너 "
        +  coordinate-system-simple-shapes-p8x6: " 모드로 그리기 위해선 별도 설정이 필요합니다."
        +  coordinate-system-simple-shapes-p9x1: "자, 이제 좀 더 완성도있는 그림을 그려볼까요! 아래의 코드는 200x200 픽셀 크기의 캔버스 위에 여러개의 도형을 그립니다. createCanvas() 함수를 사용하여 캔버스의 너비(width)와 높이(height)를 설정할 수 있습니다."
        +
        +test-tutorial:
        +
        +libraries:
        +  Libraries: "라이브러리"
        +  core-libraries: "주요 라이브러리"
        +  community-libraries: "커뮤니티 라이브러리"
        +  libraries-created-by: "제작: "
        +  p5.sound: "p5.sound는 p5에 웹 오디오 기능(오디오 입력, 재생, 분석 합성 등)을 더해줍니다. "
        +  p5.accessibility: "p5.accessibility는 p5 캔버스에 대한 맹인 또는 시각 장애인의 접근성을 높여줍니다. "
        +  asciiart: "p5.asciiart는 p5js를 아스키(ASCII) 아트로 쉽고 간단하게 변환해줍니다. 즉, p5js를 위한 아스키 아트 컨버터입니다. "
        +  p5.ble: "p5.ble은 BLE 기기와 p5 스케치를 연결해주는 자바스크립트 라이브러리입니다. "
        +  blizard.js: "blizard.js는 DOM 조작을 간단하게 처리해주는 라이브러리입니다. "
        +  p5.bots: "p5.bots를 통해 브라우저와 아두이노(Arduino) 및 여타 마이크로프로세서 간의 인터랙션을 만들 수 있습니다. 센서 데이터로 스케치를 만들거나, 스케치로 LED, 모터, 그 외의 것을 작동시켜 보세요! "
        +  p5.clickable: "이벤트 기반의, 사용이 편리한 p5.js 버튼 라이브러리입니다. "
        +  p5.cmyk.js: "CMYK ColorSpace"
        +  p5.collide2D: "p5.collide2D는 p5.js로 제작된 2D 기하 간의 충돌 감지 계산 툴을 제공합니다. "
        +  p5.createloop: "단 한 줄의 코드로 노이즈와 GIF로 이루어진 애니메이션 루프를 만들어보세요. "
        +  p5.dimensions: "p5.dimensions은 p5.js의 벡터 기능을 확장하여 n차원에서 작동하도록 합니다. "
        +  p5.EasyCam: "패닝, 줌, 회전이 가능한 간단한 3D 카메라 컨트롤. Thomas Diewald가 핵심적으로 기여하였습니다. "
        +  p5.experience: "확장형 p5.js 라이브러리로, 캔버스 기반 웹 어플리케이션 제작을 위한 이벤트리스닝 기능을 추가할 수 있습니다. "
        +  p5.func: "p5.func은 시간(time), 빈도(frequency), 그리고 공간 영역에서의 기능 생성을 위한 새로운 오브젝트와 유틸리티를 제공합니다. "
        +  p5.geolocation: "p5.geolocation은 사용자 위치를 획득, 관찰, 계산, 지오펜싱(geo-fencing)하기 위한 기술을 제공합니다. "
        +  p5.gibber: "p5.gibber는 빠른 속도의 음악 시퀀싱 및 오디오 합성 기능을 제공합니다. "
        +  grafica.js: "grafica.js는 p5.js 스케치상 변형이 쉬운 2D 플롯을 더합니다. "
        +  p5.gui: "p5.gui는 p5.js 스케치를 위한 그래픽 유저 인터페이스를 생성합니다. "
        +  p5.localmessage: "p5.localmessage는 멀티윈도우 스케칭을 위한 스케치 간 로컬 메시지 전송 기능 및 인터페이스를 제공합니다. "
        +  marching: "래스터(raster)에서 벡터(vector)로의 변환, 등면."
        +  mappa: "Mappa는 정적 맵, 타일 맵, 지오 데이터 활용을 위한 툴을 제공합니다. 지리정보 기반의 시각적 재현물을 제작할 때 용이합니다. "
        +  ml5.js: "ml5.js는 Tensorflow.js를 기반으로하며, 머신러닝 알고리즘 및 모델에 대한 브라우저상의 접근성을 높입니다. "
        +  p5.play: "p5.play는 게임과 같은 어플리케이션 제작을 위한 스프라이트(sprite), 애니메이션, 인풋, 충돌 기능을 제공합니다. "
        +  p5.particle: "파티클은 사용자가 제작한 구조 및 기능 또는 JSON 인풋으로 정의된 데이터를 기반으로 한 효과를 만드는 데에 사용됩니다. "
        +  p5.Riso: "p5.Riso는 석판화와 같은 파일을 생성하는 라이브러리입니다. 스케치를 다양한 색상의 판화처럼 만들어줍니다. "
        +  rita.js: "RiTa.js는 제너레이티브 문학을 위한 자연어 처리 오브젝트를 제공합니다. "
        +  RotatingKnobs: "Knob을 만들어 커스텀 그래픽을 회전할 수 있으며, 또 그 범위값을 반환합니다. "
        +  p5.scenemanager: "p5.SceneManager는 스케치를 여러 단계의 씬(scene)들로 구성할 수 있도록 합니다. 각각의 씬은 메인 스케치에 포함된 일부 스케치와도 같습니다. "
        +  p5.screenPosition: "프로세싱의 screenX 및 screenY 기능을 p5js에 적용합니다."
        +  p5.scribble: "2D 기본 조형을 손그림으로 표현합니다. 제작: Janneck Wullschleger, 프로세싱 라이브러리 포트 기반 "
        +  p5.serial: "p5.serial는 시리얼 (RS-232)와 p5 웹 에디터를 지원하는 기기상에서의 직렬 통신을 구현합니다. "
        +  Shape5: "Shape5는 코딩을 처음 배우는 초등학생을 위한 2D 기본 조형 라이브러리입니다."
        +  p5.shape.js: "p5.js 프레임워크에 더 많은 기본 도형을 추가하고자 제작된 라이브러리입니다."
        +  p5.speech: "p5.speech는 웹 스피치 및 스피치 인식 API에 대한 접근 권한을 제공하여, 음성을 인식하고 출력할 수 있는 스케치를 쉽게 만들 수 있게 합니다. "
        +  p5.start2d.js: "픽셀(px), 밀리미터(mm), 센티미터(cm) 또는 인치(inches) 단위를 활용하여 정적 2D 아트를 만들기 위한 p5 확장 라이브러리입니다. "
        +  p5.tiledmap: "p5.tiledmap은 스케치에 지도를 포함하기 위한 드로잉 및 도움 기능을 제공합니다. "
        +  p5.touchgui: "p5.js를 위한 멀티터치 및 마우스 그래픽 유저 인터페이스(GUI) 라이브러리 "
        +  tramontana: "Tramontana는 인터랙티브 환경 및 공간을 창작하거나, 또는 공간에서의 스케일 기능을 프로토타이핑하는 데에 있어 여러가지 기기(iOS, Android, tramontana Board, ...)를 쉽게 쓸 수 있도록 하는 플랫폼입니다. "
        +  vida: "Vida는 카메라(또는 비디오) 기반의 모션 감지 및 얼룩(blob) 트래킹 기능을 더하는 p5js 라이브러리입니다. "
        +  p5.voronoi: "p5.voronoi는 p5.js 스케치상 보로노이 다이어그램을 그리고 활용할 수 있는 툴을 제공합니다. "
        +  p5.3D: "WebGL로 3D 텍스트 및 이미지를 쓸 수 있습니다. "
        +  using-a-library-title: "라이브러리 이용하기"
        +  using-a-library1: "라이브러리란 p5.js의 핵심 기능을 확장하거나 추가하는 자바스크립트 코드를 말합니다. 라이브러리에는 크게 두 종류가 있습니다. 주요 라이브러리인 "
        +  using-a-library3: "의 경우 p5.js 자체 배포물인 반면, 커뮤니티 라이브러리는 커뮤니티 기여자에 의해 개발, 소유, 유지됩니다."
        +  using-a-library4: "스케치에 라이브러리를 사용하려면 우선 스케치에 p5.js 링크를 걸고, 그 다음 HTML 파일에 라이브러리 링크를 걸면 됩니다. 링크가 걸린 HTML 파일은 이렇게 보입니다:"
        +  create-your-own-title: "나만의 라이브러리 만들기"
        +  create-your-own1: "p5.js는 여러분만의 라이브러리 제작을 환영합니다! 라이브러리 제작에 대해 더 알고 싶다면 "
        +  create-your-own2: "라이브러리 튜토리얼"
        +  create-your-own3: "을 확인해보세요. 제작한 라이브러리를 이 페이지에 추가하고 싶다면 "
        +  create-your-own4: "이 문서를 제출하세요!"
        +
        +community:
        +  community-title: "커뮤니티"
        +  community-statement-title: "p5.js 커뮤니티 성명서"
        +  community-statement1: "p5.js는 기술을 재료삼아 예술과 디자인을 창작하는 커뮤니티입니다."
        +  community-statement2: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        +  community-statement3: "우리가 좋아하는 해시태그는 #noCodeSnobs(우리는 효율성보다 커뮤니티를 우선시합니다), #newKidLove(우리는 모두 한 때 초심자였으니깐요!), #unassumeCore(우리는 상대가 무엇을 알고 있는지에 대해 섣불리 가정하지 않습니다), and #BlackLivesMatter (말할 필요도 없이 중요한 사실이지요!) 입니다."
        +  in-practice-title: "실천:"
        +  in-practice1: "우리는 잘난체하는 개발자들이 아닙니다. 우리는 상대가 이미 어떠한 것을 알고 있을거라 섣불리 가정하거나, 모든 사람이 반드시 알아야 할 지식이 있다고 생각하지 않습니다. "
        +  in-practice2: "피드백이 필요한 경우, 언제든 적극적으로 응합니다."
        +  in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 초심자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
        +  in-practice4: "우리는 언제나 모든 형태의 기여와 참여를 적극적으로 인정하고 인증하고자 합니다."
        +  in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다."
        +  in-times-conflict-title: "갈등이 발생할 경우:"
        +  in-times-conflict1: "서로의 생각에 귀 기울입니다. "
        +  in-times-conflict2: "명확한 의사소통을 하되, 타인의 감정을 생각합니다."
        +  in-times-conflict3: "우리가 잘못한 경우에는 그 잘못을 인정하고, 용서를 구하며, 행동에 대한 책임을 집니다. "
        +  in-times-conflict4: "더 나은 우리 자신과 커뮤니티를 향해 지속적으로 노력합니다. "
        +  in-times-conflict5: "서로 존중하며 개방된 자세를 유지합니다. "
        +  in-times-conflict6: "모든 사람의 의견을 존중하고 경청합니다. "
        +  in-times-conflict7: "사려깊고 친절한 태도로 소통합니다. "
        +  in-the-future-title: "미래에 우리는: "
        +  in-the-future1: "지금이 바로 미래입니다."
        +  sharing-title: "공유하기"
        +  sharing1: "이 성명서는 "
        +  sharing2: "크리에이티브 커먼즈(CC) 라이선스"
        +  sharing3: "에 의해 라이선스를 부여받습니다. 출처와 함께 자유롭게 공유하고 응용하셔도 좋습니다."
        +
        +  contribute-title: "함께하기"
        +  contribute1: "우리 커뮤니티는 다양한 방법으로 도움을 줄 수 있는 열정가 분들을 항시 찾고 있습니다. "
        +  develop-title: "개발: "
        +  develop1: "GitHub"
        +  develop2: "는 코드, 버그와 에러, 개발 이슈 등이 문서화되며, 관련 논의가 진행되는 곳입니다. p5.js 개발에 기여하려면"
        +  develop3: " 개발 튜토리얼"
        +  develop4: "을 참고하거나, "
        +  develop5: "라이브러리를 제작해보세요."
        +  document-title: "문서화: "
        +  document1: "문서화 작업은 너무나도 소중하지요! 현재 도움이 필요한 부분으로는 "
        +  document2: "예제 이전하기"
        +  document3: ","
        +  document4: " 문서 추가하기"
        +  document5: ", 그리고 튜토리얼 제작이 있습니다."
        +  teach-title: "가르치기: "
        +  teach1: " 워크샵이나 수업을 통해 친구, 협업자에게 p5.js를 가르치는 것도 좋은 기여 방법입니다. 트위터에서 @p5xjs를 태그해주시면 여러분의 프로젝트를 공유할게요."
        +  create-title: "창작하기: "
        +  create1: " p5.js는 사용자들에게 영감을 줄 수 있는 프로젝트를 웹사이트 첫 페이지에 게재합니다. 디자이너, 예술가, 개발자, 프로그래머, 그 누구의 작업도 좋습니다! 여러분이 만든 창의적인 프로젝트를 다음의 메일 주소로 제출해보세요: "
        +  create2: "hello@p5js.org"
        +  create3: "."
        +  donate-title: "기부하기: "
        +  donate1: " p5.js는 예술가들이 만든 무료 오픈 소스입니다. "
        +  donate2: "프로세싱 재단"
        +  donate3: " 기부를 통해 p5.js를 후원해주세요!"
        +  contributors-conference-title: "p5.js 기여자 컨퍼런스"
        +  contributors-conference1: "대부분의 커뮤니티 활동은 온라인에서 진행되지만, 오프라인에서도 일어난답니다! 그동안 두 차례의 기여자 컨퍼런스가 있었는데요, 미국 피츠버그(Pittsburgh) 소재 카네기 멜론 대학교(Carnegie Mellon University)의 "
        +  contributors-conference2: "에서 진행된 것이 그 중 하나입니다. 예술가, 디자이너, 개발자, 교육자들이 모여 p5.js의 개선 방향에 대해 논의하였습니다."
        +  participants-title: "참여자"
        +  support-title: "지원"
        +  support1: "기여자 컨퍼러스는 카네기 멜론 대학교의"
        +  support2: "에서 열렸습니다. 이 곳은 예술, 과학, 기술, 그리고 문화의 교차점에서, 비정형적, 반-학제적 및 간-기관적 연구를 진행하는 학술랩입니다."
        +  support3: "이 행사는 "
        +  support4: "의 기금과 "
        +  support5: "과"
        +  support6: "의 지원 덕분에 가능했습니다. 감사합니다!"
        +  mailing-list-title: "소식지 받기"
        +  mailing-list-1: "프로세싱 재단의 정기 소식을 수신하려면 이메일 주소를 입력하세요."
        +
        +  2015contributors-conference-title: "2015년 기여자 컨퍼런스"
        +  2015contributors-conference-date: "5월 25-31일"
        +  2015contributors-conference1: "약 30여명의 참여자들이 "
        +  2015contributors-conference2: "에 모여, p5.js의 프로그래밍 코드와 문서화 작업을 진전시키고, 커뮤니티를 확장하는 방안에 대해 논의하였습니다. 멀리서는 홍콩, 그리고 시애틀, 로스 엔젤레스, 보스턴, 뉴욕 등지에서 찾아온 참여자들이 함께하였습니다. 대부분의 참여자들이 크리에이티브 기술, 인터랙션 디자인, 그리고 뉴미디어 아트 분야의 전문 종사자였고, 카네기 멜론 미술 및 건축 대학교 출신의 학부생 및 대학원생도 6명 정도 포함하였습니다."
        +  2015contributors-conference3: "사진 촬영: 최태윤(Taeyoon Choi)"
        +  2015contributors-conference-diversity-title: "다양성"
        +  2015contributors-conference-diversity1: "기술 개발 문제 외에도 중요하게 다루어졌던 컨퍼런스 주제는 커뮤니티, 확장, 다양성이었습니다. 컨퍼런스는 패널"
        +  2015contributors-conference-diversity2: "다양성: 인종, 젠더, 능력에 대한 7가지의 목소리 &amp; FLOSS와 인터넷을 위한 수업"
        +  2015contributors-conference-diversity3: "과 함께 시작하였습니다. "
        +  2015contributors-conference-diversity4: "패널 진행은 "
        +  2015contributors-conference-diversity5: "과"
        +  2015contributors-conference-diversity6: "가 맡았으며, "
        +  2015contributors-conference-diversity7: "2015년 5월 25일 화요일 카네기 멜론 대학교 Kresge Auditorium 에서 열렸습니다. 연사는"
        +  2015contributors-conference-diversity8: "과"
        +  2015contributors-conference-diversity9: "였습니다."
        +  2015cc_1: "다양한 배경 출신의 참여자들이 미소를 지으며 손으로 p5 사인을 만드는 모습"
        +  2015cc_2: "잔디 위에서 뛰놀고, 웃으며, 손을 하늘 위로 들어올리는 참여자들의 모습"
        +  2015cc_3: "노트북으로 p5.js 커뮤니티 성명서를 발표하고 있는 여성"
        +  2015cc_4: "마이크에 대고 열정적으로 말하고 있는 여성과 그를 쳐다보는 남성 협력자 두 명"
        +  2015cc_5: "미소를 띄우며 발표를 경청하는 참여자들 모습"
        +  2015cc_6: "마이크에 대고 3명의 여학생들을 향해 p5.js를 설명하는 여성"
        +  2015cc_7: "여학생 한명이 마이크에 대고 발표하는 동안, 포스트잇이 붙은 화이트보드를 둘러앉은 참여자들의 모습"
        +  2015cc_8: "책상에 둘러앉아 서로의 노트북을 보며 코드를 비교하는 참여자들의 모습"
        +  2015cc_9: "프로그래밍에 대한 노트가 적힌 여러가지 색의 포스트잇이 화이트보드에 붙어있는 모습"
        +  2015cc_10: "한 교실에서 다양한 기술 능력의 가치를 존중하는 것에 대해 발표하는 여성과 그의 파워포인트를 바라보는 참여자들의 모습"
        +  2015cc_11: "대강당 무대 위 단상에서 발표하는 여성과 무대에 앉아있는 세명의 참여자들, 그리고 무대 위 스크린상의 스카이프 화면을 통해 보이는 또다른 세명의 원격 참여자들"
        +  2015cc_12: "노트북으로 작업하는 참여자들이 있는 교실 전경"
        +  2015cc_13: "둥그렇게 앉아 토론하는 5명의 사람들"
        +  2015cc_14: "노트북과 함께 둥그렇게 앉아 자신의 필기를 공유하는 5명의 사람들"
        +  2015cc_15: "교실에서 참여자들을 향해 마이크로 발표하는 남성"
        +  2019contributors-conference-title: "2019년 기여자 컨퍼런스"
        +  2019contributors-conference-date: "8월 13-18일"
        +  2019contributors-conference1: "다학제적 배경을 지닌 35명의 참여자들이 "
        +  2019contributors-conference2: "에 모여 p5.js의 프로그래밍 환경과 그 현주소를 탐색하고, 코드 및 문서 개발, 그리고 커뮤니티 확장 방법에 대해 논의하였습니다. 참여자들은 크리에이티브 기술, 인터랙션 디자인, 뉴미디어 아트를 아우르는 다양한 분야의 종사자들로 구성되었으며, 컨퍼런스에서의 논의는 이러한 다학제적인 시각을 바탕으로 진행되었습니다. 참여자 그룹은 접근성, 퍼포먼스 속 음악과 코딩, 크리에이티브 기술 지형, 그리고 국제화를 포함한 여러 주제에 초점을 두었습니다." 
        +  2019contributors-conference3: "비디오 촬영: 치안치안 예(Qianqian Ye)"
        +  2019contributors-conference4: "사진 촬영: 재클린 존슨(Jacquelyn Johnson)"
        +  outputs: "결과물"
        +  output1: ". p5.js를 위한 아주 유연한 삼각형, 사각형, 육각형, 그리고 팔각형 묶음 구현. 제작: 아렌 데이비(Aren Davey)"
        +  output2: ". 복수의 클라이언트를 특정 호스트 페이지에 연결하는 멀티디바이스 및 멀티플레이어 게임을 위한 템플릿 파일. 제작: L05"
        +  output3: ""
        +  output3-1: "를 이용한 실험들. softCompile 및 OSC 인터페이스 초기 단계 구현과 더불어 MIDI 셋업에 연결한 데모. p5.js 협업 라이브 코딩 VJ 환경 구현. 제작: 테드 데이비스(Ted Davis)"
        +  output4: "가상 공간에서의 블랙니스(Blackness)와 젠더를 다룬 패널, 아메리칸 아티스트(American Artist)이 진행하고 shawné michaelain holloway와 LaJuné McMillian이 함께함."
        +  output5: "에베레스트 핍킨(Everest Pipkin)과 존 챔버스(Jon Chambers)가 진행한 워크숍"
        +  output6: ""
        +  output6-1: "p5.js를 위한 노트북 인터페이스"
        +  output6-2: "의 프로토타입. 제작: 앨리슨 패리쉬(Allison Parrish)"
        +  output7: "새로운 설치 예술 작품. 제작: Stalgia Grigg, LaJuné McMillian, Aatish Bhatia, 그리고 Jon Chambers."
        +  output8: "p5.js의 전세계 기여자를 위한 툴킷"
        +  output8-1: "제작: Aarón Montoya-Moraga, Kenneth Lim, Guillermo Montecinos, Qianqian Ye, Dorothy R. Santos, 그리고 Yasheng She."
        +  output9: "비폭력적 크리이에티브 코드 작성법. "
        +  output9-1: "올리비아 로스(Olivia Ross) 진행 잡지."
        +  output10: "p5.js 웹사이트의 접근성에 대한 점검. 스크린 리더 접근성 향상 기능을 비롯하여, 홈, 다운로드, 시작하기, 레퍼런스 페이지 등을 업데이트. 기여: Claire Kearney-Volpe, Sina Bahram, Kate Hollenbach, Olivia Ross, Luis Morales-Navarro, Lauren McCarthy, 그리고 Evelyn Masso"
        +  output11: "협업 퍼포먼스. 제작: Luisa Pereira, Jun Shern Chan, Shefali Nayak, Sona Lee, Ted Davis, 그리고 Carlos Garcia."
        +  output12: "퍼포먼스. 제작: 나탈리 브래긴스키(Natalie Braginsky)"
        +  output13: "p5 에디터를 위한 p5.js 라이브러리 시스템 디자인. 제작: 캐시 타라카지안(Cassie Tarakajian)과 루카 다마스코(Luca Damasco)"
        +  output14: "p5와 다른 라이브러리 연결을 위한 프로토타입들. 제작: 알렉스 이쑤안 쑤(Alex Yixuan Xu)와 로렌 밸리(Lauren Valley)"
        +  output15: "클로징 캠프파이어. 진행: 골렌 레빈(Golan Levin)"
        +  2019cc_1: "단상 위에서 한 그룹을 향해 발표를 하는 남성"
        +  2019cc_2: "긴 테이블에 앉아 점심을 먹으며 토론하는 참여자들"
        +  2019cc_3: "교실 속 참가자들의 모습으로, 어떤 이들은 노트북으로 작업하고, 다른 이들은 대화를 나눈다"
        +  2019cc_4: "교실에서 노트북으로 작업하는 참여자들의 모습"
        +  2019cc_5: "어두운 교실에서 미팅을 하는 참여자들"
        +  2019cc_6: "여러 참여자들이 모인 교실에서 발표를 하는 여성"
        +  2019cc_7: "많은 이들이 모여있는 교실에서 대화를 나누는 참가자들"
        +  2019cc_8: "한 교실에서 동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_9: "데이터 익명화의 문제점에 대한 글이 투사된 스크린과 그 앞 단상에서 말하는 참여자"
        +  2019cc_10: "\"p5.js는 접근성을 증진을 위한 기능 외에는 새로운 기능을 추가하지 않을 것입니다\"라고 적힌 텍스트 앞에 서서, 동료 참여자를 향해 마이크에 대고 말하는 사람"
        +  2019cc_11: "동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_12: "동료 참여자를 향해 마이크에 대고 말하는 남성"
        +  2019cc_13: "교실 속, 경청 중인 발표자들을 향해 앉아있는 참여자들"
        +  2019cc_14: "교실 속, 경청 중인 발표자를 마주하고 있는 참여자들"
        +  2019cc_15: "\"신성한 경계\"라 적힌 스크린을 뒤로하고, 동료 참여자를 향해 마이크에 대고 말하는 여성"
        +  2019cc_16: "3D 렌더링된 사람 이미지를 보여주는 패널에 경청하는 참여자들 전경"
        +  2019cc_17: "노트북과 함께 테이블에 둘러앉아 TV 스크린 상의 코드를 살펴보는 참여자들"
        +  2019cc_18: "등신 크기의 테디 베어 옆에 앉아 노트북으로 작업하는 여성"
        +  2019cc_19: "밖에 나와 미소를 짓는 참여자들"
        +  2019cc_20: "동그랗게 모여 서서 대화를 나누는 4명의 참여자들"
        +  2019cc_21: "밖에 나와 앉아 함께 점심을 먹는 참여자들"
        +  2019cc_22: "거대한 U자형 테이블에 둘러앉아 교실 앞쪽을 쳐다보는 참여자들"
        +  2019cc_23: "교실 앞에 앉아 마이크에 대고 활력적으로 말하는 남성"
        +  2019cc_24: "하늘 향해 손을 들고 활기차게 미소짓는 모습이 담긴 참여자 단체 사진"
        +  2019cc_25: "LCD 모니터로 만들어진 캠프파이어에 둘러앉은 사람들"
        +
        +books:
        +  books-title: "출판물"
        +
        +examples:
        +  Examples: "예제"
        +  back-examples: "예제로 돌아가기"
        +  Structure: "구조"
        +  Form: "도형"
        +  Data: "데이터"
        +  Arrays: "배열"
        +  Control: "컨트롤"
        +  Image: "이미지"
        +  Color: "색상"
        +  Math: "수학"
        +  Simulate: "시뮬레이션"
        +  Interaction: "인터랙션"
        +  Objects: "오브젝트"
        +  Lights: "라이트"
        +  Motion: "모션"
        +  Instance_Mode: "인스턴스 모드"
        +  Dom: "DOM"
        +  Drawing: "드로잉"
        +  Transform: "변형"
        +  Typography: "타이포그래피"
        +  3D: "3D"
        +  Input: "입력"
        +  Advanced_Data: "고급 데이터"
        +  Sound: "사운드"
        +  Mobile: "모바일"
        +  Hello_P5: "Hello p5"
        +
        +reference:
        +  Reference: "레퍼런스"
        +
        +showcase:
        +  showcase-title: "쇼케이스"
        +  showcase-intro1: "쇼케이스 페이지는 p5.js를 보다 흥미진진하고 포용적으로 만든 창작물, 학습물, 오픈 소스 사례들을 기쁘게 소개하고자 합니다. 쇼케이스 페이지 기획 및 제작: 애슐리 강 " 
        +  showcase-intro2: "이렇게 우리는 함께 커뮤니티를 만들어 나가는게 아닐까요?:)"
        +  showcase-intro3: "2019년 여름, 몇몇 창작자들에게 그들의 p5.js 기반의 프로젝트 소개를 요청하였습니다. 아래의 버튼을 눌러 자신 또는 타인의 p5.js 작품을 추천해보세요!"
        +  showcase-featuring: "Featuring"
        +  project-tag-art: "예술"
        +  project-tag-design: "디자인"
        +  project-tag-code: "코드"
        +  project-tag-curriculum: "커리큘럼"
        +  project-tag-documentation: "문서화"
        +  project-tag-game: "게임"
        +  project-tag-library: "라이브러리"
        +  project-tag-organizing: "행사 또는 모임"
        +  project-tag-tool: "툴"
        +  project-tag-tutorial: "튜토리얼"
        +  project-roni: "프로그래밍된 각도기 드로잉(Programmed Plotter Drawings)"
        +  credit-roni: "Roni Cantor"
        +  description-roni: "p5.js로 제작한 싸인파(Sine wave)와 선형 보간(lerp)으로, 실물 각도기와 펜과 연결되어 드로잉하고, SVG 파일로 내보내기 가능."
        +  project-phuong: "Airi Flies"
        +  credit-phuong: "Phuong Ngo"
        +  description-phuong: "p5.play로 제작된 게임으로, PEW라고 말해 Airi가 날 수 있도록 돕는다. 사용자들이 자신의 안전 지대를 벗어난 곳에서도 행동, 외모, 발언에 상관없이 자신감을 갖게하고자 하는 취지에서 제작."
        +  project-daein: "Chillin'"
        +  credit-daein: "정대인 (Dae In Chung)"
        +  description-daein: "모바일 기기의 모션 센서와 p5.js를 활용한, 인터랙티브 타이포그래픽 포스터"
        +  project-qianqian: "Qtv"
        +  credit-qianqian: "Qianqian Ye"
        +  description-qianqian: "초심자를 위한 p5.js 튜토리얼을 포함하여, 코딩, 예술, 그리고 기술에 대해 다루는 1분 길이의 중국어 영상 채널들. 유투브, 인스타그램, 비리비리(Bilibili), 틱톡(TikTok)에서 확인 가능."
        +  project-casey-louise: "p5.js 셰이더(Shaders)"
        +  credit-casey-louise: "Casey Conchinha, Louise Lessél"
        +  description-casey-louise: "셰이더(Shaders)란 무엇이고, 이를 p5.js에서 왜, 그리고 어떻게 사용하는지 배울 수 있는 자료."
        +  project-moon-xin: "움직이는 반응형 포스터(Moving Responsive Posters)"
        +  credit-moon-xin: "Moon Jang, Xin Xin, 그리고 학생들"
        +  description-moon-xin: "브라우저 기반의 움직이는 포스터로, 그래픽 시스템과 변형 메소드, 그리고 p5.js를 사용하여 8자 미만 단어가 내포하는 바를 표현. 조지아 대학교(University of Georgia)의 그래픽 디자인 과정인 'Visual Narrative Systems'의 수강생들이 디자인."
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        new file mode 100644
        index 0000000000..9e24eb2b20
        --- /dev/null
        +++ b/src/data/reference/ko.json
        @@ -0,0 +1,280 @@
        +{
        +  "Home": "홈",
        +  "Download": "다운로드",
        +  "Start": "시작하기",
        +  "Reference": "레퍼런스",
        +  "reference-tagline": "프로세싱의 직관성에 자바스크립트의 강력함을 곱하다*",
        +  "reference-search": "API 검색",
        +  "reference-menu-home": "홈",
        +  "reference-menu-download": "다운로드",
        +  "reference-menu-get-started": "시작하기",
        +  "reference-menu-reference": "레퍼런스",
        +  "reference-menu-libraries": "라이브러리",
        +  "reference-menu-learn": "배우기",
        +  "reference-menu-examples": "예제",
        +  "reference-menu-books": "출판물",
        +  "reference-menu-community": "커뮤니티",
        +  "reference-menu-forum": "포럼",
        +  "reference-description1": "찾는 항목이 없다면, 다음의 페이지를 살펴보세요:",
        +  "reference-description2": " 또는 ",
        +  "reference-description3": "오프라인 버전의 레퍼런스는 다음 링크에서 다운받을 수 있습니다: ",
        +  "reference-description4": "레퍼런스 다운로드",
        +  "reference-contribute1": "잘못된 부분이나 제안사항이 있다면",
        +  "reference-contribute2": "언제든 알려주세요",
        +  "reference-error1": "오타나 버그를 발견했다면",
        +  "reference-error2": "관련 문서는 이곳에 있습니다: ",
        +  "reference-error3": "p5.js에 기여하고 싶다면, ",
        +  "reference-error4": "파일을 수정하고",
        +  "reference-error5": "에 풀 리퀘스트(pull request) 해주세요!",
        +  "reference-example": "예제",
        +  "reference-description": "설명",
        +  "reference-extends": "확장",
        +  "reference-parameters": "변수",
        +  "reference-syntax": "문법",
        +  "reference-returns": "반환(return)",
        +  "footer1": "p5.js는 ",
        +  "footer2": "가 창안하고 협력자 커뮤니티와 함께 개발되었습니다. 지원: 프로세싱 재단 ",
        +  "footer3": " 과 ",
        +  "footer4": " 아이덴티티 및 그래픽 디자인:",
        +  "Libraries": "라이브러리",
        +  "Learn": "배우기",
        +  "Examples": "예제",
        +  "Books": "출판물",
        +  "Community": "커뮤니티",
        +  "Contribute": "함께하기",
        +  "Forum": "포럼",
        +  "h1": "레퍼런스",
        +  "Color": "색상",
        +  "Shape": "도형", 
        +  "Creating & Reading": "만들기 & 읽기", 
        +  "Setting": "설정하기", 
        +  "2D Primitives": "2D 기본 조형", 
        +  "Attributes": "Attributes",  
        +  "Curves": "곡선 Curves", 
        +  "Vertex": "버텍스 Vertex", 
        +  "3D Models": "3D 모델",  
        +  "3D Primitives": "3D 기본 조형", 
        +  "Constants": "상수",  
        +  "Structure": "구조",  
        +  "Environment": "환경",  
        +  "DOM": "DOM", 
        +  "Rendering": "렌더링",  
        +  "Transform": "변형(Transform)", 
        +  "Data": "데이터",  
        +  "Dictionary": "사전(Dictionary)",  
        +  "Array Functions": "배열 기능",  
        +  "Conversion": "변환(Conversion)", 
        +  "String Functions": "문자열(String) 기능",  
        +  "Events": "이벤트",  
        +  "Acceleration": "가속",  
        +  "Keyboard": "키보드",  
        +  "Mouse": "마우스", 
        +  "Touch": "터치", 
        +  "Image": "이미지",  
        +  "Loading & Displaying": "로딩 & 디스플레이", 
        +  "Pixels": "픽셀",  
        +  "IO": "IO", 
        +  "Input": "입력(Input)", 
        +  "Output": "아웃풋", 
        +  "Table": "테이블", 
        +  "Time & Date": "날짜 & 시간",  
        +  "XML": "XML", 
        +  "Math": "수학", 
        +  "Calculation": "계산",  
        +  "Noise": "노이즈", 
        +  "Trigonometry": "삼각법",  
        +  "Typography": "타이포그래피", 
        +  "Font": "폰트", 
        +  "Lights, Camera": "라이트, 카메라",  
        +  "Camera": "카메라",  
        +  "Lights": "라이트"",  
        +  "Material": "재질(Material)",
        +  "p5": {
        +    "background": {
        +      "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 일회적으로 설정할 경우 setup() 함수 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.",
        +      "params": ["p5.Color: color() 함수를 통해 만들어진 값",
        +               "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex",
        +               "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        +               "숫자: 흑백 채도를 설정함",
        +               "숫자: 선택한 컬러모드에 따라, red값 혹은 hue값",
        +               "숫자: 선택한 컬러모드에 따라, green값 혹은 saturation값",
        +               "숫자: 선택한 컬러모드에 따라, blue값 혹은 brightness값",
        +               "숫자 배열[]: red, green blud와 투명도를 포함한 배열",
        +               "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 창과 같은 사이즈여야 함)"],
        +      "returns": "the p5 object"
        +    },
        +    "clear": {
        +      "description": "버퍼 내의 픽셀을 클리어합니다. 본 함수는 createCanvas() 함수로 만들어진 p5.Canvas 오브젝트에만 적용되며, 메인 디스플레이 윈도우에 사용할 수는 없습니다. 메인 그래픽 영역에서와 다르게, createGraphics()를 이용해 생성한 추가 그래픽 영역 내에 있는 픽셀은 완전히 혹은 부분적으로 투명하게 만들 수 있습니다. clear() 함수는 모든 픽셀을 100% 투명하게 만듭니다.",
        +      "returns": "the p5 object"
        +    },
        +    "colorMode": {
        +      "description": "colorMode()는 p5.js가 색 데이터를 해석하는 방식을 결정합니다. fill(), stroke(), background(), color()의 매개변수의 초기값은 RGB 컬러모드이며, 범위는 0에서 255까지, 즉 colorMode(RGB, 255) 입니다. colorMode(HSB)로 설정하는 경우 HSB 컬러 시스템을 사용할 수 있는데, 초기값은 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 컬러모드를 HSL을 설정하는 것도 가능합니다. 참고: 이미 존재하는 컬러 오브젝트들은 자신이 생성되었을 당시의 모드를 기억합니다. 따라서, 이미 존재하는 컬러 오브젝트에 영향을 미치지 않으면서 컬러모드는 바꾸는 것이 가능합니다.",
        +      "params": ["상수(Constante): RGB (Red/Green/Blue), HSB (Hue/Saturation/Brightness), HSL (Hue/Saturation/Lightness) 중 하나",
        +      "숫자: 현재 컬러모드에 따라 red 혹은 hue 범위",
        +      "숫자: 현재 컬러모드에 따라 green 혹은 saturation 범위.",
        +      "숫자: 현재 컬러모드에 따라 blue 혹은 brightness/lightness 범위.",
        +      "숫자: 투명도 범위"],
        +      "returns": "the p5 object"
        +    },
        +    "fill": {
        +      "description": "도형을 칠할 색을 선택합니다. 예를 들어 fill(204, 102, 0)을 실행하면 해당되는 모든 도형들의 색이 주황색으로 바뀝니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.",
        +      "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값",
        +      "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값",
        +      "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값",
        +      "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        +      "문자열: 문자열로 된 색상값",
        +      "숫자: 흑백 채도를 설정함",
        +      "숫자 배열[]: red, green blue와 투명도를 포함한 배열",
        +      "p5.Color" ],
        +      "returns": "the p5 object"
        +    },
        +    "noFill": {
        +      "description": "도형에 색을 채우지 않도록 설정합니다. noStroke() 과  noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.",
        +      "returns": "the p5 object"
        +    },
        +    "noStroke": {
        +      "description": "선이나 윤곽선을 그리지 않도록 설정합니다. noStroke() 과  noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.",
        +      "returns": "the p5 object"
        +    },
        +    "stroke": {
        +      "description": "선을 그리거나 도형 윤곽선 색을 설정합니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.",
        +      "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값",
        +      "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값",
        +      "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값",
        +      "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        +      "문자열: 문자열로 된 색상값",
        +      "숫자: 흑백 채도를 설정함",
        +      "숫자 배열[]: red, green blud와 투명도를 포함한 배열",
        +      "p5.Color"],
        +      "returns": "the p5 object"
        +    },
        +    "arc": {
        +      "description": "화면에 호를 그립니다. 모드 선택 없이 x, y, w, h, 시작, 끝만을 지정하면 호는 열린 파이조각 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫혀진 반원(CHORD), 닫혀진 파이조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 본 함수를 이용해 시작점을 0, 끝점을 TWO_PI로 설정해 원 전체를 그리려 시도하면, 시작점과 끝점이 같기 때문에 아무것도 그려지지 않습니다. 원 전체를 그릴때는 ellipse() 함수를, 원 일부를 그릴 때는 arc() 함수를 이용하세요.",
        +      "params": ["숫자: 호를 포함하는 원의 x 좌표",
        +      "숫자: 호를 포함하는 원의 y 좌표",
        +      "숫자: 호를 포함하는 원의 너비",
        +      "숫자: 호를 포함하는 원의 높이",
        +      "숫자: 시작점의 각도로, 호도(radians)로 설정",
        +      "숫자: 끝점의 각도로, 호도(radians)로 설정",
        +      "상수: 호를 그리는 방식을 설정함. CHORD, PIEC, OPEN 중 선택. 필수 변수는 아니며 필요한 경우에만 사용하면 됨.",
        +      "숫자: WEBGL 모드에서만 사용하며, 호의 윤곽선을 구성하는 점(vertices)의 숫자를 지정한다. 필수 변수는 아니며 필요한 경우에만 사용하면 됨. 초기값은 25이다."],
        +      "returns": "the p5 object"
        +    },
        +    "ellipse": {
        +      "description": "스크린에 타원을 그립니다. 너비와 높이가 같은 경우에는 원이 그려집니다. 첫 두 변수는 위치를, 세번째 네번째 변수는 도형의 너비와 높이를 설정합니다. 높이를 설정하지 않으면 너비 값이 높이로도 사용됩니다. 너비나 높이를 음수로 입력하면, 자동적으로 절대값이 사용됩니다. 원 시작점을 원의 중심으로 둘지의 여부는 ellipseMode() 함수를 이용해 변경할 수 있습니다.",
        +      "params": ["숫자: 원의 x 좌표",
        +      "숫자: 원의 y 좌표",
        +      "숫자: 원의 너비",
        +      "숫자: 원의 높이",
        +      "정수: 원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WEGBL 모드용)"],
        +      "returns": "the p5 object"
        +    },
        +    "circle": {
        +      "description": "화면에 원을 그립니다. 원은 단순한 단일폐곡선으로, 중심점으로부터 같은 좌표에 위치한 점들의 집합입니다. 원은 너비와 높이가 동일한 타원으로 ellipse() 함수를 이용해 그리는 것도 가능합니다. 이 경우 타원의 너비와 높이는 원의 지름과 동일합니다. 본 함수의 첫번째 두번째 변수는 원의 중심점을, 세번째 변수는 지름을 설정합니다.",
        +      "params": ["숫자: 원 중심점의 x 좌표",
        +      "숫자: 원 중심점의 y 좌표",
        +      "숫자: 원의 지름"],
        +      "returns": "the p5 object"
        +    },
        +    "line": {
        +      "description": "화면에 선, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하는 경우 이차원 평면에 선을 그립니다. 선의 색을 지정하려면 stroke() 함수를 이용하세요. 선은 면은 가지고 있지 않기 때문에 면 색을 채우는 fill() 함수는 적용되지 않습니다. 선의 굵기 초기값은 1픽셀이며 이를 변경하기 위해서는 strokeWeight() 함수를 이용합니다.",
        +      "params": ["숫자: 첫번째 점의 x 좌표",
        +      "숫자: 첫번째 점의 y 좌표",
        +      "숫자: 두번째 점의 x 좌표",
        +      "숫자: 첫번째 점의 y 좌표",
        +      "숫자: 첫번째 점의 z 좌표",
        +      "숫자: 두번째 점의 z 좌표"],
        +      "returns": "the p5 object"
        +    },
        +    "point": {
        +      "description": "Dibuja un punto, una coordenada en el espacio de un pixel de dimensión. El primer parámetro es la coordenada horizontal del punto, el segundo valor es la coordenada vertical del punto. El color del punto es determinado por el trazado actual con la función stroke().",
        +      "params": ["숫자: x 좌표",
        +      "숫자: y 좌표",
        +      "숫자: z 좌표 (WEBGL 모드 사용시)"],
        +      "returns": "the p5 object"
        +    },
        +    "quad": {
        +      "description": "네모꼴을 그립니다. 네모꼴은 4개의 변을 가진 다각형으로, 직사각형과 유사해 보이지만 직사각형과 다르게 변 사이의 각도가 90도로 고정되어 있지 않습니다. 첫 한 쌍의 변수는 첫 꼭지점을 설정하며 뒤따르는 다른 쌍의 변수들은 시계방향이나 반시계방향으로 차례대로 꼭지점을 설정합니다. z 변수는 WEBGL모드에서 quad() 함수를 사용하는 경우에만 적용됩니다.",
        +      "params": ["숫자: 첫번째 꼭지점의 x 좌표",
        +      "숫자: 첫번째 꼭지점의 y 좌표",
        +      "숫자: 두번째 꼭지점의 x 좌표",
        +      "숫자: 두번째 꼭지점의 y 좌표",
        +      "숫자: 세번째 꼭지점의 x 좌표",
        +      "숫자: 세번째 꼭지점의 y 좌표",
        +      "숫자: 네번째 꼭지점의 x 좌표",
        +      "숫자: 네번째 꼭지점의 y 좌표",
        +      "숫자: 첫번째 꼭지점의 z 좌표",
        +      "숫자: 두번째 꼭지점의 z 좌표",
        +      "숫자: 세번째 꼭지점의 z 좌표",
        +      "숫자: 네번째 꼭지점의 z 좌표"],
        +      "returns": "the p5 object"
        +    },
        +    "rect": {
        +      "description": "화면에 직사각형을 그립니다. 직사각형은 변이 네개이면서 모든 각도가 90도인 도형입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 사각형의 너비를, 네번째 변수는 높이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 다섯번째, 여섯번째, 일곱번째, 여덟번째 변수를 입력하는 경우 각각의 숫자는 차계로 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 지정합니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.",
        +      "params": ["숫자: 직사각형의 x 좌표값",
        +      "숫자: 직사각형의 y 좌표값",
        +      "숫자: 직사각형의 너비",
        +      "숫자: 직사각형의 높이",
        +      "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "정수: x 방향의 segment 수 (WEBGL 모드에서 사용)",
        +      "정수: y 방향의 segment 수 (WEBGL 모드에서 사용)"],
        +      "returns": "the p5 object"
        +    },
        +    "square": {
        +      "description": "화면에 정사각형을 그립니다. 정사각형은 변이 네개이면서 모든 각도가 90도이며 네 변의 길이가 같은 도형입니다. 정사격형은 사실상 rect() 함수로도 그릴 수 있는 도형으로, 너비와 높이가 모두 s로 같은 직사각형인 셈입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 한 변의 길이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 네번째, 다섯번째, 여섯번째, 일곱번째 변수를 입력해 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 각각 지정할 수 있습니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.",
        +      "params": ["숫자: 정사각형의 x 좌표값",
        +      "숫자: 정사각형의 y 좌표값",
        +      "숫자: 정사각형 한 변의 길이",
        +      "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        +      "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력."],
        +      "returns": "the p5 object"
        +    },
        +    "createCanvas": {
        +      "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를  참고하세요.",
        +      "params": ["숫자: 캔버스의 너비",
        +      "숫자: 캔버스의 높이",
        +      "상수: P2D 또는 WEBGL"]
        +    },
        +    "loadImage": {
        +      "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.",
        +      "params": ["문자열: 불러올 이미지 경로",
        +      "함수(p5.Image): 이미지를 불러온 후 호출할 함수",
        +      "함수(Event): 이미지 불러오기를 실패하는 경우에 호출할 함수"]
        +    },
        +    "image": {
        +      "description": "p5.js 캔버스에 이미지를 배치합니다. 본 함수를 사용하는 몇가지 방법을 소개하자면 다음과 같습니다. (1) 가장 간단한 방법은 img, x, y 세 개의 변수를 사용하는 방법입니다. x, y는 이미지의 위치를 지정합니다. (2) 이미지의 크기를 설정하려면 img, x, y와 더불어 이미지의 너비와 높이를 설정하는 두개의 변수를 추가로 사용합니다. (3) 여덟개의 변수를 사용하는 방법입니다. 먼저, 각 변수들을 구별하기 위해 p5.js에서 사용하는 용어를 배워봅시다. 첫번째 용어는 '목적지 사각형(destination rectagle)로, dx, dy 등의 변수가 이에 해당합니다. 두번째 용어는 '원본 이미지(source image)'로, sx, sy등의 변수가 이에 해당합니다. '원본 이미지'의 크기를 설정하면 해당 이미지의 일부만을 디스플레이할 때 유용합니다. 자세한 사항은 아래 도식을 참고하세요.",
        +      "params": ["p5.Image, p5.Element: 디스플레이할 이미지",
        +      "숫자: 왼쪽 위 모서리의 x 좌표",
        +      "숫자: 왼쪽 위 모서리의 y 좌표",
        +      "숫자: 이미지 너비 설정",
        +      "숫자: 이미지 높이 설정",
        +      "숫자: 원본 이미지를 배치할 목적지 사각형의 x 좌표",
        +      "숫자: 원본 이미지를 배치할 목적지 사각형의 y 좌표",
        +      "숫자: 목적지 사각형의 너비",
        +      "숫자: 목적지 사각형의 높이",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 x좌표",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"]
        +    }
        +  },
        +  "p5.Image": {
        +    "loadPixels": {
        +      "description": "blah",
        +      "params": ["Numero: blah",
        +                 "Numero: blah"],
        +      "returns": "TODO"
        +    }
        +  },
        +  "p5.Element": {
        +    "description": "Clase base para todos los elementos añadidos al bosuqejo, incluyendo lienzo, buffers de gráficas, y otros elementos HTML. Los métodos en azul están incluidos en la funcionalidad base, los métodos en marrón son añadidos con la biblioteca p5.dom. No se ejecutan directamente, pero los objetos p5.Element son creados llamando a las funciones createCanvas(), createGraphics(), o en la biblioteca p5.dom, createDiv, createImg, createInput, etc.",
        +    "params": ["String: node DOM envolvente.",
        +    "Objeto: puntero a instancia p5."],
        +    "returns": "TODO"
        +  }
        +}
        diff --git a/src/templates/pages/reference/assets/index.html b/src/templates/pages/reference/assets/index.html
        index be8c3716c5..d0388faacb 100644
        --- a/src/templates/pages/reference/assets/index.html
        +++ b/src/templates/pages/reference/assets/index.html
        @@ -7,4 +7,4 @@
             <body>
                 <a href="../">Click here to redirect</a>
             </body>
        -</html>
        +</html>
        \ No newline at end of file
        diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js
        index 7b0ca9e5bc..29a5a885c5 100644
        --- a/src/templates/pages/reference/assets/js/reference.js
        +++ b/src/templates/pages/reference/assets/js/reference.js
        @@ -448,10 +448,10 @@ define('text',['module'], function (module) {
         });
         
         
        -define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\n<form>\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\n  <label class="sr-only" for="search_reference_field">Search reference</label>\n</form>\n\n';});
        +define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\r\n<form>\r\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\r\n  <label class="sr-only" for="search_reference_field">Search reference</label>\r\n</form>\r\n\r\n';});
         
         
        -define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\n\n  <strong><%=name%></strong>\n\n  <span class="small">\n    <% if (final) { %>\n    constant\n    <% } else if (itemtype) { %>\n    <%=itemtype%> \n    <% } %>\n\n    <% if (className) { %>\n    in <strong><%=className%></strong>\n    <% } %>\n\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\n    <% } %>\n  </span>\n\n</p>';});
        +define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\r\n\r\n  <strong><%=name%></strong>\r\n\r\n  <span class="small">\r\n    <% if (final) { %>\r\n    constant\r\n    <% } else if (itemtype) { %>\r\n    <%=itemtype%> \r\n    <% } %>\r\n\r\n    <% if (className) { %>\r\n    in <strong><%=className%></strong>\r\n    <% } %>\r\n\r\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\r\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\r\n    <% } %>\r\n  </span>\r\n\r\n</p>';});
         
         /*!
          * typeahead.js 0.10.2
        @@ -2303,7 +2303,7 @@ define('searchView',[
         });
         
         
        -define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\n  <div class="reference-group clearfix main-ref-page">  \n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\n    <div class="reference-subgroups clearfix main-ref-page">  \n    <% _.each(group.subgroups, function(subgroup, ind) { %>\n      <div class="reference-subgroup">\n        <% if (subgroup.name !== \'0\') { %>\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\n        <% } %>\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\n        <% _.each(subgroup.items, function(item) { %>\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\n        <% }); %>\n        </ul>\n      </div>\n    <% }); %>\n    </div>\n  </div>\n<% }); %>\n';});
        +define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\r\n  <div class="reference-group clearfix main-ref-page">  \r\n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\r\n    <div class="reference-subgroups clearfix main-ref-page">  \r\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\r\n      <div class="reference-subgroup">\r\n        <% if (subgroup.name !== \'0\') { %>\r\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\r\n        <% } %>\r\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\r\n        <% _.each(subgroup.items, function(item) { %>\r\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\r\n        <% }); %>\r\n        </ul>\r\n      </div>\r\n    <% }); %>\r\n    </div>\r\n  </div>\r\n<% }); %>\r\n';});
         
         define('listView',[
           'App',
        @@ -2442,13 +2442,13 @@ define('listView',[
         });
         
         
        -define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\n\n<% if (item.example) { %>\n<div class="example">\n  <h3 id="reference-example">Examples</h3>\n\n  <div class="example-content" data-alt="<%= item.alt %>">\n    <% _.each(item.example, function(example, i){ %>\n      <%= example %>\n    <% }); %>\n  </div>\n</div>\n<% } %>\n\n<div class="description">\n    \n  <h3 id="reference-description">Description</h3>\n\n  <% if (item.deprecated) { %>\n    <p>\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n    </p>\n  <% } %>\n      \n\n  <span class=\'description-text\'><%= item.description %></span>\n\n  <% if (item.extends) { %>\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\n  <% } %>\n\n  <% if (item.module === \'p5.sound\') { %>\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\n    </p>\n  <% } %>\n\n  <% if (item.constRefs) { %>\n    <p>Used by:\n  <%\n      var refs = item.constRefs;\n      for (var i = 0; i < refs.length; i ++) {\n        var ref = refs[i];\n        var name = ref;\n        if (name.substr(0, 3) === \'p5.\') {\n          name = name.substr(3);\n        }\n  if (i !== 0) {\n          if (i == refs.length - 1) {\n            %> and <%\n          } else {\n            %>, <%\n          }\n        }\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\n      }\n  %>\n    </p>\n  <% } %>\n</div>\n\n<% if (isConstructor || !isClass) { %>\n\n<div>\n  <h3 id="reference-syntax">Syntax</h3>\n  <p>\n    <% syntaxes.forEach(function(syntax) { %>\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\n    <% }) %>\n  </p>\n</div>\n\n\n<% if (item.params) { %>\n  <div class="params">\n    <h3 id="reference-parameters">Parameters</h3>\n    <ul aria-labelledby=\'reference-parameters\'>\n    <% for (var i=0; i<item.params.length; i++) { %>\n      <% var p = item.params[i] %>\n      <li>\n        <div class=\'paramname\'><%=p.name%></div>\n        <% if (p.type) { %>\n          <div class=\'paramtype\'>\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\n          <% if (p.optional) { %> (Optional)<% } %>\n          </div>\n        <% } %>\n      </li>\n    <% } %>\n    </ul>\n  </div>\n<% } %>\n\n<% if (item.return && item.return.type) { %>\n  <div>\n    <h3 id="reference-returns">Returns</h3>\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\n  </div>\n<% } %>\n\n<% } %>\n';});
        +define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\r\n\r\n<% if (item.example) { %>\r\n<div class="example">\r\n  <h3 id="reference-example">Examples</h3>\r\n\r\n  <div class="example-content" data-alt="<%= item.alt %>">\r\n    <% _.each(item.example, function(example, i){ %>\r\n      <%= example %>\r\n    <% }); %>\r\n  </div>\r\n</div>\r\n<% } %>\r\n\r\n<div class="description">\r\n    \r\n  <h3 id="reference-description">Description</h3>\r\n\r\n  <% if (item.deprecated) { %>\r\n    <p>\r\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\r\n    </p>\r\n  <% } %>\r\n      \r\n\r\n  <span class=\'description-text\'><%= item.description %></span>\r\n\r\n  <% if (item.extends) { %>\r\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\r\n  <% } %>\r\n\r\n  <% if (item.module === \'p5.sound\') { %>\r\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\r\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\r\n    </p>\r\n  <% } %>\r\n\r\n  <% if (item.constRefs) { %>\r\n    <p>Used by:\r\n  <%\r\n      var refs = item.constRefs;\r\n      for (var i = 0; i < refs.length; i ++) {\r\n        var ref = refs[i];\r\n        var name = ref;\r\n        if (name.substr(0, 3) === \'p5.\') {\r\n          name = name.substr(3);\r\n        }\r\n  if (i !== 0) {\r\n          if (i == refs.length - 1) {\r\n            %> and <%\r\n          } else {\r\n            %>, <%\r\n          }\r\n        }\r\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\r\n      }\r\n  %>\r\n    </p>\r\n  <% } %>\r\n</div>\r\n\r\n<% if (isConstructor || !isClass) { %>\r\n\r\n<div>\r\n  <h3 id="reference-syntax">Syntax</h3>\r\n  <p>\r\n    <% syntaxes.forEach(function(syntax) { %>\r\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\r\n    <% }) %>\r\n  </p>\r\n</div>\r\n\r\n\r\n<% if (item.params) { %>\r\n  <div class="params">\r\n    <h3 id="reference-parameters">Parameters</h3>\r\n    <ul aria-labelledby=\'reference-parameters\'>\r\n    <% for (var i=0; i<item.params.length; i++) { %>\r\n      <% var p = item.params[i] %>\r\n      <li>\r\n        <div class=\'paramname\'><%=p.name%></div>\r\n        <% if (p.type) { %>\r\n          <div class=\'paramtype\'>\r\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\r\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\r\n          <% if (p.optional) { %> (Optional)<% } %>\r\n          </div>\r\n        <% } %>\r\n      </li>\r\n    <% } %>\r\n    </ul>\r\n  </div>\r\n<% } %>\r\n\r\n<% if (item.return && item.return.type) { %>\r\n  <div>\r\n    <h3 id="reference-returns">Returns</h3>\r\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\r\n  </div>\r\n<% } %>\r\n\r\n<% } %>\r\n';});
         
         
        -define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n<div class="constructor">\n  <!--<h2>Constructor</h2>--> \n  <%=constructor%>\n</div>\n<% } %>\n\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n  <h4>Fields</h4>\n  <p>\n    <% _.each(fields, function(item) { %>\n      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>\n      <br>\n    <% }); %>\n  </p>\n<% } %>\n\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n  <h4>Methods</h4>\n  <p>\n    <table>\n    <% _.each(methods, function(item) { %>\n      <tr>\n      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>\n      </tr>\n    <% }); %>\n    </table>\n  </p>\n<% } %>\n';});
        +define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <!--<h2>Constructor</h2>--> \r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h4>Fields</h4>\r\n  <p>\r\n    <% _.each(fields, function(item) { %>\r\n      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>\r\n      <br>\r\n    <% }); %>\r\n  </p>\r\n<% } %>\r\n\r\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h4>Methods</h4>\r\n  <p>\r\n    <table>\r\n    <% _.each(methods, function(item) { %>\r\n      <tr>\r\n      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>\r\n      </tr>\r\n    <% }); %>\r\n    </table>\r\n  </p>\r\n<% } %>\r\n';});
         
         
        -define('text!tpl/itemEnd.html',[],function () { return '\n<br><br>\n\n<div>\n<% if (item.file && item.line) { %>\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\n<% } %>\n</div>\n\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\n<br><br>\n';});
        +define('text!tpl/itemEnd.html',[],function () { return '\r\n<br><br>\r\n\r\n<div>\r\n<% if (item.file && item.line) { %>\r\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\r\n<% } %>\r\n</div>\r\n\r\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\r\n<br><br>\r\n';});
         
         // Copyright (C) 2006 Google Inc.
         //
        @@ -4332,7 +4332,7 @@ define('itemView',[
         });
         
         
        -define('text!tpl/menu.html',[],function () { return '<div>\n  <br>\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\n</div>\n\n<div id=\'collection-list-categories\'>\n<h2 class="sr-only" id="categories">Categories</h2>\n<% var i=0; %>\n<% var max=Math.floor(groups.length/4); %>\n<% var rem=groups.length%4; %>\n\n<% _.each(groups, function(group){ %>\n  <% var m = rem > 0 ? 1 : 0 %>\n  <% if (i === 0) { %>\n    <ul aria-labelledby="categories">\n    <% } %>\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\n    <% if (i === (max+m-1)) { %>\n    </ul>\n  \t<% rem-- %>\n  \t<% i=0 %>\n  <% } else { %>\n  \t<% i++ %>\n  <% } %>\n<% }); %>\n</div>\n';});
        +define('text!tpl/menu.html',[],function () { return '<div>\r\n  <br>\r\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\r\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\r\n</div>\r\n\r\n<div id=\'collection-list-categories\'>\r\n<h2 class="sr-only" id="categories">Categories</h2>\r\n<% var i=0; %>\r\n<% var max=Math.floor(groups.length/4); %>\r\n<% var rem=groups.length%4; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% var m = rem > 0 ? 1 : 0 %>\r\n  <% if (i === 0) { %>\r\n    <ul aria-labelledby="categories">\r\n    <% } %>\r\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\r\n    <% if (i === (max+m-1)) { %>\r\n    </ul>\r\n  \t<% rem-- %>\r\n  \t<% i=0 %>\r\n  <% } else { %>\r\n  \t<% i++ %>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define('menuView',[
           'App',
        @@ -4401,7 +4401,7 @@ define('menuView',[
         });
         
         
        -define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\n\n<p><%= module.description %></p>\n\n<div id="library-page" class="reference-group clearfix">  \n\n<% var t = 0; col = 0; %>\n\n<% _.each(groups, function(group){ %>\n  <% if (t == 0) { %> \n    <div class="column_<%=col%>">\n  <% } %>\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\n    <% if (group.hash) { %> </a> <% } %>\n  <% } %>\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\n    <% t++; %>\n  <% }); %>\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\n    </div>\n  <% } %>\n<% }); %>\n</div>\n';});
        +define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define(
           'libraryView',[
        diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map
        index 7337a93988..dfd60136e2 100644
        --- a/src/templates/pages/reference/assets/js/reference.js.map
        +++ b/src/templates/pages/reference/assets/js/reference.js.map
        @@ -29,26 +29,26 @@
           "file": "reference.js",
           "sourcesContent": [
             "(function () {\n",
        -    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define('documented-method',[], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    module.exports = factory();\n  } else {\n    root.DocumentedMethod = factory();\n  }\n}(this, function () {\n  function extend(target, src) {\n    Object.keys(src).forEach(function(prop) {\n      target[prop] = src[prop];\n    });\n    return target;\n  }\n\n  function DocumentedMethod(classitem) {\n    extend(this, classitem);\n\n    if (this.overloads) {\n      // Make each overload inherit properties from their parent\n      // classitem.\n      this.overloads = this.overloads.map(function(overload) {\n        return extend(Object.create(this), overload);\n      }, this);\n\n      if (this.params) {\n        throw new Error('params for overloaded methods should be undefined');\n      }\n\n      this.params = this._getMergedParams();\n    }\n  }\n\n  DocumentedMethod.prototype = {\n    // Merge parameters across all overloaded versions of this item.\n    _getMergedParams: function() {\n      var paramNames = {};\n      var params = [];\n\n      this.overloads.forEach(function(overload) {\n        if (!overload.params) {\n          return;\n        }\n        overload.params.forEach(function(param) {\n          if (param.name in paramNames) {\n            return;\n          }\n          paramNames[param.name] = param;\n          params.push(param);\n        });\n      });\n\n      return params;\n    }\n  };\n\n  return DocumentedMethod;\n}));\n\n",
        -    "/**\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/requirejs/text for details\n */\n/*jslint regexp: true */\n/*global require, XMLHttpRequest, ActiveXObject,\n  define, window, process, Packages,\n  java, location, Components, FileUtils */\n\ndefine('text',['module'], function (module) {\n    'use strict';\n\n    var text, fs, Cc, Ci, xpcIsWindows,\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = {},\n        masterConfig = (module.config && module.config()) || {};\n\n    text = {\n        version: '2.0.10',\n\n        strip: function (content) {\n            //Strips <?xml ...?> declarations so that external SVG and XML\n            //documents can be added to a document without worry. Also, if the string\n            //is an HTML document, only the part inside the body tag is returned.\n            if (content) {\n                content = content.replace(xmlRegExp, \"\");\n                var matches = content.match(bodyRegExp);\n                if (matches) {\n                    content = matches[1];\n                }\n            } else {\n                content = \"\";\n            }\n            return content;\n        },\n\n        jsEscape: function (content) {\n            return content.replace(/(['\\\\])/g, '\\\\$1')\n                .replace(/[\\f]/g, \"\\\\f\")\n                .replace(/[\\b]/g, \"\\\\b\")\n                .replace(/[\\n]/g, \"\\\\n\")\n                .replace(/[\\t]/g, \"\\\\t\")\n                .replace(/[\\r]/g, \"\\\\r\")\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\n        },\n\n        createXhr: masterConfig.createXhr || function () {\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n            var xhr, i, progId;\n            if (typeof XMLHttpRequest !== \"undefined\") {\n                return new XMLHttpRequest();\n            } else if (typeof ActiveXObject !== \"undefined\") {\n                for (i = 0; i < 3; i += 1) {\n                    progId = progIds[i];\n                    try {\n                        xhr = new ActiveXObject(progId);\n                    } catch (e) {}\n\n                    if (xhr) {\n                        progIds = [progId];  // so faster next time\n                        break;\n                    }\n                }\n            }\n\n            return xhr;\n        },\n\n        /**\n         * Parses a resource name into its component parts. Resource names\n         * look like: module/name.ext!strip, where the !strip part is\n         * optional.\n         * @param {String} name the resource name\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n         * where strip is a boolean.\n         */\n        parseName: function (name) {\n            var modName, ext, temp,\n                strip = false,\n                index = name.indexOf(\".\"),\n                isRelative = name.indexOf('./') === 0 ||\n                             name.indexOf('../') === 0;\n\n            if (index !== -1 && (!isRelative || index > 1)) {\n                modName = name.substring(0, index);\n                ext = name.substring(index + 1, name.length);\n            } else {\n                modName = name;\n            }\n\n            temp = ext || modName;\n            index = temp.indexOf(\"!\");\n            if (index !== -1) {\n                //Pull off the strip arg.\n                strip = temp.substring(index + 1) === \"strip\";\n                temp = temp.substring(0, index);\n                if (ext) {\n                    ext = temp;\n                } else {\n                    modName = temp;\n                }\n            }\n\n            return {\n                moduleName: modName,\n                ext: ext,\n                strip: strip\n            };\n        },\n\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n        /**\n         * Is an URL on another domain. Only works for browser use, returns\n         * false in non-browser environments. Only used to know if an\n         * optimized .js version of a text resource should be loaded\n         * instead.\n         * @param {String} url\n         * @returns Boolean\n         */\n        useXhr: function (url, protocol, hostname, port) {\n            var uProtocol, uHostName, uPort,\n                match = text.xdRegExp.exec(url);\n            if (!match) {\n                return true;\n            }\n            uProtocol = match[2];\n            uHostName = match[3];\n\n            uHostName = uHostName.split(':');\n            uPort = uHostName[1];\n            uHostName = uHostName[0];\n\n            return (!uProtocol || uProtocol === protocol) &&\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\n                   ((!uPort && !uHostName) || uPort === port);\n        },\n\n        finishLoad: function (name, strip, content, onLoad) {\n            content = strip ? text.strip(content) : content;\n            if (masterConfig.isBuild) {\n                buildMap[name] = content;\n            }\n            onLoad(content);\n        },\n\n        load: function (name, req, onLoad, config) {\n            //Name has format: some.module.filext!strip\n            //The strip part is optional.\n            //if strip is present, then that means only get the string contents\n            //inside a body tag in an HTML string. For XML/SVG content it means\n            //removing the <?xml ...?> declarations so the content can be inserted\n            //into the current doc without problems.\n\n            // Do not bother with the work if a build and text will\n            // not be inlined.\n            if (config.isBuild && !config.inlineText) {\n                onLoad();\n                return;\n            }\n\n            masterConfig.isBuild = config.isBuild;\n\n            var parsed = text.parseName(name),\n                nonStripName = parsed.moduleName +\n                    (parsed.ext ? '.' + parsed.ext : ''),\n                url = req.toUrl(nonStripName),\n                useXhr = (masterConfig.useXhr) ||\n                         text.useXhr;\n\n            // Do not load if it is an empty: url\n            if (url.indexOf('empty:') === 0) {\n                onLoad();\n                return;\n            }\n\n            //Load the text. Use XHR if possible and in a browser.\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                text.get(url, function (content) {\n                    text.finishLoad(name, parsed.strip, content, onLoad);\n                }, function (err) {\n                    if (onLoad.error) {\n                        onLoad.error(err);\n                    }\n                });\n            } else {\n                //Need to fetch the resource across domains. Assume\n                //the resource has been optimized into a JS module. Fetch\n                //by the module name + extension, but do not include the\n                //!strip part to avoid file system issues.\n                req([nonStripName], function (content) {\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                    parsed.strip, content, onLoad);\n                });\n            }\n        },\n\n        write: function (pluginName, moduleName, write, config) {\n            if (buildMap.hasOwnProperty(moduleName)) {\n                var content = text.jsEscape(buildMap[moduleName]);\n                write.asModule(pluginName + \"!\" + moduleName,\n                               \"define(function () { return '\" +\n                                   content +\n                               \"';});\\n\");\n            }\n        },\n\n        writeFile: function (pluginName, moduleName, req, write, config) {\n            var parsed = text.parseName(moduleName),\n                extPart = parsed.ext ? '.' + parsed.ext : '',\n                nonStripName = parsed.moduleName + extPart,\n                //Use a '.js' file name so that it indicates it is a\n                //script that can be loaded across domains.\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\n\n            //Leverage own load() method to load plugin value, but only\n            //write out values that do not have the strip argument,\n            //to avoid any potential issues with ! in file names.\n            text.load(nonStripName, req, function (value) {\n                //Use own write() method to construct full module value.\n                //But need to create shell that translates writeFile's\n                //write() to the right interface.\n                var textWrite = function (contents) {\n                    return write(fileName, contents);\n                };\n                textWrite.asModule = function (moduleName, contents) {\n                    return write.asModule(moduleName, fileName, contents);\n                };\n\n                text.write(pluginName, nonStripName, textWrite, config);\n            }, config);\n        }\n    };\n\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\n            typeof process !== \"undefined\" &&\n            process.versions &&\n            !!process.versions.node &&\n            !process.versions['node-webkit'])) {\n        //Using special require.nodeRequire, something added by r.js.\n        fs = require.nodeRequire('fs');\n\n        text.get = function (url, callback, errback) {\n            try {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            } catch (e) {\n                errback(e);\n            }\n        };\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\n            text.createXhr())) {\n        text.get = function (url, callback, errback, headers) {\n            var xhr = text.createXhr(), header;\n            xhr.open('GET', url, true);\n\n            //Allow plugins direct access to xhr headers\n            if (headers) {\n                for (header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                    }\n                }\n            }\n\n            //Allow overrides specified in config\n            if (masterConfig.onXhr) {\n                masterConfig.onXhr(xhr, url);\n            }\n\n            xhr.onreadystatechange = function (evt) {\n                var status, err;\n                //Do not explicitly handle errors, those should be\n                //visible via console output in the browser.\n                if (xhr.readyState === 4) {\n                    status = xhr.status;\n                    if (status > 399 && status < 600) {\n                        //An http 4xx or 5xx error. Signal an error.\n                        err = new Error(url + ' HTTP status: ' + status);\n                        err.xhr = xhr;\n                        errback(err);\n                    } else {\n                        callback(xhr.responseText);\n                    }\n\n                    if (masterConfig.onXhrComplete) {\n                        masterConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            };\n            xhr.send(null);\n        };\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\n        //Why Java, why is this so awkward?\n        text.get = function (url, callback) {\n            var stringBuffer, line,\n                encoding = \"utf-8\",\n                file = new java.io.File(url),\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                content = '';\n            try {\n                stringBuffer = new java.lang.StringBuffer();\n                line = input.readLine();\n\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                // http://www.unicode.org/faq/utf_bom.html\n\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\n                    // Eat the BOM, since we've already found the encoding on this file,\n                    // and we plan to concatenating this buffer with others; the BOM should\n                    // only appear at the top of a file.\n                    line = line.substring(1);\n                }\n\n                if (line !== null) {\n                    stringBuffer.append(line);\n                }\n\n                while ((line = input.readLine()) !== null) {\n                    stringBuffer.append(lineSeparator);\n                    stringBuffer.append(line);\n                }\n                //Make sure we return a JavaScript string and not a Java string.\n                content = String(stringBuffer.toString()); //String\n            } finally {\n                input.close();\n            }\n            callback(content);\n        };\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\n            typeof Components !== 'undefined' && Components.classes &&\n            Components.interfaces)) {\n        //Avert your gaze!\n        Cc = Components.classes,\n        Ci = Components.interfaces;\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\n\n        text.get = function (url, callback) {\n            var inStream, convertStream, fileObj,\n                readData = {};\n\n            if (xpcIsWindows) {\n                url = url.replace(/\\//g, '\\\\');\n            }\n\n            fileObj = new FileUtils.File(url);\n\n            //XPCOM, you so crazy\n            try {\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\n                           .createInstance(Ci.nsIFileInputStream);\n                inStream.init(fileObj, 1, 0, false);\n\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\n                                .createInstance(Ci.nsIConverterInputStream);\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\n\n                convertStream.readString(inStream.available(), readData);\n                convertStream.close();\n                inStream.close();\n                callback(readData.value);\n            } catch (e) {\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\n            }\n        };\n    }\n    return text;\n});\n\n",
        -    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\n<form>\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\n</form>\\n\\n';});\n\n",
        -    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\n\\n  <strong><%=name%></strong>\\n\\n  <span class=\"small\">\\n    <% if (final) { %>\\n    constant\\n    <% } else if (itemtype) { %>\\n    <%=itemtype%> \\n    <% } %>\\n\\n    <% if (className) { %>\\n    in <strong><%=className%></strong>\\n    <% } %>\\n\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\n    <% } %>\\n  </span>\\n\\n</p>';});\n\n",
        -    "/*!\n * typeahead.js 0.10.2\n * https://github.com/twitter/typeahead.js\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\n */\ndefine('typeahead',[], function() {\n\n//(function($) {\n\n\n    var _ = {\n        isMsie: function() {\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\n        },\n        isBlankString: function(str) {\n            return !str || /^\\s*$/.test(str);\n        },\n        escapeRegExChars: function(str) {\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n        },\n        isString: function(obj) {\n            return typeof obj === \"string\";\n        },\n        isNumber: function(obj) {\n            return typeof obj === \"number\";\n        },\n        isArray: $.isArray,\n        isFunction: $.isFunction,\n        isObject: $.isPlainObject,\n        isUndefined: function(obj) {\n            return typeof obj === \"undefined\";\n        },\n        bind: $.proxy,\n        each: function(collection, cb) {\n            $.each(collection, reverseArgs);\n            function reverseArgs(index, value) {\n                return cb(value, index);\n            }\n        },\n        map: $.map,\n        filter: $.grep,\n        every: function(obj, test) {\n            var result = true;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (!(result = test.call(null, val, key, obj))) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        some: function(obj, test) {\n            var result = false;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (result = test.call(null, val, key, obj)) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        mixin: $.extend,\n        getUniqueId: function() {\n            var counter = 0;\n            return function() {\n                return counter++;\n            };\n        }(),\n        templatify: function templatify(obj) {\n            return $.isFunction(obj) ? obj : template;\n            function template() {\n                return String(obj);\n            }\n        },\n        defer: function(fn) {\n            setTimeout(fn, 0);\n        },\n        debounce: function(func, wait, immediate) {\n            var timeout, result;\n            return function() {\n                var context = this, args = arguments, later, callNow;\n                later = function() {\n                    timeout = null;\n                    if (!immediate) {\n                        result = func.apply(context, args);\n                    }\n                };\n                callNow = immediate && !timeout;\n                clearTimeout(timeout);\n                timeout = setTimeout(later, wait);\n                if (callNow) {\n                    result = func.apply(context, args);\n                }\n                return result;\n            };\n        },\n        throttle: function(func, wait) {\n            var context, args, timeout, result, previous, later;\n            previous = 0;\n            later = function() {\n                previous = new Date();\n                timeout = null;\n                result = func.apply(context, args);\n            };\n            return function() {\n                var now = new Date(), remaining = wait - (now - previous);\n                context = this;\n                args = arguments;\n                if (remaining <= 0) {\n                    clearTimeout(timeout);\n                    timeout = null;\n                    previous = now;\n                    result = func.apply(context, args);\n                } else if (!timeout) {\n                    timeout = setTimeout(later, remaining);\n                }\n                return result;\n            };\n        },\n        noop: function() {}\n    };\n    var VERSION = \"0.10.2\";\n    var tokenizers = function(root) {\n        return {\n            nonword: nonword,\n            whitespace: whitespace,\n            obj: {\n                nonword: getObjTokenizer(nonword),\n                whitespace: getObjTokenizer(whitespace)\n            }\n        };\n        function whitespace(s) {\n            return s.split(/\\s+/);\n        }\n        function nonword(s) {\n            return s.split(/\\W+/);\n        }\n        function getObjTokenizer(tokenizer) {\n            return function setKey(key) {\n                return function tokenize(o) {\n                    return tokenizer(o[key]);\n                };\n            };\n        }\n    }();\n    var LruCache = function() {\n        function LruCache(maxSize) {\n            this.maxSize = maxSize || 100;\n            this.size = 0;\n            this.hash = {};\n            this.list = new List();\n        }\n        _.mixin(LruCache.prototype, {\n            set: function set(key, val) {\n                var tailItem = this.list.tail, node;\n                if (this.size >= this.maxSize) {\n                    this.list.remove(tailItem);\n                    delete this.hash[tailItem.key];\n                }\n                if (node = this.hash[key]) {\n                    node.val = val;\n                    this.list.moveToFront(node);\n                } else {\n                    node = new Node(key, val);\n                    this.list.add(node);\n                    this.hash[key] = node;\n                    this.size++;\n                }\n            },\n            get: function get(key) {\n                var node = this.hash[key];\n                if (node) {\n                    this.list.moveToFront(node);\n                    return node.val;\n                }\n            }\n        });\n        function List() {\n            this.head = this.tail = null;\n        }\n        _.mixin(List.prototype, {\n            add: function add(node) {\n                if (this.head) {\n                    node.next = this.head;\n                    this.head.prev = node;\n                }\n                this.head = node;\n                this.tail = this.tail || node;\n            },\n            remove: function remove(node) {\n                node.prev ? node.prev.next = node.next : this.head = node.next;\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\n            },\n            moveToFront: function(node) {\n                this.remove(node);\n                this.add(node);\n            }\n        });\n        function Node(key, val) {\n            this.key = key;\n            this.val = val;\n            this.prev = this.next = null;\n        }\n        return LruCache;\n    }();\n    var PersistentStorage = function() {\n        var ls, methods;\n        try {\n            ls = window.localStorage;\n            ls.setItem(\"~~~\", \"!\");\n            ls.removeItem(\"~~~\");\n        } catch (err) {\n            ls = null;\n        }\n        function PersistentStorage(namespace) {\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\n            this.ttlKey = \"__ttl__\";\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\n        }\n        if (ls && window.JSON) {\n            methods = {\n                _prefix: function(key) {\n                    return this.prefix + key;\n                },\n                _ttlKey: function(key) {\n                    return this._prefix(key) + this.ttlKey;\n                },\n                get: function(key) {\n                    if (this.isExpired(key)) {\n                        this.remove(key);\n                    }\n                    return decode(ls.getItem(this._prefix(key)));\n                },\n                set: function(key, val, ttl) {\n                    if (_.isNumber(ttl)) {\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\n                    } else {\n                        ls.removeItem(this._ttlKey(key));\n                    }\n                    return ls.setItem(this._prefix(key), encode(val));\n                },\n                remove: function(key) {\n                    ls.removeItem(this._ttlKey(key));\n                    ls.removeItem(this._prefix(key));\n                    return this;\n                },\n                clear: function() {\n                    var i, key, keys = [], len = ls.length;\n                    for (i = 0; i < len; i++) {\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\n                            keys.push(key.replace(this.keyMatcher, \"\"));\n                        }\n                    }\n                    for (i = keys.length; i--; ) {\n                        this.remove(keys[i]);\n                    }\n                    return this;\n                },\n                isExpired: function(key) {\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\n                }\n            };\n        } else {\n            methods = {\n                get: _.noop,\n                set: _.noop,\n                remove: _.noop,\n                clear: _.noop,\n                isExpired: _.noop\n            };\n        }\n        _.mixin(PersistentStorage.prototype, methods);\n        return PersistentStorage;\n        function now() {\n            return new Date().getTime();\n        }\n        function encode(val) {\n            return JSON.stringify(_.isUndefined(val) ? null : val);\n        }\n        function decode(val) {\n            return JSON.parse(val);\n        }\n    }();\n    var Transport = function() {\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\n        function Transport(o) {\n            o = o || {};\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\n        }\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\n            maxPendingRequests = num;\n        };\n        Transport.resetCache = function clearCache() {\n            requestCache = new LruCache(10);\n        };\n        _.mixin(Transport.prototype, {\n            _get: function(url, o, cb) {\n                var that = this, jqXhr;\n                if (jqXhr = pendingRequests[url]) {\n                    jqXhr.done(done).fail(fail);\n                } else if (pendingRequestsCount < maxPendingRequests) {\n                    pendingRequestsCount++;\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\n                } else {\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\n                }\n                function done(resp) {\n                    cb && cb(null, resp);\n                    requestCache.set(url, resp);\n                }\n                function fail() {\n                    cb && cb(true);\n                }\n                function always() {\n                    pendingRequestsCount--;\n                    delete pendingRequests[url];\n                    if (that.onDeckRequestArgs) {\n                        that._get.apply(that, that.onDeckRequestArgs);\n                        that.onDeckRequestArgs = null;\n                    }\n                }\n            },\n            get: function(url, o, cb) {\n                var resp;\n                if (_.isFunction(o)) {\n                    cb = o;\n                    o = {};\n                }\n                if (resp = requestCache.get(url)) {\n                    _.defer(function() {\n                        cb && cb(null, resp);\n                    });\n                } else {\n                    this._get(url, o, cb);\n                }\n                return !!resp;\n            }\n        });\n        return Transport;\n        function callbackToDeferred(fn) {\n            return function customSendWrapper(url, o) {\n                var deferred = $.Deferred();\n                fn(url, o, onSuccess, onError);\n                return deferred;\n                function onSuccess(resp) {\n                    _.defer(function() {\n                        deferred.resolve(resp);\n                    });\n                }\n                function onError(err) {\n                    _.defer(function() {\n                        deferred.reject(err);\n                    });\n                }\n            };\n        }\n    }();\n    var SearchIndex = function() {\n        function SearchIndex(o) {\n            o = o || {};\n            if (!o.datumTokenizer || !o.queryTokenizer) {\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\n            }\n            this.datumTokenizer = o.datumTokenizer;\n            this.queryTokenizer = o.queryTokenizer;\n            this.reset();\n        }\n        _.mixin(SearchIndex.prototype, {\n            bootstrap: function bootstrap(o) {\n                this.datums = o.datums;\n                this.trie = o.trie;\n            },\n            add: function(data) {\n                var that = this;\n                data = _.isArray(data) ? data : [ data ];\n                _.each(data, function(datum) {\n                    var id, tokens;\n                    id = that.datums.push(datum) - 1;\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\n                    _.each(tokens, function(token) {\n                        var node, chars, ch;\n                        node = that.trie;\n                        chars = token.split(\"\");\n                        while (ch = chars.shift()) {\n                            node = node.children[ch] || (node.children[ch] = newNode());\n                            node.ids.push(id);\n                        }\n                    });\n                });\n            },\n            get: function get(query) {\n                var that = this, tokens, matches;\n                tokens = normalizeTokens(this.queryTokenizer(query));\n                _.each(tokens, function(token) {\n                    var node, chars, ch, ids;\n                    if (matches && matches.length === 0) {\n                        return false;\n                    }\n                    node = that.trie;\n                    chars = token.split(\"\");\n                    while (node && (ch = chars.shift())) {\n                        node = node.children[ch];\n                    }\n                    if (node && chars.length === 0) {\n                        ids = node.ids.slice(0);\n                        matches = matches ? getIntersection(matches, ids) : ids;\n                    } else {\n                        matches = [];\n                        return false;\n                    }\n                });\n                return matches ? _.map(unique(matches), function(id) {\n                    return that.datums[id];\n                }) : [];\n            },\n            reset: function reset() {\n                this.datums = [];\n                this.trie = newNode();\n            },\n            serialize: function serialize() {\n                return {\n                    datums: this.datums,\n                    trie: this.trie\n                };\n            }\n        });\n        return SearchIndex;\n        function normalizeTokens(tokens) {\n            tokens = _.filter(tokens, function(token) {\n                return !!token;\n            });\n            tokens = _.map(tokens, function(token) {\n                return token.toLowerCase();\n            });\n            return tokens;\n        }\n        function newNode() {\n            return {\n                ids: [],\n                children: {}\n            };\n        }\n        function unique(array) {\n            var seen = {}, uniques = [];\n            for (var i = 0; i < array.length; i++) {\n                if (!seen[array[i]]) {\n                    seen[array[i]] = true;\n                    uniques.push(array[i]);\n                }\n            }\n            return uniques;\n        }\n        function getIntersection(arrayA, arrayB) {\n            var ai = 0, bi = 0, intersection = [];\n            arrayA = arrayA.sort(compare);\n            arrayB = arrayB.sort(compare);\n            while (ai < arrayA.length && bi < arrayB.length) {\n                if (arrayA[ai] < arrayB[bi]) {\n                    ai++;\n                } else if (arrayA[ai] > arrayB[bi]) {\n                    bi++;\n                } else {\n                    intersection.push(arrayA[ai]);\n                    ai++;\n                    bi++;\n                }\n            }\n            return intersection;\n            function compare(a, b) {\n                return a - b;\n            }\n        }\n    }();\n    var oParser = function() {\n        return {\n            local: getLocal,\n            prefetch: getPrefetch,\n            remote: getRemote\n        };\n        function getLocal(o) {\n            return o.local || null;\n        }\n        function getPrefetch(o) {\n            var prefetch, defaults;\n            defaults = {\n                url: null,\n                thumbprint: \"\",\n                ttl: 24 * 60 * 60 * 1e3,\n                filter: null,\n                ajax: {}\n            };\n            if (prefetch = o.prefetch || null) {\n                prefetch = _.isString(prefetch) ? {\n                    url: prefetch\n                } : prefetch;\n                prefetch = _.mixin(defaults, prefetch);\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\n            }\n            return prefetch;\n        }\n        function getRemote(o) {\n            var remote, defaults;\n            defaults = {\n                url: null,\n                wildcard: \"%QUERY\",\n                replace: null,\n                rateLimitBy: \"debounce\",\n                rateLimitWait: 300,\n                send: null,\n                filter: null,\n                ajax: {}\n            };\n            if (remote = o.remote || null) {\n                remote = _.isString(remote) ? {\n                    url: remote\n                } : remote;\n                remote = _.mixin(defaults, remote);\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\n                remote.ajax.type = remote.ajax.type || \"GET\";\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\n                delete remote.rateLimitBy;\n                delete remote.rateLimitWait;\n                !remote.url && $.error(\"remote requires url to be set\");\n            }\n            return remote;\n            function byDebounce(wait) {\n                return function(fn) {\n                    return _.debounce(fn, wait);\n                };\n            }\n            function byThrottle(wait) {\n                return function(fn) {\n                    return _.throttle(fn, wait);\n                };\n            }\n        }\n    }();\n    (function(root) {\n        var old, keys;\n        old = root.Bloodhound;\n        keys = {\n            data: \"data\",\n            protocol: \"protocol\",\n            thumbprint: \"thumbprint\"\n        };\n        root.Bloodhound = Bloodhound;\n        function Bloodhound(o) {\n            if (!o || !o.local && !o.prefetch && !o.remote) {\n                $.error(\"one of local, prefetch, or remote is required\");\n            }\n            this.limit = o.limit || 5;\n            this.sorter = getSorter(o.sorter);\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\n            this.local = oParser.local(o);\n            this.prefetch = oParser.prefetch(o);\n            this.remote = oParser.remote(o);\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\n            this.index = new SearchIndex({\n                datumTokenizer: o.datumTokenizer,\n                queryTokenizer: o.queryTokenizer\n            });\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\n        }\n        Bloodhound.noConflict = function noConflict() {\n            root.Bloodhound = old;\n            return Bloodhound;\n        };\n        Bloodhound.tokenizers = tokenizers;\n        _.mixin(Bloodhound.prototype, {\n            _loadPrefetch: function loadPrefetch(o) {\n                var that = this, serialized, deferred;\n                if (serialized = this._readFromStorage(o.thumbprint)) {\n                    this.index.bootstrap(serialized);\n                    deferred = $.Deferred().resolve();\n                } else {\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\n                }\n                return deferred;\n                function handlePrefetchResponse(resp) {\n                    that.clear();\n                    that.add(o.filter ? o.filter(resp) : resp);\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\n                }\n            },\n            _getFromRemote: function getFromRemote(query, cb) {\n                var that = this, url, uriEncodedQuery;\n                query = query || \"\";\n                uriEncodedQuery = encodeURIComponent(query);\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\n                function handleRemoteResponse(err, resp) {\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\n                }\n            },\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\n                if (this.storage) {\n                    this.storage.set(keys.data, data, ttl);\n                    this.storage.set(keys.protocol, location.protocol, ttl);\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\n                }\n            },\n            _readFromStorage: function readFromStorage(thumbprint) {\n                var stored = {}, isExpired;\n                if (this.storage) {\n                    stored.data = this.storage.get(keys.data);\n                    stored.protocol = this.storage.get(keys.protocol);\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\n                }\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\n                return stored.data && !isExpired ? stored.data : null;\n            },\n            _initialize: function initialize() {\n                var that = this, local = this.local, deferred;\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\n                local && deferred.done(addLocalToIndex);\n                this.transport = this.remote ? new Transport(this.remote) : null;\n                return this.initPromise = deferred.promise();\n                function addLocalToIndex() {\n                    that.add(_.isFunction(local) ? local() : local);\n                }\n            },\n            initialize: function initialize(force) {\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\n            },\n            add: function add(data) {\n                this.index.add(data);\n            },\n            get: function get(query, cb) {\n                var that = this, matches = [], cacheHit = false;\n                matches = this.index.get(query);\n                matches = this.sorter(matches).slice(0, this.limit);\n                if (matches.length < this.limit && this.transport) {\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\n                }\n                if (!cacheHit) {\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\n                }\n                function returnRemoteMatches(remoteMatches) {\n                    var matchesWithBackfill = matches.slice(0);\n                    _.each(remoteMatches, function(remoteMatch) {\n                        var isDuplicate;\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\n                            return that.dupDetector(remoteMatch, match);\n                        });\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\n                        return matchesWithBackfill.length < that.limit;\n                    });\n                    cb && cb(that.sorter(matchesWithBackfill));\n                }\n            },\n            clear: function clear() {\n                this.index.reset();\n            },\n            clearPrefetchCache: function clearPrefetchCache() {\n                this.storage && this.storage.clear();\n            },\n            clearRemoteCache: function clearRemoteCache() {\n                this.transport && Transport.resetCache();\n            },\n            ttAdapter: function ttAdapter() {\n                return _.bind(this.get, this);\n            }\n        });\n        return Bloodhound;\n        function getSorter(sortFn) {\n            return _.isFunction(sortFn) ? sort : noSort;\n            function sort(array) {\n                return array.sort(sortFn);\n            }\n            function noSort(array) {\n                return array;\n            }\n        }\n        function ignoreDuplicates() {\n            return false;\n        }\n    })(this);\n    var html = {\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\n        suggestions: '<span class=\"tt-suggestions\"></span>',\n        suggestion: '<div class=\"tt-suggestion\"></div>'\n    };\n    var css = {\n        wrapper: {\n            position: \"relative\",\n            display: \"inline-block\"\n        },\n        hint: {\n            position: \"absolute\",\n            top: \"0\",\n            left: \"0\",\n            borderColor: \"transparent\",\n            boxShadow: \"none\"\n        },\n        input: {\n            position: \"relative\",\n            verticalAlign: \"top\",\n            backgroundColor: \"transparent\"\n        },\n        inputWithNoHint: {\n            position: \"relative\",\n            verticalAlign: \"top\"\n        },\n        dropdown: {\n            position: \"absolute\",\n            top: \"100%\",\n            left: \"0\",\n            zIndex: \"100\",\n            display: \"none\"\n        },\n        suggestions: {\n            display: \"block\"\n        },\n        suggestion: {\n            whiteSpace: \"nowrap\",\n            cursor: \"pointer\"\n        },\n        suggestionChild: {\n            whiteSpace: \"normal\"\n        },\n        ltr: {\n            left: \"0\",\n            right: \"auto\"\n        },\n        rtl: {\n            left: \"auto\",\n            right: \" 0\"\n        }\n    };\n    if (_.isMsie()) {\n        _.mixin(css.input, {\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\n        });\n    }\n    if (_.isMsie() && _.isMsie() <= 7) {\n        _.mixin(css.input, {\n            marginTop: \"-1px\"\n        });\n    }\n    var EventBus = function() {\n        var namespace = \"typeahead:\";\n        function EventBus(o) {\n            if (!o || !o.el) {\n                $.error(\"EventBus initialized without el\");\n            }\n            this.$el = $(o.el);\n        }\n        _.mixin(EventBus.prototype, {\n            trigger: function(type) {\n                var args = [].slice.call(arguments, 1);\n                this.$el.trigger(namespace + type, args);\n            }\n        });\n        return EventBus;\n    }();\n    var EventEmitter = function() {\n        var splitter = /\\s+/, nextTick = getNextTick();\n        return {\n            onSync: onSync,\n            onAsync: onAsync,\n            off: off,\n            trigger: trigger\n        };\n        function on(method, types, cb, context) {\n            var type;\n            if (!cb) {\n                return this;\n            }\n            types = types.split(splitter);\n            cb = context ? bindContext(cb, context) : cb;\n            this._callbacks = this._callbacks || {};\n            while (type = types.shift()) {\n                this._callbacks[type] = this._callbacks[type] || {\n                    sync: [],\n                    async: []\n                };\n                this._callbacks[type][method].push(cb);\n            }\n            return this;\n        }\n        function onAsync(types, cb, context) {\n            return on.call(this, \"async\", types, cb, context);\n        }\n        function onSync(types, cb, context) {\n            return on.call(this, \"sync\", types, cb, context);\n        }\n        function off(types) {\n            var type;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            while (type = types.shift()) {\n                delete this._callbacks[type];\n            }\n            return this;\n        }\n        function trigger(types) {\n            var type, callbacks, args, syncFlush, asyncFlush;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            args = [].slice.call(arguments, 1);\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\n                syncFlush() && nextTick(asyncFlush);\n            }\n            return this;\n        }\n        function getFlush(callbacks, context, args) {\n            return flush;\n            function flush() {\n                var cancelled;\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\n                    cancelled = callbacks[i].apply(context, args) === false;\n                }\n                return !cancelled;\n            }\n        }\n        function getNextTick() {\n            var nextTickFn;\n            if (window.setImmediate) {\n                nextTickFn = function nextTickSetImmediate(fn) {\n                    setImmediate(function() {\n                        fn();\n                    });\n                };\n            } else {\n                nextTickFn = function nextTickSetTimeout(fn) {\n                    setTimeout(function() {\n                        fn();\n                    }, 0);\n                };\n            }\n            return nextTickFn;\n        }\n        function bindContext(fn, context) {\n            return fn.bind ? fn.bind(context) : function() {\n                fn.apply(context, [].slice.call(arguments, 0));\n            };\n        }\n    }();\n    var highlight = function(doc) {\n        var defaults = {\n            node: null,\n            pattern: null,\n            tagName: \"strong\",\n            className: null,\n            wordsOnly: false,\n            caseSensitive: false\n        };\n        return function hightlight(o) {\n            var regex;\n            o = _.mixin({}, defaults, o);\n            if (!o.node || !o.pattern) {\n                return;\n            }\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\n            traverse(o.node, hightlightTextNode);\n            function hightlightTextNode(textNode) {\n                var match, patternNode;\n                if (match = regex.exec(textNode.data)) {\n                    wrapperNode = doc.createElement(o.tagName);\n                    o.className && (wrapperNode.className = o.className);\n                    patternNode = textNode.splitText(match.index);\n                    patternNode.splitText(match[0].length);\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\n                }\n                return !!match;\n            }\n            function traverse(el, hightlightTextNode) {\n                var childNode, TEXT_NODE_TYPE = 3;\n                for (var i = 0; i < el.childNodes.length; i++) {\n                    childNode = el.childNodes[i];\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\n                        i += hightlightTextNode(childNode) ? 1 : 0;\n                    } else {\n                        traverse(childNode, hightlightTextNode);\n                    }\n                }\n            }\n        };\n        function getRegex(patterns, caseSensitive, wordsOnly) {\n            var escapedPatterns = [], regexStr;\n            for (var i = 0; i < patterns.length; i++) {\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\n            }\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\n        }\n    }(window.document);\n    var Input = function() {\n        var specialKeyCodeMap;\n        specialKeyCodeMap = {\n            9: \"tab\",\n            27: \"esc\",\n            37: \"left\",\n            39: \"right\",\n            13: \"enter\",\n            38: \"up\",\n            40: \"down\"\n        };\n        function Input(o) {\n            var that = this, onBlur, onFocus, onKeydown, onInput;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"input is missing\");\n            }\n            onBlur = _.bind(this._onBlur, this);\n            onFocus = _.bind(this._onFocus, this);\n            onKeydown = _.bind(this._onKeydown, this);\n            onInput = _.bind(this._onInput, this);\n            this.$hint = $(o.hint);\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\n            if (this.$hint.length === 0) {\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\n            }\n            if (!_.isMsie()) {\n                this.$input.on(\"input.tt\", onInput);\n            } else {\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\n                        return;\n                    }\n                    _.defer(_.bind(that._onInput, that, $e));\n                });\n            }\n            this.query = this.$input.val();\n            this.$overflowHelper = buildOverflowHelper(this.$input);\n        }\n        Input.normalizeQuery = function(str) {\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\n        };\n        _.mixin(Input.prototype, EventEmitter, {\n            _onBlur: function onBlur() {\n                this.resetInputValue();\n                this.trigger(\"blurred\");\n            },\n            _onFocus: function onFocus() {\n                this.trigger(\"focused\");\n            },\n            _onKeydown: function onKeydown($e) {\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\n                this._managePreventDefault(keyName, $e);\n                if (keyName && this._shouldTrigger(keyName, $e)) {\n                    this.trigger(keyName + \"Keyed\", $e);\n                }\n            },\n            _onInput: function onInput() {\n                this._checkInputValue();\n            },\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\n                var preventDefault, hintValue, inputValue;\n                switch (keyName) {\n                  case \"tab\":\n                    hintValue = this.getHint();\n                    inputValue = this.getInputValue();\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\n                    break;\n\n                  case \"up\":\n                  case \"down\":\n                    preventDefault = !withModifier($e);\n                    break;\n\n                  default:\n                    preventDefault = false;\n                }\n                preventDefault && $e.preventDefault();\n            },\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\n                var trigger;\n                switch (keyName) {\n                  case \"tab\":\n                    trigger = !withModifier($e);\n                    break;\n\n                  default:\n                    trigger = true;\n                }\n                return trigger;\n            },\n            _checkInputValue: function checkInputValue() {\n                var inputValue, areEquivalent, hasDifferentWhitespace;\n                inputValue = this.getInputValue();\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\n                if (!areEquivalent) {\n                    this.trigger(\"queryChanged\", this.query = inputValue);\n                } else if (hasDifferentWhitespace) {\n                    this.trigger(\"whitespaceChanged\", this.query);\n                }\n            },\n            focus: function focus() {\n                this.$input.focus();\n            },\n            blur: function blur() {\n                this.$input.blur();\n            },\n            getQuery: function getQuery() {\n                return this.query;\n            },\n            setQuery: function setQuery(query) {\n                this.query = query;\n            },\n            getInputValue: function getInputValue() {\n                return this.$input.val();\n            },\n            setInputValue: function setInputValue(value, silent) {\n                this.$input.val(value);\n                silent ? this.clearHint() : this._checkInputValue();\n            },\n            resetInputValue: function resetInputValue() {\n                this.setInputValue(this.query, true);\n            },\n            getHint: function getHint() {\n                return this.$hint.val();\n            },\n            setHint: function setHint(value) {\n                this.$hint.val(value);\n            },\n            clearHint: function clearHint() {\n                this.setHint(\"\");\n            },\n            clearHintIfInvalid: function clearHintIfInvalid() {\n                var val, hint, valIsPrefixOfHint, isValid;\n                val = this.getInputValue();\n                hint = this.getHint();\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\n                !isValid && this.clearHint();\n            },\n            getLanguageDirection: function getLanguageDirection() {\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\n            },\n            hasOverflow: function hasOverflow() {\n                var constraint = this.$input.width() - 2;\n                this.$overflowHelper.text(this.getInputValue());\n                return this.$overflowHelper.width() >= constraint;\n            },\n            isCursorAtEnd: function() {\n                var valueLength, selectionStart, range;\n                valueLength = this.$input.val().length;\n                selectionStart = this.$input[0].selectionStart;\n                if (_.isNumber(selectionStart)) {\n                    return selectionStart === valueLength;\n                } else if (document.selection) {\n                    range = document.selection.createRange();\n                    range.moveStart(\"character\", -valueLength);\n                    return valueLength === range.text.length;\n                }\n                return true;\n            },\n            destroy: function destroy() {\n                this.$hint.off(\".tt\");\n                this.$input.off(\".tt\");\n                this.$hint = this.$input = this.$overflowHelper = null;\n            }\n        });\n        return Input;\n        function buildOverflowHelper($input) {\n            return $('<pre aria-hidden=\"true\"></pre>').css({\n                position: \"absolute\",\n                visibility: \"hidden\",\n                whiteSpace: \"pre\",\n                fontFamily: $input.css(\"font-family\"),\n                fontSize: $input.css(\"font-size\"),\n                fontStyle: $input.css(\"font-style\"),\n                fontVariant: $input.css(\"font-variant\"),\n                fontWeight: $input.css(\"font-weight\"),\n                wordSpacing: $input.css(\"word-spacing\"),\n                letterSpacing: $input.css(\"letter-spacing\"),\n                textIndent: $input.css(\"text-indent\"),\n                textRendering: $input.css(\"text-rendering\"),\n                textTransform: $input.css(\"text-transform\")\n            }).insertAfter($input);\n        }\n        function areQueriesEquivalent(a, b) {\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\n        }\n        function withModifier($e) {\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\n        }\n    }();\n    var Dataset = function() {\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\n        function Dataset(o) {\n            o = o || {};\n            o.templates = o.templates || {};\n            if (!o.source) {\n                $.error(\"missing source\");\n            }\n            if (o.name && !isValidName(o.name)) {\n                $.error(\"invalid dataset name: \" + o.name);\n            }\n            this.query = null;\n            this.highlight = !!o.highlight;\n            this.name = o.name || _.getUniqueId();\n            this.source = o.source;\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\n            this.templates = getTemplates(o.templates, this.displayFn);\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\n        }\n        Dataset.extractDatasetName = function extractDatasetName(el) {\n            return $(el).data(datasetKey);\n        };\n        Dataset.extractValue = function extractDatum(el) {\n            return $(el).data(valueKey);\n        };\n        Dataset.extractDatum = function extractDatum(el) {\n            return $(el).data(datumKey);\n        };\n        _.mixin(Dataset.prototype, EventEmitter, {\n            _render: function render(query, suggestions) {\n                if (!this.$el) {\n                    return;\n                }\n                var that = this, hasSuggestions;\n                this.$el.empty();\n                hasSuggestions = suggestions && suggestions.length;\n                if (!hasSuggestions && this.templates.empty) {\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                } else if (hasSuggestions) {\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                }\n                this.trigger(\"rendered\");\n                function getEmptyHtml() {\n                    return that.templates.empty({\n                        query: query,\n                        isEmpty: true\n                    });\n                }\n                function getSuggestionsHtml() {\n                    var $suggestions, nodes;\n                    $suggestions = $(html.suggestions).css(css.suggestions);\n                    nodes = _.map(suggestions, getSuggestionNode);\n                    $suggestions.append.apply($suggestions, nodes);\n                    that.highlight && highlight({\n                        node: $suggestions[0],\n                        pattern: query\n                    });\n                    return $suggestions;\n                    function getSuggestionNode(suggestion) {\n                        var $el;\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\n                        $el.children().each(function() {\n                            $(this).css(css.suggestionChild);\n                        });\n                        return $el;\n                    }\n                }\n                function getHeaderHtml() {\n                    return that.templates.header({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n                function getFooterHtml() {\n                    return that.templates.footer({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n            },\n            getRoot: function getRoot() {\n                return this.$el;\n            },\n            update: function update(query) {\n                var that = this;\n                this.query = query;\n                this.canceled = false;\n                this.source(query, render);\n                function render(suggestions) {\n                    if (!that.canceled && query === that.query) {\n                        that._render(query, suggestions);\n                    }\n                }\n            },\n            cancel: function cancel() {\n                this.canceled = true;\n            },\n            clear: function clear() {\n                this.cancel();\n                this.$el.empty();\n                this.trigger(\"rendered\");\n            },\n            isEmpty: function isEmpty() {\n                return this.$el.is(\":empty\");\n            },\n            destroy: function destroy() {\n                this.$el = null;\n            }\n        });\n        return Dataset;\n        function getDisplayFn(display) {\n            display = display || \"value\";\n            return _.isFunction(display) ? display : displayFn;\n            function displayFn(obj) {\n                return obj[display];\n            }\n        }\n        function getTemplates(templates, displayFn) {\n            return {\n                empty: templates.empty && _.templatify(templates.empty),\n                header: templates.header && _.templatify(templates.header),\n                footer: templates.footer && _.templatify(templates.footer),\n                suggestion: templates.suggestion || suggestionTemplate\n            };\n            function suggestionTemplate(context) {\n                return \"<p>\" + displayFn(context) + \"</p>\";\n            }\n        }\n        function isValidName(str) {\n            return /^[_a-zA-Z0-9-]+$/.test(str);\n        }\n    }();\n    var Dropdown = function() {\n        function Dropdown(o) {\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\n            o = o || {};\n            if (!o.menu) {\n                $.error(\"menu is required\");\n            }\n            this.isOpen = false;\n            this.isEmpty = true;\n            this.datasets = _.map(o.datasets, initializeDataset);\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\n            _.each(this.datasets, function(dataset) {\n                that.$menu.append(dataset.getRoot());\n                dataset.onSync(\"rendered\", that._onRendered, that);\n            });\n        }\n        _.mixin(Dropdown.prototype, EventEmitter, {\n            _onSuggestionClick: function onSuggestionClick($e) {\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\n            },\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\n                this._removeCursor();\n                this._setCursor($($e.currentTarget), true);\n            },\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\n                this._removeCursor();\n            },\n            _onRendered: function onRendered() {\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\n                this.trigger(\"datasetRendered\");\n                function isDatasetEmpty(dataset) {\n                    return dataset.isEmpty();\n                }\n            },\n            _hide: function() {\n                this.$menu.hide();\n            },\n            _show: function() {\n                this.$menu.css(\"display\", \"block\");\n            },\n            _getSuggestions: function getSuggestions() {\n                return this.$menu.find(\".tt-suggestion\");\n            },\n            _getCursor: function getCursor() {\n                return this.$menu.find(\".tt-cursor\").first();\n            },\n            _setCursor: function setCursor($el, silent) {\n                $el.first().addClass(\"tt-cursor\");\n                !silent && this.trigger(\"cursorMoved\");\n            },\n            _removeCursor: function removeCursor() {\n                this._getCursor().removeClass(\"tt-cursor\");\n            },\n            _moveCursor: function moveCursor(increment) {\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\n                if (!this.isOpen) {\n                    return;\n                }\n                $oldCursor = this._getCursor();\n                $suggestions = this._getSuggestions();\n                this._removeCursor();\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\n                if (newCursorIndex === -1) {\n                    this.trigger(\"cursorRemoved\");\n                    return;\n                } else if (newCursorIndex < -1) {\n                    newCursorIndex = $suggestions.length - 1;\n                }\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\n                this._ensureVisible($newCursor);\n            },\n            _ensureVisible: function ensureVisible($el) {\n                var elTop, elBottom, menuScrollTop, menuHeight;\n                elTop = $el.position().top;\n                elBottom = elTop + $el.outerHeight(true);\n                menuScrollTop = this.$menu.scrollTop();\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\n                if (elTop < 0) {\n                    this.$menu.scrollTop(menuScrollTop + elTop);\n                } else if (menuHeight < elBottom) {\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\n                }\n            },\n            close: function close() {\n                if (this.isOpen) {\n                    this.isOpen = false;\n                    this._removeCursor();\n                    this._hide();\n                    this.trigger(\"closed\");\n                }\n            },\n            open: function open() {\n                if (!this.isOpen) {\n                    this.isOpen = true;\n                    !this.isEmpty && this._show();\n                    this.trigger(\"opened\");\n                }\n            },\n            setLanguageDirection: function setLanguageDirection(dir) {\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\n            },\n            moveCursorUp: function moveCursorUp() {\n                this._moveCursor(-1);\n            },\n            moveCursorDown: function moveCursorDown() {\n                this._moveCursor(+1);\n            },\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\n                var datum = null;\n                if ($el.length) {\n                    datum = {\n                        raw: Dataset.extractDatum($el),\n                        value: Dataset.extractValue($el),\n                        datasetName: Dataset.extractDatasetName($el)\n                    };\n                }\n                return datum;\n            },\n            getDatumForCursor: function getDatumForCursor() {\n                return this.getDatumForSuggestion(this._getCursor().first());\n            },\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\n                return this.getDatumForSuggestion(this._getSuggestions().first());\n            },\n            update: function update(query) {\n                _.each(this.datasets, updateDataset);\n                function updateDataset(dataset) {\n                    dataset.update(query);\n                }\n            },\n            empty: function empty() {\n                _.each(this.datasets, clearDataset);\n                this.isEmpty = true;\n                function clearDataset(dataset) {\n                    dataset.clear();\n                }\n            },\n            isVisible: function isVisible() {\n                return this.isOpen && !this.isEmpty;\n            },\n            destroy: function destroy() {\n                this.$menu.off(\".tt\");\n                this.$menu = null;\n                _.each(this.datasets, destroyDataset);\n                function destroyDataset(dataset) {\n                    dataset.destroy();\n                }\n            }\n        });\n        return Dropdown;\n        function initializeDataset(oDataset) {\n            return new Dataset(oDataset);\n        }\n    }();\n    var Typeahead = function() {\n        var attrsKey = \"ttAttrs\";\n        function Typeahead(o) {\n            var $menu, $input, $hint;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"missing input\");\n            }\n            this.isActivated = false;\n            this.autoselect = !!o.autoselect;\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\n            this.$node = buildDomStructure(o.input, o.withHint);\n            $menu = this.$node.find(\".tt-dropdown-menu\");\n            $input = this.$node.find(\".tt-input\");\n            $hint = this.$node.find(\".tt-hint\");\n            $input.on(\"blur.tt\", function($e) {\n                var active, isActive, hasActive;\n                active = document.activeElement;\n                isActive = $menu.is(active);\n                hasActive = $menu.has(active).length > 0;\n                if (_.isMsie() && (isActive || hasActive)) {\n                    $e.preventDefault();\n                    $e.stopImmediatePropagation();\n                    _.defer(function() {\n                        $input.focus();\n                    });\n                }\n            });\n            $menu.on(\"mousedown.tt\", function($e) {\n                $e.preventDefault();\n            });\n            this.eventBus = o.eventBus || new EventBus({\n                el: $input\n            });\n            this.dropdown = new Dropdown({\n                menu: $menu,\n                datasets: o.datasets\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\n            this.input = new Input({\n                input: $input,\n                hint: $hint\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\n            this._setLanguageDirection();\n        }\n        _.mixin(Typeahead.prototype, {\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\n                var datum;\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\n                    this._select(datum);\n                }\n            },\n            _onCursorMoved: function onCursorMoved() {\n                var datum = this.dropdown.getDatumForCursor();\n                this.input.setInputValue(datum.value, true);\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\n            },\n            _onCursorRemoved: function onCursorRemoved() {\n                this.input.resetInputValue();\n                this._updateHint();\n            },\n            _onDatasetRendered: function onDatasetRendered() {\n                this._updateHint();\n            },\n            _onOpened: function onOpened() {\n                this._updateHint();\n                this.eventBus.trigger(\"opened\");\n            },\n            _onClosed: function onClosed() {\n                this.input.clearHint();\n                this.eventBus.trigger(\"closed\");\n            },\n            _onFocused: function onFocused() {\n                this.isActivated = true;\n                this.dropdown.open();\n            },\n            _onBlurred: function onBlurred() {\n                this.isActivated = false;\n                this.dropdown.empty();\n                this.dropdown.close();\n                this.setVal(\"\", true); //LM\n            },\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\n                var cursorDatum, topSuggestionDatum;\n                cursorDatum = this.dropdown.getDatumForCursor();\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\n                if (cursorDatum) {\n                    this._select(cursorDatum);\n                    $e.preventDefault();\n                } else if (this.autoselect && topSuggestionDatum) {\n                    this._select(topSuggestionDatum);\n                    $e.preventDefault();\n                }\n            },\n            _onTabKeyed: function onTabKeyed(type, $e) {\n                var datum;\n                if (datum = this.dropdown.getDatumForCursor()) {\n                    this._select(datum);\n                    $e.preventDefault();\n                } else {\n                    this._autocomplete(true);\n                }\n            },\n            _onEscKeyed: function onEscKeyed() {\n                this.dropdown.close();\n                this.input.resetInputValue();\n            },\n            _onUpKeyed: function onUpKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\n                this.dropdown.open();\n            },\n            _onDownKeyed: function onDownKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\n                this.dropdown.open();\n            },\n            _onLeftKeyed: function onLeftKeyed() {\n                this.dir === \"rtl\" && this._autocomplete();\n            },\n            _onRightKeyed: function onRightKeyed() {\n                this.dir === \"ltr\" && this._autocomplete();\n            },\n            _onQueryChanged: function onQueryChanged(e, query) {\n                this.input.clearHintIfInvalid();\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\n                this.dropdown.open();\n                this._setLanguageDirection();\n            },\n            _onWhitespaceChanged: function onWhitespaceChanged() {\n                this._updateHint();\n                this.dropdown.open();\n            },\n            _setLanguageDirection: function setLanguageDirection() {\n                var dir;\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\n                    this.dir = dir;\n                    this.$node.css(\"direction\", dir);\n                    this.dropdown.setLanguageDirection(dir);\n                }\n            },\n            _updateHint: function updateHint() {\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\n                datum = this.dropdown.getDatumForTopSuggestion();\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\n                    val = this.input.getInputValue();\n                    query = Input.normalizeQuery(val);\n                    escapedQuery = _.escapeRegExChars(query);\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\n                    match = frontMatchRegEx.exec(datum.value);\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\n                } else {\n                    this.input.clearHint();\n                }\n            },\n            _autocomplete: function autocomplete(laxCursor) {\n                var hint, query, isCursorAtEnd, datum;\n                hint = this.input.getHint();\n                query = this.input.getQuery();\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\n                if (hint && query !== hint && isCursorAtEnd) {\n                    datum = this.dropdown.getDatumForTopSuggestion();\n                    datum && this.input.setInputValue(datum.value);\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\n                }\n            },\n            _select: function select(datum) {\n                this.input.setQuery(datum.value);\n                this.input.setInputValue(datum.value, true);\n                this._setLanguageDirection();\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\n                this.dropdown.close();\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\n            },\n            open: function open() {\n                this.dropdown.open();\n            },\n            close: function close() {\n                this.dropdown.close();\n            },\n            setVal: function setVal(val) {\n                if (this.isActivated) {\n                    this.input.setInputValue(val);\n                } else {\n                    this.input.setQuery(val);\n                    this.input.setInputValue(val, true);\n                }\n                this._setLanguageDirection();\n            },\n            getVal: function getVal() {\n                return this.input.getQuery();\n            },\n            destroy: function destroy() {\n                this.input.destroy();\n                this.dropdown.destroy();\n                destroyDomStructure(this.$node);\n                this.$node = null;\n            }\n        });\n        return Typeahead;\n        function buildDomStructure(input, withHint) {\n            var $input, $wrapper, $dropdown, $hint;\n            $input = $(input);\n            $wrapper = $(html.wrapper).css(css.wrapper);\n            $dropdown = $(html.dropdown).css(css.dropdown);\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\n                autocomplete: \"off\",\n                spellcheck: \"false\"\n            });\n            $input.data(attrsKey, {\n                dir: $input.attr(\"dir\"),\n                autocomplete: $input.attr(\"autocomplete\"),\n                spellcheck: $input.attr(\"spellcheck\"),\n                style: $input.attr(\"style\")\n            });\n            $input.addClass(\"tt-input\").attr({\n                autocomplete: \"off\",\n                spellcheck: false\n            }).css(withHint ? css.input : css.inputWithNoHint);\n            try {\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\n            } catch (e) {}\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\n        }\n        function getBackgroundStyles($el) {\n            return {\n                backgroundAttachment: $el.css(\"background-attachment\"),\n                backgroundClip: $el.css(\"background-clip\"),\n                backgroundColor: $el.css(\"background-color\"),\n                backgroundImage: $el.css(\"background-image\"),\n                backgroundOrigin: $el.css(\"background-origin\"),\n                backgroundPosition: $el.css(\"background-position\"),\n                backgroundRepeat: $el.css(\"background-repeat\"),\n                backgroundSize: $el.css(\"background-size\")\n            };\n        }\n        function destroyDomStructure($node) {\n            var $input = $node.find(\".tt-input\");\n            _.each($input.data(attrsKey), function(val, key) {\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\n            });\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\n            $node.remove();\n        }\n    }();\n    (function() {\n        var old, typeaheadKey, methods;\n        old = $.fn.typeahead;\n        typeaheadKey = \"ttTypeahead\";\n        methods = {\n            initialize: function initialize(o, datasets) {\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\n                o = o || {};\n                return this.each(attach);\n                function attach() {\n                    var $input = $(this), eventBus, typeahead;\n                    _.each(datasets, function(d) {\n                        d.highlight = !!o.highlight;\n                    });\n                    typeahead = new Typeahead({\n                        input: $input,\n                        eventBus: eventBus = new EventBus({\n                            el: $input\n                        }),\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\n                        minLength: o.minLength,\n                        autoselect: o.autoselect,\n                        datasets: datasets\n                    });\n                    $input.data(typeaheadKey, typeahead);\n                }\n            },\n            open: function open() {\n                return this.each(openTypeahead);\n                function openTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.open();\n                    }\n                }\n            },\n            close: function close() {\n                return this.each(closeTypeahead);\n                function closeTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.close();\n                    }\n                }\n            },\n            val: function val(newVal) {\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\n                function setVal() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.setVal(newVal);\n                    }\n                }\n                function getVal($input) {\n                    var typeahead, query;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        query = typeahead.getVal();\n                    }\n                    return query;\n                }\n            },\n            destroy: function destroy() {\n                return this.each(unattach);\n                function unattach() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.destroy();\n                        $input.removeData(typeaheadKey);\n                    }\n                }\n            }\n        };\n        $.fn.typeahead = function(method) {\n            if (methods[method]) {\n                return methods[method].apply(this, [].slice.call(arguments, 1));\n            } else {\n                return methods.initialize.apply(this, arguments);\n            }\n        };\n        $.fn.typeahead.noConflict = function noConflict() {\n            $.fn.typeahead = old;\n            return this;\n        };\n    })();\n    \n    \n    \n//})(window.jQuery);\n\n\n});\n",
        -    "define('searchView',[\n  'App',\n  // Templates\n  'text!tpl/search.html',\n  'text!tpl/search_suggestion.html',\n  // Tools\n  'typeahead'\n], function(App, searchTpl, suggestionTpl) {\n\n  var searchView = Backbone.View.extend({\n    el: '#search',\n    /**\n     * Init.\n     */\n    init: function() {\n      var tpl = _.template(searchTpl);\n      var className = 'form-control input-lg';\n      var placeholder = 'Search reference';\n      this.searchHtml = tpl({\n        'placeholder': placeholder,\n        'className': className\n      });\n      this.items = App.classes.concat(App.allItems);\n\n      return this;\n    },\n    /**\n     * Render input field with Typehead activated.\n     */\n    render: function() {\n      // Append the view to the dom\n      this.$el.append(this.searchHtml);\n\n      // Render Typeahead\n      var $searchInput = this.$el.find('input[type=text]');\n      this.typeaheadRender($searchInput);\n      this.typeaheadEvents($searchInput);\n\n      return this;\n    },\n    /**\n     * Apply Twitter Typeahead to the search input field.\n     * @param {jquery} $input\n     */\n    typeaheadRender: function($input) {\n      var self = this;\n      $input.typeahead(null, {\n        'displayKey': 'name',\n        'minLength': 2,\n        //'highlight': true,\n        'source': self.substringMatcher(this.items),\n        'templates': {\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\n          'suggestion': _.template(suggestionTpl)\n        }\n      });\n    },\n    /**\n     * Setup typeahead custom events (item selected).\n     */\n    typeaheadEvents: function($input) {\n      var self = this;\n      $input.on('typeahead:selected', function(e, item, datasetName) {\n        var selectedItem = self.items[item.idx];\n        select(selectedItem);\n      });\n      $input.on('keydown', function(e) {\n        if (e.which === 13) { // enter\n          var txt = $input.val();\n          var f = _.find(self.items, function(it) { return it.name == txt; });\n          if (f) {\n            select(f);\n          }\n        } else if (e.which === 27) {\n          $input.blur();\n        }\n      });\n\n      function select(selectedItem) {\n        var hash = App.router.getHash(selectedItem);//\n        App.router.navigate(hash, {'trigger': true});\n        $('#item').focus();\n      }\n    },\n    /**\n     * substringMatcher function for Typehead (search for strings in an array).\n     * @param {array} array\n     * @returns {Function}\n     */\n    substringMatcher: function(array) {\n      return function findMatches(query, callback) {\n        var matches = [], substrRegex, arrayLength = array.length;\n\n        // regex used to determine if a string contains the substring `query`\n        substrRegex = new RegExp(query, 'i');\n\n        // iterate through the pool of strings and for any string that\n        // contains the substring `query`, add it to the `matches` array\n        for (var i=0; i < arrayLength; i++) {\n          var item = array[i];\n          if (substrRegex.test(item.name)) {\n            // typeahead expects suggestions to be a js object\n            matches.push({\n              'itemtype': item.itemtype,\n              'name': item.name,\n              'className': item.class,\n              'is_constructor': !!item.is_constructor,\n              'final': item.final,\n              'idx': i\n            });\n          }\n        }\n\n        callback(matches);\n      };\n    }\n\n  });\n\n  return searchView;\n\n});\n\n",
        -    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\n  <div class=\"reference-group clearfix main-ref-page\">  \\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\n      <div class=\"reference-subgroup\">\\n        <% if (subgroup.name !== \\'0\\') { %>\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\n        <% } %>\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\n        <% _.each(subgroup.items, function(item) { %>\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\n        <% }); %>\\n        </ul>\\n      </div>\\n    <% }); %>\\n    </div>\\n  </div>\\n<% }); %>\\n';});\n\n",
        -    "define('listView',[\n  'App',\n  // Templates\n  'text!tpl/list.html'\n], function (App, listTpl) {\n  var striptags = function(html) {\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.textContent;\n  };\n\n  var listView = Backbone.View.extend({\n    el: '#list',\n    events: {},\n    /**\n     * Init.\n     */\n    init: function () {\n      this.listTpl = _.template(listTpl);\n\n      return this;\n    },\n    /**\n     * Render the list.\n     */\n    render: function (items, listCollection) {\n      if (items && listCollection) {\n        var self = this;\n\n        // Render items and group them by module\n        // module === group\n        this.groups = {};\n        _.each(items, function (item, i) {\n\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n\n            var group = item.module || '_';\n            var subgroup = item.submodule || '_';\n            if (group === subgroup) {\n              subgroup = '0';\n            }\n            var hash = App.router.getHash(item);\n\n            // Create a group list\n            if (!self.groups[group]) {\n              self.groups[group] = {\n                name: group.replace('_', '&nbsp;'),\n                subgroups: {}\n              };\n            }\n\n            // Create a subgroup list\n            if (!self.groups[group].subgroups[subgroup]) {\n              self.groups[group].subgroups[subgroup] = {\n                name: subgroup.replace('_', '&nbsp;'),\n                items: []\n              };\n            }\n\n            // hide the un-interesting constants\n            if (group === 'Constants' && !item.example)\n              return;\n\n            if (item.class === 'p5') {\n\n              self.groups[group].subgroups[subgroup].items.push(item);\n\n            } else {\n\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\n                function(i){ return i.name == item.class; });\n\n              if (!found) {\n\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\n                var ind = hash.lastIndexOf('/');\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\n                self.groups[group].subgroups[subgroup].items.push({\n                  name: item.class,\n                  hash: hash\n                });\n              }\n\n            }\n          }\n        });\n\n        // Put the <li> items html into the list <ul>\n        var listHtml = self.listTpl({\n          'striptags': striptags,\n          'title': self.capitalizeFirst(listCollection),\n          'groups': self.groups,\n          'listCollection': listCollection\n        });\n\n        // Render the view\n        this.$el.html(listHtml);\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Show a list of items.\n     * @param {array} items Array of item objects.\n     * @returns {object} This view.\n     */\n    show: function (listGroup) {\n      if (App[listGroup]) {\n        this.render(App[listGroup], listGroup);\n      }\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function (str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n\n\n\n  });\n\n  return listView;\n\n});\n\n",
        -    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\n\\n<% if (item.example) { %>\\n<div class=\"example\">\\n  <h3 id=\"reference-example\">Examples</h3>\\n\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\n    <% _.each(item.example, function(example, i){ %>\\n      <%= example %>\\n    <% }); %>\\n  </div>\\n</div>\\n<% } %>\\n\\n<div class=\"description\">\\n    \\n  <h3 id=\"reference-description\">Description</h3>\\n\\n  <% if (item.deprecated) { %>\\n    <p>\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n    </p>\\n  <% } %>\\n      \\n\\n  <span class=\\'description-text\\'><%= item.description %></span>\\n\\n  <% if (item.extends) { %>\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\n  <% } %>\\n\\n  <% if (item.module === \\'p5.sound\\') { %>\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\n    </p>\\n  <% } %>\\n\\n  <% if (item.constRefs) { %>\\n    <p>Used by:\\n  <%\\n      var refs = item.constRefs;\\n      for (var i = 0; i < refs.length; i ++) {\\n        var ref = refs[i];\\n        var name = ref;\\n        if (name.substr(0, 3) === \\'p5.\\') {\\n          name = name.substr(3);\\n        }\\n  if (i !== 0) {\\n          if (i == refs.length - 1) {\\n            %> and <%\\n          } else {\\n            %>, <%\\n          }\\n        }\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\n      }\\n  %>\\n    </p>\\n  <% } %>\\n</div>\\n\\n<% if (isConstructor || !isClass) { %>\\n\\n<div>\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\n  <p>\\n    <% syntaxes.forEach(function(syntax) { %>\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\n    <% }) %>\\n  </p>\\n</div>\\n\\n\\n<% if (item.params) { %>\\n  <div class=\"params\">\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\n    <% for (var i=0; i<item.params.length; i++) { %>\\n      <% var p = item.params[i] %>\\n      <li>\\n        <div class=\\'paramname\\'><%=p.name%></div>\\n        <% if (p.type) { %>\\n          <div class=\\'paramtype\\'>\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\n          <% if (p.optional) { %> (Optional)<% } %>\\n          </div>\\n        <% } %>\\n      </li>\\n    <% } %>\\n    </ul>\\n  </div>\\n<% } %>\\n\\n<% if (item.return && item.return.type) { %>\\n  <div>\\n    <h3 id=\"reference-returns\">Returns</h3>\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\n  </div>\\n<% } %>\\n\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n<div class=\"constructor\">\\n  <!--<h2>Constructor</h2>--> \\n  <%=constructor%>\\n</div>\\n<% } %>\\n\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n  <h4>Fields</h4>\\n  <p>\\n    <% _.each(fields, function(item) { %>\\n      <a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%></a>: <%= item.description %>\\n      <br>\\n    <% }); %>\\n  </p>\\n<% } %>\\n\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n  <h4>Methods</h4>\\n  <p>\\n    <table>\\n    <% _.each(methods, function(item) { %>\\n      <tr>\\n      <td><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></td><td><div class=\"method_description\"><%= item.description %></div></td>\\n      </tr>\\n    <% }); %>\\n    </table>\\n  </p>\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\n<br><br>\\n\\n<div>\\n<% if (item.file && item.line) { %>\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\n<% } %>\\n</div>\\n\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\n<br><br>\\n';});\n\n",
        -    "// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n * <p>\n * For a fairly comprehensive set of languages see the\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n * file that came with this source.  At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n * <p>\n * Usage: <ol>\n * <li> include this source file in an html page via\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\n * <li> define style rules.  See the example page for examples.\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n\ndefine(\"prettify\", function(){});\n\n",
        -    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function(App, itemTpl, classTpl, endTpl) {\n  'use strict';\n\n  var appVersion = App.project.version || 'master';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function() {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) {\n        syntax += 'new ';\n      } else if (cleanItem.static && cleanItem.class) {\n        syntax += cleanItem.class + '.';\n      }\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i = 0; i < cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) {\n              syntax += '[';\n            }\n            syntax += p.name;\n            if (p.optdefault) {\n              syntax += '=' + p.optdefault;\n            }\n            if (p.optional) {\n              syntax += ']';\n            }\n            if (i !== cleanItem.params.length - 1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function(item) {\n      if (item) {\n        var itemHtml = '';\n        var cleanItem = this.clean(item);\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\n        var collectionName = isClass\n            ? 'Constructor'\n            : this.capitalizeFirst(cleanItem.itemtype),\n          isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c) {\n            return c.name === cleanItem.name;\n          });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n        } else {\n          cleanItem.constRefs =\n            item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode(cleanItem.name);\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === 'method') {\n          App.pageView.appendToDocumentTitle(item.name + '()');\n        } else {\n          App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts)\n              .data('alt')\n              .split('\\n');\n\n            var canvases = $('.cnv_div');\n            for (var j = 0; j < alts.length; j++) {\n              if (j < canvases.length) {\n                $(canvases[j]).append(\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\n                );\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function(item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function(item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      $('#item').focus();\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function() {\n      this.$el.html(\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\n      );\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function(str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n});\n\n",
        -    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\n  <br>\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\n</div>\\n\\n<div id=\\'collection-list-categories\\'>\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\n<% var i=0; %>\\n<% var max=Math.floor(groups.length/4); %>\\n<% var rem=groups.length%4; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% var m = rem > 0 ? 1 : 0 %>\\n  <% if (i === 0) { %>\\n    <ul aria-labelledby=\"categories\">\\n    <% } %>\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\n    <% if (i === (max+m-1)) { %>\\n    </ul>\\n  \\t<% rem-- %>\\n  \\t<% i=0 %>\\n  <% } else { %>\\n  \\t<% i++ %>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define('menuView',[\n  'App',\n  'text!tpl/menu.html'\n], function(App, menuTpl) {\n\n  var menuView = Backbone.View.extend({\n    el: '#collection-list-nav',\n    /**\n     * Init.\n     * @returns {object} This view.\n     */\n    init: function() {\n      this.menuTpl = _.template(menuTpl);\n      return this;\n    },\n    /**\n     * Render.\n     * @returns {object} This view.\n     */\n    render: function() {\n\n      var groups = [];\n      _.each(App.modules, function (item, i) {\n        if (!item.is_submodule) {\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n            groups.push(item.name);\n          }\n        }\n        //}\n      });\n\n      // Sort groups by name A-Z\n      groups.sort();\n\n      var menuHtml = this.menuTpl({\n        'groups': groups\n      });\n\n      // Render the view\n      this.$el.html(menuHtml);\n    },\n\n    hide: function() {\n      this.$el.hide();\n    },\n\n    show: function() {\n      this.$el.show();\n    },\n\n    /**\n     * Update the menu.\n     * @param {string} el The name of the current route.\n     */\n    update: function(menuItem) {\n      //console.log(menuItem);\n      // this.$menuItems.removeClass('active');\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\n\n    }\n  });\n\n  return menuView;\n\n});\n\n",
        -    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\n\\n<p><%= module.description %></p>\\n\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\n\\n<% var t = 0; col = 0; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% if (t == 0) { %> \\n    <div class=\"column_<%=col%>\">\\n  <% } %>\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\n    <% if (group.hash) { %> </a> <% } %>\\n  <% } %>\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\n    <% t++; %>\\n  <% }); %>\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\n    </div>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define(\n  'libraryView',[\n    'App',\n    // Templates\n    'text!tpl/library.html'\n  ],\n  function(App, libraryTpl) {\n    var libraryView = Backbone.View.extend({\n      el: '#list',\n      events: {},\n      /**\n       * Init.\n       */\n      init: function() {\n        this.libraryTpl = _.template(libraryTpl);\n\n        return this;\n      },\n      /**\n       * Render the list.\n       */\n      render: function(m, listCollection) {\n        if (m && listCollection) {\n          var self = this;\n\n          // Render items and group them by module\n          // module === group\n          this.groups = {};\n          _.each(m.items, function(item, i) {\n            var module = item.module || '_';\n            var group;\n            // Override default group with a selected category\n            // TODO: Overwriting with the first category might not be the best choice\n            // We might also want to have links for categories\n            if (item.category && item.category[0]) {\n              group = item.category[0];\n              // Populate item.hash\n              App.router.getHash(item);\n\n              // Create a group list without link hash\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: undefined,\n                  items: []\n                };\n              }\n            } else {\n              group = item.class || '_';\n              var hash = App.router.getHash(item);\n\n              var ind = hash.lastIndexOf('/');\n              hash = hash.substring(0, ind);\n\n              // Create a group list\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: hash,\n                  items: []\n                };\n              }\n            }\n\n            self.groups[group].items.push(item);\n          });\n\n          // Sort groups by name A-Z\n          self.groups = _.sortBy(self.groups, this.sortByName);\n\n          // Put the <li> items html into the list <ul>\n          var libraryHtml = self.libraryTpl({\n            title: self.capitalizeFirst(listCollection),\n            module: m.module,\n            totalItems: m.items.length,\n            groups: self.groups\n          });\n\n          // Render the view\n          this.$el.html(libraryHtml);\n        }\n\n        return this;\n      },\n      /**\n       * Show a list of items.\n       * @param {array} items Array of item objects.\n       * @returns {object} This view.\n       */\n      show: function(listGroup) {\n        if (App[listGroup]) {\n          this.render(App[listGroup], listGroup);\n        }\n        App.pageView.hideContentViews();\n\n        this.$el.show();\n\n        return this;\n      },\n      /**\n       * Helper method to capitalize the first letter of a string\n       * @param {string} str\n       * @returns {string} Returns the string.\n       */\n      capitalizeFirst: function(str) {\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\n      },\n      /**\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\n       * @param {string} a\n       * @param {string} b\n       * @returns {Array} Returns an array with elements sorted from A to Z.\n       */\n      sortAZ: function(a, b) {\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\n      },\n\n      sortByName: function(a, b) {\n        if (a.name === 'p5') return -1;\n        else return 0;\n      }\n    });\n\n    return libraryView;\n  }\n);\n\n",
        -    "define('pageView',[\n  'App',\n\n  // Views\n  'searchView',\n  'listView',\n  'itemView',\n  'menuView',\n  'libraryView'\n], function(App, searchView, listView, itemView, menuView, libraryView) {\n\n  // Store the original title parts so we can substitue different endings.\n  var _originalDocumentTitle = window.document.title;\n\n  var pageView = Backbone.View.extend({\n    el: 'body',\n    /**\n     * Init.\n     */\n    init: function() {\n      App.$container = $('#container');\n      App.contentViews = [];\n\n      return this;\n    },\n    /**\n     * Render.\n     */\n    render: function() {\n\n      // Menu view\n      if (!App.menuView) {\n        App.menuView = new menuView();\n        App.menuView.init().render();\n      }\n\n      // Item view\n      if (!App.itemView) {\n        App.itemView = new itemView();\n        App.itemView.init().render();\n        // Add the item view to the views array\n        App.contentViews.push(App.itemView);\n      }\n\n      // List view\n      if (!App.listView) {\n        App.listView = new listView();\n        App.listView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.listView);\n      }\n\n      // Library view\n      if (!App.libraryView) {\n        App.libraryView = new libraryView();\n        App.libraryView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.libraryView);\n      }\n\n      // Search\n      if (!App.searchView) {\n        App.searchView = new searchView();\n        App.searchView.init().render();\n      }\n      return this;\n    },\n    /**\n     * Hide item and list views.\n     * @returns {object} This view.\n     */\n    hideContentViews: function() {\n      _.each(App.contentViews, function(view, i) {\n        view.$el.hide();\n      });\n\n      return this;\n    },\n    /**\n     * Append the supplied name to the first part of original document title.\n     * If no name is supplied, the title will reset to the original one.\n     */\n    appendToDocumentTitle: function(name){\n      if(name){\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\n        window.document.title = [firstTitlePart, name].join(\" | \");\n      } else {\n        window.document.title = _originalDocumentTitle;\n      }\n    }    \n  });\n\n  return pageView;\n\n});\n\n",
        -    "define('router',[\n  'App'\n], function(App) {\n\n  'use strict'; //\n\n  var Router = Backbone.Router.extend({\n\n    routes: {\n      '': 'list',\n      'p5': 'list',\n      'p5/': 'list',\n      'classes': 'list',\n      'search': 'search',\n      'libraries/:lib': 'library',\n      ':searchClass(/:searchItem)': 'get'\n    },\n    /**\n     * Whether the json API data was loaded.\n     */\n    _initialized: false,\n    /**\n     * Initialize the app: load json API data and create searchable arrays.\n     */\n    init: function(callback) {\n      var self = this;\n      require(['pageView'], function(pageView) {\n\n        // If already initialized, move away from here!\n        if (self._initialized) {\n          if (callback)\n            callback();\n          return;\n        }\n\n        // Update initialization state: must be done now to avoid recursive mess\n        self._initialized = true;\n\n        // Render views\n        if (!App.pageView) {\n          App.pageView = new pageView();\n          App.pageView.init().render();\n        }\n\n        // If a callback is set (a route has already been called), run it\n        // otherwise, show the default list\n        if (callback)\n          callback();\n        else\n          self.list();\n      });\n    },\n    /**\n     * Start route. Simply check if initialized.\n     */\n    start: function() {\n      this.init();\n    },\n    /**\n     * Show item details by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     */\n    get: function(searchClass, searchItem) {\n\n      // if looking for a library page, redirect\n      if (searchClass === 'p5.sound' && !searchItem) {\n        window.location.hash = '/libraries/'+searchClass;\n        return;\n      }\n\n      var self = this;\n      this.init(function() {\n        var item = self.getItem(searchClass, searchItem);\n\n        App.menuView.hide();\n\n        if (item) {\n          App.itemView.show(item);\n        } else {\n          //App.itemView.nothingFound();\n\n          self.list();\n        }\n\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Returns one item object by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     * @returns {object} The item found or undefined if nothing was found.\n     */\n    getItem: function(searchClass, searchItem) {\n      var classes = App.classes,\n              items = App.allItems,\n              classesCount = classes.length,\n              itemsCount = items.length,\n              className = searchClass ? searchClass.toLowerCase() : undefined,\n              itemName = searchItem ? searchItem : undefined,\n              found;\n\n      // Only search for a class, if itemName is undefined\n      if (className && !itemName) {\n        for (var i = 0; i < classesCount; i++) {\n          if (classes[i].name.toLowerCase() === className) {\n            found = classes[i];\n            _.each(found.items, function(i, idx) {\n              i.hash = App.router.getHash(i);\n            });\n            break;\n          }\n        }\n        // Search for a class item\n      } else if (className && itemName) {\n        // Search case sensitively\n        for (var i = 0; i < itemsCount; i++) {\n          if (items[i].class.toLowerCase() === className &&\n            items[i].name === itemName) {\n            found = items[i];\n            break;\n          }\n        }\n\n        // If no match was found, fallback to search case insensitively\n        if(!found){\n          for (var i = 0; i < itemsCount; i++) {\n            if(items[i].class.toLowerCase() === className &&\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\n              found = items[i];\n              break;\n            }\n          }\n        }\n      }\n\n      return found;\n    },\n    /**\n     * List items.\n     * @param {string} collection The name of the collection to list.\n     */\n    list: function(collection) {\n\n      collection = 'allItems';\n\n      // Make sure collection is valid\n      if (App.collections.indexOf(collection) < 0) {\n        return;\n      }\n\n      this.init(function() {\n        App.menuView.show(collection);\n        App.menuView.update(collection);\n        App.listView.show(collection);\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Display information for a library.\n     * @param {string} collection The name of the collection to list.\n     */\n    library: function(collection) {\n      this.init(function() {\n        App.menuView.hide();\n        App.libraryView.show(collection.substring(3)); //remove p5.\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Close all content views.\n     */\n    search: function() {\n      this.init(function() {\n        App.menuView.hide();\n        App.pageView.hideContentViews();\n      });\n    },\n\n    /**\n     * Create an hash/url for the item.\n     * @param {Object} item A class, method, property or event object.\n     * @returns {String} The hash string, including the '#'.\n     */\n     getHash: function(item) {\n\n       if (!item.hash) {\n\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\n\n         if (item.class) {\n           var clsFunc = '#/' + item.class + '.' + item.name;\n           var idx = clsFunc.lastIndexOf('.');\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\n         } else {\n          item.hash = '#/' + item.name;\n         }\n       }\n\n       return item.hash;\n    }\n  });\n\n  \n  function styleCodeLinks() {\n    var links = document.getElementsByTagName(\"a\");\n    for (var iLink = 0; iLink < links.length; iLink++) {\n      var link = links[iLink];\n      if (link.hash.startsWith('#/p5')) {\n        link.classList.add('code');\n      }\n    }\n  }\n\n\n  // Get the router\n  App.router = new Router();\n\n  // Start history\n  Backbone.history.start();\n\n  return App.router;\n\n});\n\n",
        -    "/**\n * Define global App.\n */\nvar App = window.App || {};\ndefine('App', [],function() {\n  return App;\n});\n\n/**\n * Load json API data and start the router.\n * @param {module} App\n * @param {module} router\n */\nrequire([\n  'App',\n  './documented-method'], function(App, DocumentedMethod) {\n\n  // Set collections\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];\n\n  // Get json API data\n  $.getJSON('data.min.json', function(data) {\n    App.data = data;\n    App.classes = [];\n    App.methods = [];\n    App.properties = [];\n    App.events = [];\n    App.allItems = [];\n    App.sound = { items: [] };\n    App.dom = { items: [] };\n    App.modules = [];\n    App.project = data.project;\n\n\n    var modules = data.modules;\n\n    // Get class items (methods, properties, events)\n    _.each(modules, function(m, idx, array) {\n      App.modules.push(m);\n      if (m.name == \"p5.sound\") {\n        App.sound.module = m;\n      }\n    });\n\n\n    var items = data.classitems;\n    var classes = data.classes;\n\n    // Get classes\n    _.each(classes, function(c, idx, array) {\n      if (!c.private) {\n        App.classes.push(c);\n      }\n    });\n\n\n    // Get class items (methods, properties, events)\n    _.each(items, function(el, idx, array) {\n      if (el.itemtype) {\n        if (el.itemtype === \"method\") {\n          el = new DocumentedMethod(el);\n          App.methods.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"property\") {\n          App.properties.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"event\") {\n          App.events.push(el);\n          App.allItems.push(el);\n        }\n\n        // libraries\n        if (el.module === \"p5.sound\") {\n          App.sound.items.push(el);\n        }\n      }\n    });\n\n    _.each(App.classes, function(c, idx) {\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\n    });\n\n    require(['router']);\n  });\n});\n\ndefine(\"main\", function(){});\n\n",
        +    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\r\n(function (root, factory) {\r\n  if (typeof define === 'function' && define.amd) {\r\n    define('documented-method',[], factory);\r\n  } else if (typeof module === 'object' && module.exports) {\r\n    module.exports = factory();\r\n  } else {\r\n    root.DocumentedMethod = factory();\r\n  }\r\n}(this, function () {\r\n  function extend(target, src) {\r\n    Object.keys(src).forEach(function(prop) {\r\n      target[prop] = src[prop];\r\n    });\r\n    return target;\r\n  }\r\n\r\n  function DocumentedMethod(classitem) {\r\n    extend(this, classitem);\r\n\r\n    if (this.overloads) {\r\n      // Make each overload inherit properties from their parent\r\n      // classitem.\r\n      this.overloads = this.overloads.map(function(overload) {\r\n        return extend(Object.create(this), overload);\r\n      }, this);\r\n\r\n      if (this.params) {\r\n        throw new Error('params for overloaded methods should be undefined');\r\n      }\r\n\r\n      this.params = this._getMergedParams();\r\n    }\r\n  }\r\n\r\n  DocumentedMethod.prototype = {\r\n    // Merge parameters across all overloaded versions of this item.\r\n    _getMergedParams: function() {\r\n      var paramNames = {};\r\n      var params = [];\r\n\r\n      this.overloads.forEach(function(overload) {\r\n        if (!overload.params) {\r\n          return;\r\n        }\r\n        overload.params.forEach(function(param) {\r\n          if (param.name in paramNames) {\r\n            return;\r\n          }\r\n          paramNames[param.name] = param;\r\n          params.push(param);\r\n        });\r\n      });\r\n\r\n      return params;\r\n    }\r\n  };\r\n\r\n  return DocumentedMethod;\r\n}));\r\n\n",
        +    "/**\r\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\r\n * Available via the MIT or new BSD license.\r\n * see: http://github.com/requirejs/text for details\r\n */\r\n/*jslint regexp: true */\r\n/*global require, XMLHttpRequest, ActiveXObject,\r\n  define, window, process, Packages,\r\n  java, location, Components, FileUtils */\r\n\r\ndefine('text',['module'], function (module) {\r\n    'use strict';\r\n\r\n    var text, fs, Cc, Ci, xpcIsWindows,\r\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\r\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\r\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\r\n        hasLocation = typeof location !== 'undefined' && location.href,\r\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\r\n        defaultHostName = hasLocation && location.hostname,\r\n        defaultPort = hasLocation && (location.port || undefined),\r\n        buildMap = {},\r\n        masterConfig = (module.config && module.config()) || {};\r\n\r\n    text = {\r\n        version: '2.0.10',\r\n\r\n        strip: function (content) {\r\n            //Strips <?xml ...?> declarations so that external SVG and XML\r\n            //documents can be added to a document without worry. Also, if the string\r\n            //is an HTML document, only the part inside the body tag is returned.\r\n            if (content) {\r\n                content = content.replace(xmlRegExp, \"\");\r\n                var matches = content.match(bodyRegExp);\r\n                if (matches) {\r\n                    content = matches[1];\r\n                }\r\n            } else {\r\n                content = \"\";\r\n            }\r\n            return content;\r\n        },\r\n\r\n        jsEscape: function (content) {\r\n            return content.replace(/(['\\\\])/g, '\\\\$1')\r\n                .replace(/[\\f]/g, \"\\\\f\")\r\n                .replace(/[\\b]/g, \"\\\\b\")\r\n                .replace(/[\\n]/g, \"\\\\n\")\r\n                .replace(/[\\t]/g, \"\\\\t\")\r\n                .replace(/[\\r]/g, \"\\\\r\")\r\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\r\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\r\n        },\r\n\r\n        createXhr: masterConfig.createXhr || function () {\r\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\r\n            var xhr, i, progId;\r\n            if (typeof XMLHttpRequest !== \"undefined\") {\r\n                return new XMLHttpRequest();\r\n            } else if (typeof ActiveXObject !== \"undefined\") {\r\n                for (i = 0; i < 3; i += 1) {\r\n                    progId = progIds[i];\r\n                    try {\r\n                        xhr = new ActiveXObject(progId);\r\n                    } catch (e) {}\r\n\r\n                    if (xhr) {\r\n                        progIds = [progId];  // so faster next time\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            return xhr;\r\n        },\r\n\r\n        /**\r\n         * Parses a resource name into its component parts. Resource names\r\n         * look like: module/name.ext!strip, where the !strip part is\r\n         * optional.\r\n         * @param {String} name the resource name\r\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\r\n         * where strip is a boolean.\r\n         */\r\n        parseName: function (name) {\r\n            var modName, ext, temp,\r\n                strip = false,\r\n                index = name.indexOf(\".\"),\r\n                isRelative = name.indexOf('./') === 0 ||\r\n                             name.indexOf('../') === 0;\r\n\r\n            if (index !== -1 && (!isRelative || index > 1)) {\r\n                modName = name.substring(0, index);\r\n                ext = name.substring(index + 1, name.length);\r\n            } else {\r\n                modName = name;\r\n            }\r\n\r\n            temp = ext || modName;\r\n            index = temp.indexOf(\"!\");\r\n            if (index !== -1) {\r\n                //Pull off the strip arg.\r\n                strip = temp.substring(index + 1) === \"strip\";\r\n                temp = temp.substring(0, index);\r\n                if (ext) {\r\n                    ext = temp;\r\n                } else {\r\n                    modName = temp;\r\n                }\r\n            }\r\n\r\n            return {\r\n                moduleName: modName,\r\n                ext: ext,\r\n                strip: strip\r\n            };\r\n        },\r\n\r\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\r\n\r\n        /**\r\n         * Is an URL on another domain. Only works for browser use, returns\r\n         * false in non-browser environments. Only used to know if an\r\n         * optimized .js version of a text resource should be loaded\r\n         * instead.\r\n         * @param {String} url\r\n         * @returns Boolean\r\n         */\r\n        useXhr: function (url, protocol, hostname, port) {\r\n            var uProtocol, uHostName, uPort,\r\n                match = text.xdRegExp.exec(url);\r\n            if (!match) {\r\n                return true;\r\n            }\r\n            uProtocol = match[2];\r\n            uHostName = match[3];\r\n\r\n            uHostName = uHostName.split(':');\r\n            uPort = uHostName[1];\r\n            uHostName = uHostName[0];\r\n\r\n            return (!uProtocol || uProtocol === protocol) &&\r\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\r\n                   ((!uPort && !uHostName) || uPort === port);\r\n        },\r\n\r\n        finishLoad: function (name, strip, content, onLoad) {\r\n            content = strip ? text.strip(content) : content;\r\n            if (masterConfig.isBuild) {\r\n                buildMap[name] = content;\r\n            }\r\n            onLoad(content);\r\n        },\r\n\r\n        load: function (name, req, onLoad, config) {\r\n            //Name has format: some.module.filext!strip\r\n            //The strip part is optional.\r\n            //if strip is present, then that means only get the string contents\r\n            //inside a body tag in an HTML string. For XML/SVG content it means\r\n            //removing the <?xml ...?> declarations so the content can be inserted\r\n            //into the current doc without problems.\r\n\r\n            // Do not bother with the work if a build and text will\r\n            // not be inlined.\r\n            if (config.isBuild && !config.inlineText) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            masterConfig.isBuild = config.isBuild;\r\n\r\n            var parsed = text.parseName(name),\r\n                nonStripName = parsed.moduleName +\r\n                    (parsed.ext ? '.' + parsed.ext : ''),\r\n                url = req.toUrl(nonStripName),\r\n                useXhr = (masterConfig.useXhr) ||\r\n                         text.useXhr;\r\n\r\n            // Do not load if it is an empty: url\r\n            if (url.indexOf('empty:') === 0) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            //Load the text. Use XHR if possible and in a browser.\r\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\r\n                text.get(url, function (content) {\r\n                    text.finishLoad(name, parsed.strip, content, onLoad);\r\n                }, function (err) {\r\n                    if (onLoad.error) {\r\n                        onLoad.error(err);\r\n                    }\r\n                });\r\n            } else {\r\n                //Need to fetch the resource across domains. Assume\r\n                //the resource has been optimized into a JS module. Fetch\r\n                //by the module name + extension, but do not include the\r\n                //!strip part to avoid file system issues.\r\n                req([nonStripName], function (content) {\r\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\r\n                                    parsed.strip, content, onLoad);\r\n                });\r\n            }\r\n        },\r\n\r\n        write: function (pluginName, moduleName, write, config) {\r\n            if (buildMap.hasOwnProperty(moduleName)) {\r\n                var content = text.jsEscape(buildMap[moduleName]);\r\n                write.asModule(pluginName + \"!\" + moduleName,\r\n                               \"define(function () { return '\" +\r\n                                   content +\r\n                               \"';});\\n\");\r\n            }\r\n        },\r\n\r\n        writeFile: function (pluginName, moduleName, req, write, config) {\r\n            var parsed = text.parseName(moduleName),\r\n                extPart = parsed.ext ? '.' + parsed.ext : '',\r\n                nonStripName = parsed.moduleName + extPart,\r\n                //Use a '.js' file name so that it indicates it is a\r\n                //script that can be loaded across domains.\r\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\r\n\r\n            //Leverage own load() method to load plugin value, but only\r\n            //write out values that do not have the strip argument,\r\n            //to avoid any potential issues with ! in file names.\r\n            text.load(nonStripName, req, function (value) {\r\n                //Use own write() method to construct full module value.\r\n                //But need to create shell that translates writeFile's\r\n                //write() to the right interface.\r\n                var textWrite = function (contents) {\r\n                    return write(fileName, contents);\r\n                };\r\n                textWrite.asModule = function (moduleName, contents) {\r\n                    return write.asModule(moduleName, fileName, contents);\r\n                };\r\n\r\n                text.write(pluginName, nonStripName, textWrite, config);\r\n            }, config);\r\n        }\r\n    };\r\n\r\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\r\n            typeof process !== \"undefined\" &&\r\n            process.versions &&\r\n            !!process.versions.node &&\r\n            !process.versions['node-webkit'])) {\r\n        //Using special require.nodeRequire, something added by r.js.\r\n        fs = require.nodeRequire('fs');\r\n\r\n        text.get = function (url, callback, errback) {\r\n            try {\r\n                var file = fs.readFileSync(url, 'utf8');\r\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\r\n                if (file.indexOf('\\uFEFF') === 0) {\r\n                    file = file.substring(1);\r\n                }\r\n                callback(file);\r\n            } catch (e) {\r\n                errback(e);\r\n            }\r\n        };\r\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\r\n            text.createXhr())) {\r\n        text.get = function (url, callback, errback, headers) {\r\n            var xhr = text.createXhr(), header;\r\n            xhr.open('GET', url, true);\r\n\r\n            //Allow plugins direct access to xhr headers\r\n            if (headers) {\r\n                for (header in headers) {\r\n                    if (headers.hasOwnProperty(header)) {\r\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Allow overrides specified in config\r\n            if (masterConfig.onXhr) {\r\n                masterConfig.onXhr(xhr, url);\r\n            }\r\n\r\n            xhr.onreadystatechange = function (evt) {\r\n                var status, err;\r\n                //Do not explicitly handle errors, those should be\r\n                //visible via console output in the browser.\r\n                if (xhr.readyState === 4) {\r\n                    status = xhr.status;\r\n                    if (status > 399 && status < 600) {\r\n                        //An http 4xx or 5xx error. Signal an error.\r\n                        err = new Error(url + ' HTTP status: ' + status);\r\n                        err.xhr = xhr;\r\n                        errback(err);\r\n                    } else {\r\n                        callback(xhr.responseText);\r\n                    }\r\n\r\n                    if (masterConfig.onXhrComplete) {\r\n                        masterConfig.onXhrComplete(xhr, url);\r\n                    }\r\n                }\r\n            };\r\n            xhr.send(null);\r\n        };\r\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\r\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\r\n        //Why Java, why is this so awkward?\r\n        text.get = function (url, callback) {\r\n            var stringBuffer, line,\r\n                encoding = \"utf-8\",\r\n                file = new java.io.File(url),\r\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\r\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\r\n                content = '';\r\n            try {\r\n                stringBuffer = new java.lang.StringBuffer();\r\n                line = input.readLine();\r\n\r\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\r\n                // http://www.unicode.org/faq/utf_bom.html\r\n\r\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\r\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\r\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\r\n                    // Eat the BOM, since we've already found the encoding on this file,\r\n                    // and we plan to concatenating this buffer with others; the BOM should\r\n                    // only appear at the top of a file.\r\n                    line = line.substring(1);\r\n                }\r\n\r\n                if (line !== null) {\r\n                    stringBuffer.append(line);\r\n                }\r\n\r\n                while ((line = input.readLine()) !== null) {\r\n                    stringBuffer.append(lineSeparator);\r\n                    stringBuffer.append(line);\r\n                }\r\n                //Make sure we return a JavaScript string and not a Java string.\r\n                content = String(stringBuffer.toString()); //String\r\n            } finally {\r\n                input.close();\r\n            }\r\n            callback(content);\r\n        };\r\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\r\n            typeof Components !== 'undefined' && Components.classes &&\r\n            Components.interfaces)) {\r\n        //Avert your gaze!\r\n        Cc = Components.classes,\r\n        Ci = Components.interfaces;\r\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\r\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\r\n\r\n        text.get = function (url, callback) {\r\n            var inStream, convertStream, fileObj,\r\n                readData = {};\r\n\r\n            if (xpcIsWindows) {\r\n                url = url.replace(/\\//g, '\\\\');\r\n            }\r\n\r\n            fileObj = new FileUtils.File(url);\r\n\r\n            //XPCOM, you so crazy\r\n            try {\r\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\r\n                           .createInstance(Ci.nsIFileInputStream);\r\n                inStream.init(fileObj, 1, 0, false);\r\n\r\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\r\n                                .createInstance(Ci.nsIConverterInputStream);\r\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\r\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\r\n\r\n                convertStream.readString(inStream.available(), readData);\r\n                convertStream.close();\r\n                inStream.close();\r\n                callback(readData.value);\r\n            } catch (e) {\r\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\r\n            }\r\n        };\r\n    }\r\n    return text;\r\n});\r\n\n",
        +    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\r\\n<form>\\r\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\r\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\r\\n</form>\\r\\n\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\r\\n\\r\\n  <strong><%=name%></strong>\\r\\n\\r\\n  <span class=\"small\">\\r\\n    <% if (final) { %>\\r\\n    constant\\r\\n    <% } else if (itemtype) { %>\\r\\n    <%=itemtype%> \\r\\n    <% } %>\\r\\n\\r\\n    <% if (className) { %>\\r\\n    in <strong><%=className%></strong>\\r\\n    <% } %>\\r\\n\\r\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\r\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\r\\n    <% } %>\\r\\n  </span>\\r\\n\\r\\n</p>';});\n\n",
        +    "/*!\r\n * typeahead.js 0.10.2\r\n * https://github.com/twitter/typeahead.js\r\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\r\n */\r\ndefine('typeahead',[], function() {\r\n\r\n//(function($) {\r\n\r\n\r\n    var _ = {\r\n        isMsie: function() {\r\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\r\n        },\r\n        isBlankString: function(str) {\r\n            return !str || /^\\s*$/.test(str);\r\n        },\r\n        escapeRegExChars: function(str) {\r\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\r\n        },\r\n        isString: function(obj) {\r\n            return typeof obj === \"string\";\r\n        },\r\n        isNumber: function(obj) {\r\n            return typeof obj === \"number\";\r\n        },\r\n        isArray: $.isArray,\r\n        isFunction: $.isFunction,\r\n        isObject: $.isPlainObject,\r\n        isUndefined: function(obj) {\r\n            return typeof obj === \"undefined\";\r\n        },\r\n        bind: $.proxy,\r\n        each: function(collection, cb) {\r\n            $.each(collection, reverseArgs);\r\n            function reverseArgs(index, value) {\r\n                return cb(value, index);\r\n            }\r\n        },\r\n        map: $.map,\r\n        filter: $.grep,\r\n        every: function(obj, test) {\r\n            var result = true;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (!(result = test.call(null, val, key, obj))) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        some: function(obj, test) {\r\n            var result = false;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (result = test.call(null, val, key, obj)) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        mixin: $.extend,\r\n        getUniqueId: function() {\r\n            var counter = 0;\r\n            return function() {\r\n                return counter++;\r\n            };\r\n        }(),\r\n        templatify: function templatify(obj) {\r\n            return $.isFunction(obj) ? obj : template;\r\n            function template() {\r\n                return String(obj);\r\n            }\r\n        },\r\n        defer: function(fn) {\r\n            setTimeout(fn, 0);\r\n        },\r\n        debounce: function(func, wait, immediate) {\r\n            var timeout, result;\r\n            return function() {\r\n                var context = this, args = arguments, later, callNow;\r\n                later = function() {\r\n                    timeout = null;\r\n                    if (!immediate) {\r\n                        result = func.apply(context, args);\r\n                    }\r\n                };\r\n                callNow = immediate && !timeout;\r\n                clearTimeout(timeout);\r\n                timeout = setTimeout(later, wait);\r\n                if (callNow) {\r\n                    result = func.apply(context, args);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        throttle: function(func, wait) {\r\n            var context, args, timeout, result, previous, later;\r\n            previous = 0;\r\n            later = function() {\r\n                previous = new Date();\r\n                timeout = null;\r\n                result = func.apply(context, args);\r\n            };\r\n            return function() {\r\n                var now = new Date(), remaining = wait - (now - previous);\r\n                context = this;\r\n                args = arguments;\r\n                if (remaining <= 0) {\r\n                    clearTimeout(timeout);\r\n                    timeout = null;\r\n                    previous = now;\r\n                    result = func.apply(context, args);\r\n                } else if (!timeout) {\r\n                    timeout = setTimeout(later, remaining);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        noop: function() {}\r\n    };\r\n    var VERSION = \"0.10.2\";\r\n    var tokenizers = function(root) {\r\n        return {\r\n            nonword: nonword,\r\n            whitespace: whitespace,\r\n            obj: {\r\n                nonword: getObjTokenizer(nonword),\r\n                whitespace: getObjTokenizer(whitespace)\r\n            }\r\n        };\r\n        function whitespace(s) {\r\n            return s.split(/\\s+/);\r\n        }\r\n        function nonword(s) {\r\n            return s.split(/\\W+/);\r\n        }\r\n        function getObjTokenizer(tokenizer) {\r\n            return function setKey(key) {\r\n                return function tokenize(o) {\r\n                    return tokenizer(o[key]);\r\n                };\r\n            };\r\n        }\r\n    }();\r\n    var LruCache = function() {\r\n        function LruCache(maxSize) {\r\n            this.maxSize = maxSize || 100;\r\n            this.size = 0;\r\n            this.hash = {};\r\n            this.list = new List();\r\n        }\r\n        _.mixin(LruCache.prototype, {\r\n            set: function set(key, val) {\r\n                var tailItem = this.list.tail, node;\r\n                if (this.size >= this.maxSize) {\r\n                    this.list.remove(tailItem);\r\n                    delete this.hash[tailItem.key];\r\n                }\r\n                if (node = this.hash[key]) {\r\n                    node.val = val;\r\n                    this.list.moveToFront(node);\r\n                } else {\r\n                    node = new Node(key, val);\r\n                    this.list.add(node);\r\n                    this.hash[key] = node;\r\n                    this.size++;\r\n                }\r\n            },\r\n            get: function get(key) {\r\n                var node = this.hash[key];\r\n                if (node) {\r\n                    this.list.moveToFront(node);\r\n                    return node.val;\r\n                }\r\n            }\r\n        });\r\n        function List() {\r\n            this.head = this.tail = null;\r\n        }\r\n        _.mixin(List.prototype, {\r\n            add: function add(node) {\r\n                if (this.head) {\r\n                    node.next = this.head;\r\n                    this.head.prev = node;\r\n                }\r\n                this.head = node;\r\n                this.tail = this.tail || node;\r\n            },\r\n            remove: function remove(node) {\r\n                node.prev ? node.prev.next = node.next : this.head = node.next;\r\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\r\n            },\r\n            moveToFront: function(node) {\r\n                this.remove(node);\r\n                this.add(node);\r\n            }\r\n        });\r\n        function Node(key, val) {\r\n            this.key = key;\r\n            this.val = val;\r\n            this.prev = this.next = null;\r\n        }\r\n        return LruCache;\r\n    }();\r\n    var PersistentStorage = function() {\r\n        var ls, methods;\r\n        try {\r\n            ls = window.localStorage;\r\n            ls.setItem(\"~~~\", \"!\");\r\n            ls.removeItem(\"~~~\");\r\n        } catch (err) {\r\n            ls = null;\r\n        }\r\n        function PersistentStorage(namespace) {\r\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\r\n            this.ttlKey = \"__ttl__\";\r\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\r\n        }\r\n        if (ls && window.JSON) {\r\n            methods = {\r\n                _prefix: function(key) {\r\n                    return this.prefix + key;\r\n                },\r\n                _ttlKey: function(key) {\r\n                    return this._prefix(key) + this.ttlKey;\r\n                },\r\n                get: function(key) {\r\n                    if (this.isExpired(key)) {\r\n                        this.remove(key);\r\n                    }\r\n                    return decode(ls.getItem(this._prefix(key)));\r\n                },\r\n                set: function(key, val, ttl) {\r\n                    if (_.isNumber(ttl)) {\r\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\r\n                    } else {\r\n                        ls.removeItem(this._ttlKey(key));\r\n                    }\r\n                    return ls.setItem(this._prefix(key), encode(val));\r\n                },\r\n                remove: function(key) {\r\n                    ls.removeItem(this._ttlKey(key));\r\n                    ls.removeItem(this._prefix(key));\r\n                    return this;\r\n                },\r\n                clear: function() {\r\n                    var i, key, keys = [], len = ls.length;\r\n                    for (i = 0; i < len; i++) {\r\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\r\n                            keys.push(key.replace(this.keyMatcher, \"\"));\r\n                        }\r\n                    }\r\n                    for (i = keys.length; i--; ) {\r\n                        this.remove(keys[i]);\r\n                    }\r\n                    return this;\r\n                },\r\n                isExpired: function(key) {\r\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\r\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\r\n                }\r\n            };\r\n        } else {\r\n            methods = {\r\n                get: _.noop,\r\n                set: _.noop,\r\n                remove: _.noop,\r\n                clear: _.noop,\r\n                isExpired: _.noop\r\n            };\r\n        }\r\n        _.mixin(PersistentStorage.prototype, methods);\r\n        return PersistentStorage;\r\n        function now() {\r\n            return new Date().getTime();\r\n        }\r\n        function encode(val) {\r\n            return JSON.stringify(_.isUndefined(val) ? null : val);\r\n        }\r\n        function decode(val) {\r\n            return JSON.parse(val);\r\n        }\r\n    }();\r\n    var Transport = function() {\r\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\r\n        function Transport(o) {\r\n            o = o || {};\r\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\r\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\r\n        }\r\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\r\n            maxPendingRequests = num;\r\n        };\r\n        Transport.resetCache = function clearCache() {\r\n            requestCache = new LruCache(10);\r\n        };\r\n        _.mixin(Transport.prototype, {\r\n            _get: function(url, o, cb) {\r\n                var that = this, jqXhr;\r\n                if (jqXhr = pendingRequests[url]) {\r\n                    jqXhr.done(done).fail(fail);\r\n                } else if (pendingRequestsCount < maxPendingRequests) {\r\n                    pendingRequestsCount++;\r\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\r\n                } else {\r\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\r\n                }\r\n                function done(resp) {\r\n                    cb && cb(null, resp);\r\n                    requestCache.set(url, resp);\r\n                }\r\n                function fail() {\r\n                    cb && cb(true);\r\n                }\r\n                function always() {\r\n                    pendingRequestsCount--;\r\n                    delete pendingRequests[url];\r\n                    if (that.onDeckRequestArgs) {\r\n                        that._get.apply(that, that.onDeckRequestArgs);\r\n                        that.onDeckRequestArgs = null;\r\n                    }\r\n                }\r\n            },\r\n            get: function(url, o, cb) {\r\n                var resp;\r\n                if (_.isFunction(o)) {\r\n                    cb = o;\r\n                    o = {};\r\n                }\r\n                if (resp = requestCache.get(url)) {\r\n                    _.defer(function() {\r\n                        cb && cb(null, resp);\r\n                    });\r\n                } else {\r\n                    this._get(url, o, cb);\r\n                }\r\n                return !!resp;\r\n            }\r\n        });\r\n        return Transport;\r\n        function callbackToDeferred(fn) {\r\n            return function customSendWrapper(url, o) {\r\n                var deferred = $.Deferred();\r\n                fn(url, o, onSuccess, onError);\r\n                return deferred;\r\n                function onSuccess(resp) {\r\n                    _.defer(function() {\r\n                        deferred.resolve(resp);\r\n                    });\r\n                }\r\n                function onError(err) {\r\n                    _.defer(function() {\r\n                        deferred.reject(err);\r\n                    });\r\n                }\r\n            };\r\n        }\r\n    }();\r\n    var SearchIndex = function() {\r\n        function SearchIndex(o) {\r\n            o = o || {};\r\n            if (!o.datumTokenizer || !o.queryTokenizer) {\r\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\r\n            }\r\n            this.datumTokenizer = o.datumTokenizer;\r\n            this.queryTokenizer = o.queryTokenizer;\r\n            this.reset();\r\n        }\r\n        _.mixin(SearchIndex.prototype, {\r\n            bootstrap: function bootstrap(o) {\r\n                this.datums = o.datums;\r\n                this.trie = o.trie;\r\n            },\r\n            add: function(data) {\r\n                var that = this;\r\n                data = _.isArray(data) ? data : [ data ];\r\n                _.each(data, function(datum) {\r\n                    var id, tokens;\r\n                    id = that.datums.push(datum) - 1;\r\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\r\n                    _.each(tokens, function(token) {\r\n                        var node, chars, ch;\r\n                        node = that.trie;\r\n                        chars = token.split(\"\");\r\n                        while (ch = chars.shift()) {\r\n                            node = node.children[ch] || (node.children[ch] = newNode());\r\n                            node.ids.push(id);\r\n                        }\r\n                    });\r\n                });\r\n            },\r\n            get: function get(query) {\r\n                var that = this, tokens, matches;\r\n                tokens = normalizeTokens(this.queryTokenizer(query));\r\n                _.each(tokens, function(token) {\r\n                    var node, chars, ch, ids;\r\n                    if (matches && matches.length === 0) {\r\n                        return false;\r\n                    }\r\n                    node = that.trie;\r\n                    chars = token.split(\"\");\r\n                    while (node && (ch = chars.shift())) {\r\n                        node = node.children[ch];\r\n                    }\r\n                    if (node && chars.length === 0) {\r\n                        ids = node.ids.slice(0);\r\n                        matches = matches ? getIntersection(matches, ids) : ids;\r\n                    } else {\r\n                        matches = [];\r\n                        return false;\r\n                    }\r\n                });\r\n                return matches ? _.map(unique(matches), function(id) {\r\n                    return that.datums[id];\r\n                }) : [];\r\n            },\r\n            reset: function reset() {\r\n                this.datums = [];\r\n                this.trie = newNode();\r\n            },\r\n            serialize: function serialize() {\r\n                return {\r\n                    datums: this.datums,\r\n                    trie: this.trie\r\n                };\r\n            }\r\n        });\r\n        return SearchIndex;\r\n        function normalizeTokens(tokens) {\r\n            tokens = _.filter(tokens, function(token) {\r\n                return !!token;\r\n            });\r\n            tokens = _.map(tokens, function(token) {\r\n                return token.toLowerCase();\r\n            });\r\n            return tokens;\r\n        }\r\n        function newNode() {\r\n            return {\r\n                ids: [],\r\n                children: {}\r\n            };\r\n        }\r\n        function unique(array) {\r\n            var seen = {}, uniques = [];\r\n            for (var i = 0; i < array.length; i++) {\r\n                if (!seen[array[i]]) {\r\n                    seen[array[i]] = true;\r\n                    uniques.push(array[i]);\r\n                }\r\n            }\r\n            return uniques;\r\n        }\r\n        function getIntersection(arrayA, arrayB) {\r\n            var ai = 0, bi = 0, intersection = [];\r\n            arrayA = arrayA.sort(compare);\r\n            arrayB = arrayB.sort(compare);\r\n            while (ai < arrayA.length && bi < arrayB.length) {\r\n                if (arrayA[ai] < arrayB[bi]) {\r\n                    ai++;\r\n                } else if (arrayA[ai] > arrayB[bi]) {\r\n                    bi++;\r\n                } else {\r\n                    intersection.push(arrayA[ai]);\r\n                    ai++;\r\n                    bi++;\r\n                }\r\n            }\r\n            return intersection;\r\n            function compare(a, b) {\r\n                return a - b;\r\n            }\r\n        }\r\n    }();\r\n    var oParser = function() {\r\n        return {\r\n            local: getLocal,\r\n            prefetch: getPrefetch,\r\n            remote: getRemote\r\n        };\r\n        function getLocal(o) {\r\n            return o.local || null;\r\n        }\r\n        function getPrefetch(o) {\r\n            var prefetch, defaults;\r\n            defaults = {\r\n                url: null,\r\n                thumbprint: \"\",\r\n                ttl: 24 * 60 * 60 * 1e3,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (prefetch = o.prefetch || null) {\r\n                prefetch = _.isString(prefetch) ? {\r\n                    url: prefetch\r\n                } : prefetch;\r\n                prefetch = _.mixin(defaults, prefetch);\r\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\r\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\r\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\r\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\r\n            }\r\n            return prefetch;\r\n        }\r\n        function getRemote(o) {\r\n            var remote, defaults;\r\n            defaults = {\r\n                url: null,\r\n                wildcard: \"%QUERY\",\r\n                replace: null,\r\n                rateLimitBy: \"debounce\",\r\n                rateLimitWait: 300,\r\n                send: null,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (remote = o.remote || null) {\r\n                remote = _.isString(remote) ? {\r\n                    url: remote\r\n                } : remote;\r\n                remote = _.mixin(defaults, remote);\r\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\r\n                remote.ajax.type = remote.ajax.type || \"GET\";\r\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\r\n                delete remote.rateLimitBy;\r\n                delete remote.rateLimitWait;\r\n                !remote.url && $.error(\"remote requires url to be set\");\r\n            }\r\n            return remote;\r\n            function byDebounce(wait) {\r\n                return function(fn) {\r\n                    return _.debounce(fn, wait);\r\n                };\r\n            }\r\n            function byThrottle(wait) {\r\n                return function(fn) {\r\n                    return _.throttle(fn, wait);\r\n                };\r\n            }\r\n        }\r\n    }();\r\n    (function(root) {\r\n        var old, keys;\r\n        old = root.Bloodhound;\r\n        keys = {\r\n            data: \"data\",\r\n            protocol: \"protocol\",\r\n            thumbprint: \"thumbprint\"\r\n        };\r\n        root.Bloodhound = Bloodhound;\r\n        function Bloodhound(o) {\r\n            if (!o || !o.local && !o.prefetch && !o.remote) {\r\n                $.error(\"one of local, prefetch, or remote is required\");\r\n            }\r\n            this.limit = o.limit || 5;\r\n            this.sorter = getSorter(o.sorter);\r\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\r\n            this.local = oParser.local(o);\r\n            this.prefetch = oParser.prefetch(o);\r\n            this.remote = oParser.remote(o);\r\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\r\n            this.index = new SearchIndex({\r\n                datumTokenizer: o.datumTokenizer,\r\n                queryTokenizer: o.queryTokenizer\r\n            });\r\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\r\n        }\r\n        Bloodhound.noConflict = function noConflict() {\r\n            root.Bloodhound = old;\r\n            return Bloodhound;\r\n        };\r\n        Bloodhound.tokenizers = tokenizers;\r\n        _.mixin(Bloodhound.prototype, {\r\n            _loadPrefetch: function loadPrefetch(o) {\r\n                var that = this, serialized, deferred;\r\n                if (serialized = this._readFromStorage(o.thumbprint)) {\r\n                    this.index.bootstrap(serialized);\r\n                    deferred = $.Deferred().resolve();\r\n                } else {\r\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\r\n                }\r\n                return deferred;\r\n                function handlePrefetchResponse(resp) {\r\n                    that.clear();\r\n                    that.add(o.filter ? o.filter(resp) : resp);\r\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\r\n                }\r\n            },\r\n            _getFromRemote: function getFromRemote(query, cb) {\r\n                var that = this, url, uriEncodedQuery;\r\n                query = query || \"\";\r\n                uriEncodedQuery = encodeURIComponent(query);\r\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\r\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\r\n                function handleRemoteResponse(err, resp) {\r\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\r\n                }\r\n            },\r\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\r\n                if (this.storage) {\r\n                    this.storage.set(keys.data, data, ttl);\r\n                    this.storage.set(keys.protocol, location.protocol, ttl);\r\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\r\n                }\r\n            },\r\n            _readFromStorage: function readFromStorage(thumbprint) {\r\n                var stored = {}, isExpired;\r\n                if (this.storage) {\r\n                    stored.data = this.storage.get(keys.data);\r\n                    stored.protocol = this.storage.get(keys.protocol);\r\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\r\n                }\r\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\r\n                return stored.data && !isExpired ? stored.data : null;\r\n            },\r\n            _initialize: function initialize() {\r\n                var that = this, local = this.local, deferred;\r\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\r\n                local && deferred.done(addLocalToIndex);\r\n                this.transport = this.remote ? new Transport(this.remote) : null;\r\n                return this.initPromise = deferred.promise();\r\n                function addLocalToIndex() {\r\n                    that.add(_.isFunction(local) ? local() : local);\r\n                }\r\n            },\r\n            initialize: function initialize(force) {\r\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\r\n            },\r\n            add: function add(data) {\r\n                this.index.add(data);\r\n            },\r\n            get: function get(query, cb) {\r\n                var that = this, matches = [], cacheHit = false;\r\n                matches = this.index.get(query);\r\n                matches = this.sorter(matches).slice(0, this.limit);\r\n                if (matches.length < this.limit && this.transport) {\r\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\r\n                }\r\n                if (!cacheHit) {\r\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\r\n                }\r\n                function returnRemoteMatches(remoteMatches) {\r\n                    var matchesWithBackfill = matches.slice(0);\r\n                    _.each(remoteMatches, function(remoteMatch) {\r\n                        var isDuplicate;\r\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\r\n                            return that.dupDetector(remoteMatch, match);\r\n                        });\r\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\r\n                        return matchesWithBackfill.length < that.limit;\r\n                    });\r\n                    cb && cb(that.sorter(matchesWithBackfill));\r\n                }\r\n            },\r\n            clear: function clear() {\r\n                this.index.reset();\r\n            },\r\n            clearPrefetchCache: function clearPrefetchCache() {\r\n                this.storage && this.storage.clear();\r\n            },\r\n            clearRemoteCache: function clearRemoteCache() {\r\n                this.transport && Transport.resetCache();\r\n            },\r\n            ttAdapter: function ttAdapter() {\r\n                return _.bind(this.get, this);\r\n            }\r\n        });\r\n        return Bloodhound;\r\n        function getSorter(sortFn) {\r\n            return _.isFunction(sortFn) ? sort : noSort;\r\n            function sort(array) {\r\n                return array.sort(sortFn);\r\n            }\r\n            function noSort(array) {\r\n                return array;\r\n            }\r\n        }\r\n        function ignoreDuplicates() {\r\n            return false;\r\n        }\r\n    })(this);\r\n    var html = {\r\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\r\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\r\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\r\n        suggestions: '<span class=\"tt-suggestions\"></span>',\r\n        suggestion: '<div class=\"tt-suggestion\"></div>'\r\n    };\r\n    var css = {\r\n        wrapper: {\r\n            position: \"relative\",\r\n            display: \"inline-block\"\r\n        },\r\n        hint: {\r\n            position: \"absolute\",\r\n            top: \"0\",\r\n            left: \"0\",\r\n            borderColor: \"transparent\",\r\n            boxShadow: \"none\"\r\n        },\r\n        input: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\",\r\n            backgroundColor: \"transparent\"\r\n        },\r\n        inputWithNoHint: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\"\r\n        },\r\n        dropdown: {\r\n            position: \"absolute\",\r\n            top: \"100%\",\r\n            left: \"0\",\r\n            zIndex: \"100\",\r\n            display: \"none\"\r\n        },\r\n        suggestions: {\r\n            display: \"block\"\r\n        },\r\n        suggestion: {\r\n            whiteSpace: \"nowrap\",\r\n            cursor: \"pointer\"\r\n        },\r\n        suggestionChild: {\r\n            whiteSpace: \"normal\"\r\n        },\r\n        ltr: {\r\n            left: \"0\",\r\n            right: \"auto\"\r\n        },\r\n        rtl: {\r\n            left: \"auto\",\r\n            right: \" 0\"\r\n        }\r\n    };\r\n    if (_.isMsie()) {\r\n        _.mixin(css.input, {\r\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\r\n        });\r\n    }\r\n    if (_.isMsie() && _.isMsie() <= 7) {\r\n        _.mixin(css.input, {\r\n            marginTop: \"-1px\"\r\n        });\r\n    }\r\n    var EventBus = function() {\r\n        var namespace = \"typeahead:\";\r\n        function EventBus(o) {\r\n            if (!o || !o.el) {\r\n                $.error(\"EventBus initialized without el\");\r\n            }\r\n            this.$el = $(o.el);\r\n        }\r\n        _.mixin(EventBus.prototype, {\r\n            trigger: function(type) {\r\n                var args = [].slice.call(arguments, 1);\r\n                this.$el.trigger(namespace + type, args);\r\n            }\r\n        });\r\n        return EventBus;\r\n    }();\r\n    var EventEmitter = function() {\r\n        var splitter = /\\s+/, nextTick = getNextTick();\r\n        return {\r\n            onSync: onSync,\r\n            onAsync: onAsync,\r\n            off: off,\r\n            trigger: trigger\r\n        };\r\n        function on(method, types, cb, context) {\r\n            var type;\r\n            if (!cb) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            cb = context ? bindContext(cb, context) : cb;\r\n            this._callbacks = this._callbacks || {};\r\n            while (type = types.shift()) {\r\n                this._callbacks[type] = this._callbacks[type] || {\r\n                    sync: [],\r\n                    async: []\r\n                };\r\n                this._callbacks[type][method].push(cb);\r\n            }\r\n            return this;\r\n        }\r\n        function onAsync(types, cb, context) {\r\n            return on.call(this, \"async\", types, cb, context);\r\n        }\r\n        function onSync(types, cb, context) {\r\n            return on.call(this, \"sync\", types, cb, context);\r\n        }\r\n        function off(types) {\r\n            var type;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            while (type = types.shift()) {\r\n                delete this._callbacks[type];\r\n            }\r\n            return this;\r\n        }\r\n        function trigger(types) {\r\n            var type, callbacks, args, syncFlush, asyncFlush;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            args = [].slice.call(arguments, 1);\r\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\r\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\r\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\r\n                syncFlush() && nextTick(asyncFlush);\r\n            }\r\n            return this;\r\n        }\r\n        function getFlush(callbacks, context, args) {\r\n            return flush;\r\n            function flush() {\r\n                var cancelled;\r\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\r\n                    cancelled = callbacks[i].apply(context, args) === false;\r\n                }\r\n                return !cancelled;\r\n            }\r\n        }\r\n        function getNextTick() {\r\n            var nextTickFn;\r\n            if (window.setImmediate) {\r\n                nextTickFn = function nextTickSetImmediate(fn) {\r\n                    setImmediate(function() {\r\n                        fn();\r\n                    });\r\n                };\r\n            } else {\r\n                nextTickFn = function nextTickSetTimeout(fn) {\r\n                    setTimeout(function() {\r\n                        fn();\r\n                    }, 0);\r\n                };\r\n            }\r\n            return nextTickFn;\r\n        }\r\n        function bindContext(fn, context) {\r\n            return fn.bind ? fn.bind(context) : function() {\r\n                fn.apply(context, [].slice.call(arguments, 0));\r\n            };\r\n        }\r\n    }();\r\n    var highlight = function(doc) {\r\n        var defaults = {\r\n            node: null,\r\n            pattern: null,\r\n            tagName: \"strong\",\r\n            className: null,\r\n            wordsOnly: false,\r\n            caseSensitive: false\r\n        };\r\n        return function hightlight(o) {\r\n            var regex;\r\n            o = _.mixin({}, defaults, o);\r\n            if (!o.node || !o.pattern) {\r\n                return;\r\n            }\r\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\r\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\r\n            traverse(o.node, hightlightTextNode);\r\n            function hightlightTextNode(textNode) {\r\n                var match, patternNode;\r\n                if (match = regex.exec(textNode.data)) {\r\n                    wrapperNode = doc.createElement(o.tagName);\r\n                    o.className && (wrapperNode.className = o.className);\r\n                    patternNode = textNode.splitText(match.index);\r\n                    patternNode.splitText(match[0].length);\r\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\r\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\r\n                }\r\n                return !!match;\r\n            }\r\n            function traverse(el, hightlightTextNode) {\r\n                var childNode, TEXT_NODE_TYPE = 3;\r\n                for (var i = 0; i < el.childNodes.length; i++) {\r\n                    childNode = el.childNodes[i];\r\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\r\n                        i += hightlightTextNode(childNode) ? 1 : 0;\r\n                    } else {\r\n                        traverse(childNode, hightlightTextNode);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        function getRegex(patterns, caseSensitive, wordsOnly) {\r\n            var escapedPatterns = [], regexStr;\r\n            for (var i = 0; i < patterns.length; i++) {\r\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\r\n            }\r\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\r\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\r\n        }\r\n    }(window.document);\r\n    var Input = function() {\r\n        var specialKeyCodeMap;\r\n        specialKeyCodeMap = {\r\n            9: \"tab\",\r\n            27: \"esc\",\r\n            37: \"left\",\r\n            39: \"right\",\r\n            13: \"enter\",\r\n            38: \"up\",\r\n            40: \"down\"\r\n        };\r\n        function Input(o) {\r\n            var that = this, onBlur, onFocus, onKeydown, onInput;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"input is missing\");\r\n            }\r\n            onBlur = _.bind(this._onBlur, this);\r\n            onFocus = _.bind(this._onFocus, this);\r\n            onKeydown = _.bind(this._onKeydown, this);\r\n            onInput = _.bind(this._onInput, this);\r\n            this.$hint = $(o.hint);\r\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\r\n            if (this.$hint.length === 0) {\r\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\r\n            }\r\n            if (!_.isMsie()) {\r\n                this.$input.on(\"input.tt\", onInput);\r\n            } else {\r\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\r\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\r\n                        return;\r\n                    }\r\n                    _.defer(_.bind(that._onInput, that, $e));\r\n                });\r\n            }\r\n            this.query = this.$input.val();\r\n            this.$overflowHelper = buildOverflowHelper(this.$input);\r\n        }\r\n        Input.normalizeQuery = function(str) {\r\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\r\n        };\r\n        _.mixin(Input.prototype, EventEmitter, {\r\n            _onBlur: function onBlur() {\r\n                this.resetInputValue();\r\n                this.trigger(\"blurred\");\r\n            },\r\n            _onFocus: function onFocus() {\r\n                this.trigger(\"focused\");\r\n            },\r\n            _onKeydown: function onKeydown($e) {\r\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\r\n                this._managePreventDefault(keyName, $e);\r\n                if (keyName && this._shouldTrigger(keyName, $e)) {\r\n                    this.trigger(keyName + \"Keyed\", $e);\r\n                }\r\n            },\r\n            _onInput: function onInput() {\r\n                this._checkInputValue();\r\n            },\r\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\r\n                var preventDefault, hintValue, inputValue;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    hintValue = this.getHint();\r\n                    inputValue = this.getInputValue();\r\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\r\n                    break;\r\n\r\n                  case \"up\":\r\n                  case \"down\":\r\n                    preventDefault = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    preventDefault = false;\r\n                }\r\n                preventDefault && $e.preventDefault();\r\n            },\r\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\r\n                var trigger;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    trigger = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    trigger = true;\r\n                }\r\n                return trigger;\r\n            },\r\n            _checkInputValue: function checkInputValue() {\r\n                var inputValue, areEquivalent, hasDifferentWhitespace;\r\n                inputValue = this.getInputValue();\r\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\r\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\r\n                if (!areEquivalent) {\r\n                    this.trigger(\"queryChanged\", this.query = inputValue);\r\n                } else if (hasDifferentWhitespace) {\r\n                    this.trigger(\"whitespaceChanged\", this.query);\r\n                }\r\n            },\r\n            focus: function focus() {\r\n                this.$input.focus();\r\n            },\r\n            blur: function blur() {\r\n                this.$input.blur();\r\n            },\r\n            getQuery: function getQuery() {\r\n                return this.query;\r\n            },\r\n            setQuery: function setQuery(query) {\r\n                this.query = query;\r\n            },\r\n            getInputValue: function getInputValue() {\r\n                return this.$input.val();\r\n            },\r\n            setInputValue: function setInputValue(value, silent) {\r\n                this.$input.val(value);\r\n                silent ? this.clearHint() : this._checkInputValue();\r\n            },\r\n            resetInputValue: function resetInputValue() {\r\n                this.setInputValue(this.query, true);\r\n            },\r\n            getHint: function getHint() {\r\n                return this.$hint.val();\r\n            },\r\n            setHint: function setHint(value) {\r\n                this.$hint.val(value);\r\n            },\r\n            clearHint: function clearHint() {\r\n                this.setHint(\"\");\r\n            },\r\n            clearHintIfInvalid: function clearHintIfInvalid() {\r\n                var val, hint, valIsPrefixOfHint, isValid;\r\n                val = this.getInputValue();\r\n                hint = this.getHint();\r\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\r\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\r\n                !isValid && this.clearHint();\r\n            },\r\n            getLanguageDirection: function getLanguageDirection() {\r\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\r\n            },\r\n            hasOverflow: function hasOverflow() {\r\n                var constraint = this.$input.width() - 2;\r\n                this.$overflowHelper.text(this.getInputValue());\r\n                return this.$overflowHelper.width() >= constraint;\r\n            },\r\n            isCursorAtEnd: function() {\r\n                var valueLength, selectionStart, range;\r\n                valueLength = this.$input.val().length;\r\n                selectionStart = this.$input[0].selectionStart;\r\n                if (_.isNumber(selectionStart)) {\r\n                    return selectionStart === valueLength;\r\n                } else if (document.selection) {\r\n                    range = document.selection.createRange();\r\n                    range.moveStart(\"character\", -valueLength);\r\n                    return valueLength === range.text.length;\r\n                }\r\n                return true;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$hint.off(\".tt\");\r\n                this.$input.off(\".tt\");\r\n                this.$hint = this.$input = this.$overflowHelper = null;\r\n            }\r\n        });\r\n        return Input;\r\n        function buildOverflowHelper($input) {\r\n            return $('<pre aria-hidden=\"true\"></pre>').css({\r\n                position: \"absolute\",\r\n                visibility: \"hidden\",\r\n                whiteSpace: \"pre\",\r\n                fontFamily: $input.css(\"font-family\"),\r\n                fontSize: $input.css(\"font-size\"),\r\n                fontStyle: $input.css(\"font-style\"),\r\n                fontVariant: $input.css(\"font-variant\"),\r\n                fontWeight: $input.css(\"font-weight\"),\r\n                wordSpacing: $input.css(\"word-spacing\"),\r\n                letterSpacing: $input.css(\"letter-spacing\"),\r\n                textIndent: $input.css(\"text-indent\"),\r\n                textRendering: $input.css(\"text-rendering\"),\r\n                textTransform: $input.css(\"text-transform\")\r\n            }).insertAfter($input);\r\n        }\r\n        function areQueriesEquivalent(a, b) {\r\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\r\n        }\r\n        function withModifier($e) {\r\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\r\n        }\r\n    }();\r\n    var Dataset = function() {\r\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\r\n        function Dataset(o) {\r\n            o = o || {};\r\n            o.templates = o.templates || {};\r\n            if (!o.source) {\r\n                $.error(\"missing source\");\r\n            }\r\n            if (o.name && !isValidName(o.name)) {\r\n                $.error(\"invalid dataset name: \" + o.name);\r\n            }\r\n            this.query = null;\r\n            this.highlight = !!o.highlight;\r\n            this.name = o.name || _.getUniqueId();\r\n            this.source = o.source;\r\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\r\n            this.templates = getTemplates(o.templates, this.displayFn);\r\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\r\n        }\r\n        Dataset.extractDatasetName = function extractDatasetName(el) {\r\n            return $(el).data(datasetKey);\r\n        };\r\n        Dataset.extractValue = function extractDatum(el) {\r\n            return $(el).data(valueKey);\r\n        };\r\n        Dataset.extractDatum = function extractDatum(el) {\r\n            return $(el).data(datumKey);\r\n        };\r\n        _.mixin(Dataset.prototype, EventEmitter, {\r\n            _render: function render(query, suggestions) {\r\n                if (!this.$el) {\r\n                    return;\r\n                }\r\n                var that = this, hasSuggestions;\r\n                this.$el.empty();\r\n                hasSuggestions = suggestions && suggestions.length;\r\n                if (!hasSuggestions && this.templates.empty) {\r\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                } else if (hasSuggestions) {\r\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                }\r\n                this.trigger(\"rendered\");\r\n                function getEmptyHtml() {\r\n                    return that.templates.empty({\r\n                        query: query,\r\n                        isEmpty: true\r\n                    });\r\n                }\r\n                function getSuggestionsHtml() {\r\n                    var $suggestions, nodes;\r\n                    $suggestions = $(html.suggestions).css(css.suggestions);\r\n                    nodes = _.map(suggestions, getSuggestionNode);\r\n                    $suggestions.append.apply($suggestions, nodes);\r\n                    that.highlight && highlight({\r\n                        node: $suggestions[0],\r\n                        pattern: query\r\n                    });\r\n                    return $suggestions;\r\n                    function getSuggestionNode(suggestion) {\r\n                        var $el;\r\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\r\n                        $el.children().each(function() {\r\n                            $(this).css(css.suggestionChild);\r\n                        });\r\n                        return $el;\r\n                    }\r\n                }\r\n                function getHeaderHtml() {\r\n                    return that.templates.header({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n                function getFooterHtml() {\r\n                    return that.templates.footer({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n            },\r\n            getRoot: function getRoot() {\r\n                return this.$el;\r\n            },\r\n            update: function update(query) {\r\n                var that = this;\r\n                this.query = query;\r\n                this.canceled = false;\r\n                this.source(query, render);\r\n                function render(suggestions) {\r\n                    if (!that.canceled && query === that.query) {\r\n                        that._render(query, suggestions);\r\n                    }\r\n                }\r\n            },\r\n            cancel: function cancel() {\r\n                this.canceled = true;\r\n            },\r\n            clear: function clear() {\r\n                this.cancel();\r\n                this.$el.empty();\r\n                this.trigger(\"rendered\");\r\n            },\r\n            isEmpty: function isEmpty() {\r\n                return this.$el.is(\":empty\");\r\n            },\r\n            destroy: function destroy() {\r\n                this.$el = null;\r\n            }\r\n        });\r\n        return Dataset;\r\n        function getDisplayFn(display) {\r\n            display = display || \"value\";\r\n            return _.isFunction(display) ? display : displayFn;\r\n            function displayFn(obj) {\r\n                return obj[display];\r\n            }\r\n        }\r\n        function getTemplates(templates, displayFn) {\r\n            return {\r\n                empty: templates.empty && _.templatify(templates.empty),\r\n                header: templates.header && _.templatify(templates.header),\r\n                footer: templates.footer && _.templatify(templates.footer),\r\n                suggestion: templates.suggestion || suggestionTemplate\r\n            };\r\n            function suggestionTemplate(context) {\r\n                return \"<p>\" + displayFn(context) + \"</p>\";\r\n            }\r\n        }\r\n        function isValidName(str) {\r\n            return /^[_a-zA-Z0-9-]+$/.test(str);\r\n        }\r\n    }();\r\n    var Dropdown = function() {\r\n        function Dropdown(o) {\r\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\r\n            o = o || {};\r\n            if (!o.menu) {\r\n                $.error(\"menu is required\");\r\n            }\r\n            this.isOpen = false;\r\n            this.isEmpty = true;\r\n            this.datasets = _.map(o.datasets, initializeDataset);\r\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\r\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\r\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\r\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\r\n            _.each(this.datasets, function(dataset) {\r\n                that.$menu.append(dataset.getRoot());\r\n                dataset.onSync(\"rendered\", that._onRendered, that);\r\n            });\r\n        }\r\n        _.mixin(Dropdown.prototype, EventEmitter, {\r\n            _onSuggestionClick: function onSuggestionClick($e) {\r\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\r\n            },\r\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\r\n                this._removeCursor();\r\n                this._setCursor($($e.currentTarget), true);\r\n            },\r\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\r\n                this._removeCursor();\r\n            },\r\n            _onRendered: function onRendered() {\r\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\r\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\r\n                this.trigger(\"datasetRendered\");\r\n                function isDatasetEmpty(dataset) {\r\n                    return dataset.isEmpty();\r\n                }\r\n            },\r\n            _hide: function() {\r\n                this.$menu.hide();\r\n            },\r\n            _show: function() {\r\n                this.$menu.css(\"display\", \"block\");\r\n            },\r\n            _getSuggestions: function getSuggestions() {\r\n                return this.$menu.find(\".tt-suggestion\");\r\n            },\r\n            _getCursor: function getCursor() {\r\n                return this.$menu.find(\".tt-cursor\").first();\r\n            },\r\n            _setCursor: function setCursor($el, silent) {\r\n                $el.first().addClass(\"tt-cursor\");\r\n                !silent && this.trigger(\"cursorMoved\");\r\n            },\r\n            _removeCursor: function removeCursor() {\r\n                this._getCursor().removeClass(\"tt-cursor\");\r\n            },\r\n            _moveCursor: function moveCursor(increment) {\r\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\r\n                if (!this.isOpen) {\r\n                    return;\r\n                }\r\n                $oldCursor = this._getCursor();\r\n                $suggestions = this._getSuggestions();\r\n                this._removeCursor();\r\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\r\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\r\n                if (newCursorIndex === -1) {\r\n                    this.trigger(\"cursorRemoved\");\r\n                    return;\r\n                } else if (newCursorIndex < -1) {\r\n                    newCursorIndex = $suggestions.length - 1;\r\n                }\r\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\r\n                this._ensureVisible($newCursor);\r\n            },\r\n            _ensureVisible: function ensureVisible($el) {\r\n                var elTop, elBottom, menuScrollTop, menuHeight;\r\n                elTop = $el.position().top;\r\n                elBottom = elTop + $el.outerHeight(true);\r\n                menuScrollTop = this.$menu.scrollTop();\r\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\r\n                if (elTop < 0) {\r\n                    this.$menu.scrollTop(menuScrollTop + elTop);\r\n                } else if (menuHeight < elBottom) {\r\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\r\n                }\r\n            },\r\n            close: function close() {\r\n                if (this.isOpen) {\r\n                    this.isOpen = false;\r\n                    this._removeCursor();\r\n                    this._hide();\r\n                    this.trigger(\"closed\");\r\n                }\r\n            },\r\n            open: function open() {\r\n                if (!this.isOpen) {\r\n                    this.isOpen = true;\r\n                    !this.isEmpty && this._show();\r\n                    this.trigger(\"opened\");\r\n                }\r\n            },\r\n            setLanguageDirection: function setLanguageDirection(dir) {\r\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\r\n            },\r\n            moveCursorUp: function moveCursorUp() {\r\n                this._moveCursor(-1);\r\n            },\r\n            moveCursorDown: function moveCursorDown() {\r\n                this._moveCursor(+1);\r\n            },\r\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\r\n                var datum = null;\r\n                if ($el.length) {\r\n                    datum = {\r\n                        raw: Dataset.extractDatum($el),\r\n                        value: Dataset.extractValue($el),\r\n                        datasetName: Dataset.extractDatasetName($el)\r\n                    };\r\n                }\r\n                return datum;\r\n            },\r\n            getDatumForCursor: function getDatumForCursor() {\r\n                return this.getDatumForSuggestion(this._getCursor().first());\r\n            },\r\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\r\n                return this.getDatumForSuggestion(this._getSuggestions().first());\r\n            },\r\n            update: function update(query) {\r\n                _.each(this.datasets, updateDataset);\r\n                function updateDataset(dataset) {\r\n                    dataset.update(query);\r\n                }\r\n            },\r\n            empty: function empty() {\r\n                _.each(this.datasets, clearDataset);\r\n                this.isEmpty = true;\r\n                function clearDataset(dataset) {\r\n                    dataset.clear();\r\n                }\r\n            },\r\n            isVisible: function isVisible() {\r\n                return this.isOpen && !this.isEmpty;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$menu.off(\".tt\");\r\n                this.$menu = null;\r\n                _.each(this.datasets, destroyDataset);\r\n                function destroyDataset(dataset) {\r\n                    dataset.destroy();\r\n                }\r\n            }\r\n        });\r\n        return Dropdown;\r\n        function initializeDataset(oDataset) {\r\n            return new Dataset(oDataset);\r\n        }\r\n    }();\r\n    var Typeahead = function() {\r\n        var attrsKey = \"ttAttrs\";\r\n        function Typeahead(o) {\r\n            var $menu, $input, $hint;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"missing input\");\r\n            }\r\n            this.isActivated = false;\r\n            this.autoselect = !!o.autoselect;\r\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\r\n            this.$node = buildDomStructure(o.input, o.withHint);\r\n            $menu = this.$node.find(\".tt-dropdown-menu\");\r\n            $input = this.$node.find(\".tt-input\");\r\n            $hint = this.$node.find(\".tt-hint\");\r\n            $input.on(\"blur.tt\", function($e) {\r\n                var active, isActive, hasActive;\r\n                active = document.activeElement;\r\n                isActive = $menu.is(active);\r\n                hasActive = $menu.has(active).length > 0;\r\n                if (_.isMsie() && (isActive || hasActive)) {\r\n                    $e.preventDefault();\r\n                    $e.stopImmediatePropagation();\r\n                    _.defer(function() {\r\n                        $input.focus();\r\n                    });\r\n                }\r\n            });\r\n            $menu.on(\"mousedown.tt\", function($e) {\r\n                $e.preventDefault();\r\n            });\r\n            this.eventBus = o.eventBus || new EventBus({\r\n                el: $input\r\n            });\r\n            this.dropdown = new Dropdown({\r\n                menu: $menu,\r\n                datasets: o.datasets\r\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\r\n            this.input = new Input({\r\n                input: $input,\r\n                hint: $hint\r\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\r\n            this._setLanguageDirection();\r\n        }\r\n        _.mixin(Typeahead.prototype, {\r\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\r\n                    this._select(datum);\r\n                }\r\n            },\r\n            _onCursorMoved: function onCursorMoved() {\r\n                var datum = this.dropdown.getDatumForCursor();\r\n                this.input.setInputValue(datum.value, true);\r\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\r\n            },\r\n            _onCursorRemoved: function onCursorRemoved() {\r\n                this.input.resetInputValue();\r\n                this._updateHint();\r\n            },\r\n            _onDatasetRendered: function onDatasetRendered() {\r\n                this._updateHint();\r\n            },\r\n            _onOpened: function onOpened() {\r\n                this._updateHint();\r\n                this.eventBus.trigger(\"opened\");\r\n            },\r\n            _onClosed: function onClosed() {\r\n                this.input.clearHint();\r\n                this.eventBus.trigger(\"closed\");\r\n            },\r\n            _onFocused: function onFocused() {\r\n                this.isActivated = true;\r\n                this.dropdown.open();\r\n            },\r\n            _onBlurred: function onBlurred() {\r\n                this.isActivated = false;\r\n                this.dropdown.empty();\r\n                this.dropdown.close();\r\n                this.setVal(\"\", true); //LM\r\n            },\r\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\r\n                var cursorDatum, topSuggestionDatum;\r\n                cursorDatum = this.dropdown.getDatumForCursor();\r\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\r\n                if (cursorDatum) {\r\n                    this._select(cursorDatum);\r\n                    $e.preventDefault();\r\n                } else if (this.autoselect && topSuggestionDatum) {\r\n                    this._select(topSuggestionDatum);\r\n                    $e.preventDefault();\r\n                }\r\n            },\r\n            _onTabKeyed: function onTabKeyed(type, $e) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForCursor()) {\r\n                    this._select(datum);\r\n                    $e.preventDefault();\r\n                } else {\r\n                    this._autocomplete(true);\r\n                }\r\n            },\r\n            _onEscKeyed: function onEscKeyed() {\r\n                this.dropdown.close();\r\n                this.input.resetInputValue();\r\n            },\r\n            _onUpKeyed: function onUpKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\r\n                this.dropdown.open();\r\n            },\r\n            _onDownKeyed: function onDownKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\r\n                this.dropdown.open();\r\n            },\r\n            _onLeftKeyed: function onLeftKeyed() {\r\n                this.dir === \"rtl\" && this._autocomplete();\r\n            },\r\n            _onRightKeyed: function onRightKeyed() {\r\n                this.dir === \"ltr\" && this._autocomplete();\r\n            },\r\n            _onQueryChanged: function onQueryChanged(e, query) {\r\n                this.input.clearHintIfInvalid();\r\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\r\n                this.dropdown.open();\r\n                this._setLanguageDirection();\r\n            },\r\n            _onWhitespaceChanged: function onWhitespaceChanged() {\r\n                this._updateHint();\r\n                this.dropdown.open();\r\n            },\r\n            _setLanguageDirection: function setLanguageDirection() {\r\n                var dir;\r\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\r\n                    this.dir = dir;\r\n                    this.$node.css(\"direction\", dir);\r\n                    this.dropdown.setLanguageDirection(dir);\r\n                }\r\n            },\r\n            _updateHint: function updateHint() {\r\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\r\n                datum = this.dropdown.getDatumForTopSuggestion();\r\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\r\n                    val = this.input.getInputValue();\r\n                    query = Input.normalizeQuery(val);\r\n                    escapedQuery = _.escapeRegExChars(query);\r\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\r\n                    match = frontMatchRegEx.exec(datum.value);\r\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\r\n                } else {\r\n                    this.input.clearHint();\r\n                }\r\n            },\r\n            _autocomplete: function autocomplete(laxCursor) {\r\n                var hint, query, isCursorAtEnd, datum;\r\n                hint = this.input.getHint();\r\n                query = this.input.getQuery();\r\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\r\n                if (hint && query !== hint && isCursorAtEnd) {\r\n                    datum = this.dropdown.getDatumForTopSuggestion();\r\n                    datum && this.input.setInputValue(datum.value);\r\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\r\n                }\r\n            },\r\n            _select: function select(datum) {\r\n                this.input.setQuery(datum.value);\r\n                this.input.setInputValue(datum.value, true);\r\n                this._setLanguageDirection();\r\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\r\n                this.dropdown.close();\r\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\r\n            },\r\n            open: function open() {\r\n                this.dropdown.open();\r\n            },\r\n            close: function close() {\r\n                this.dropdown.close();\r\n            },\r\n            setVal: function setVal(val) {\r\n                if (this.isActivated) {\r\n                    this.input.setInputValue(val);\r\n                } else {\r\n                    this.input.setQuery(val);\r\n                    this.input.setInputValue(val, true);\r\n                }\r\n                this._setLanguageDirection();\r\n            },\r\n            getVal: function getVal() {\r\n                return this.input.getQuery();\r\n            },\r\n            destroy: function destroy() {\r\n                this.input.destroy();\r\n                this.dropdown.destroy();\r\n                destroyDomStructure(this.$node);\r\n                this.$node = null;\r\n            }\r\n        });\r\n        return Typeahead;\r\n        function buildDomStructure(input, withHint) {\r\n            var $input, $wrapper, $dropdown, $hint;\r\n            $input = $(input);\r\n            $wrapper = $(html.wrapper).css(css.wrapper);\r\n            $dropdown = $(html.dropdown).css(css.dropdown);\r\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\r\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: \"false\"\r\n            });\r\n            $input.data(attrsKey, {\r\n                dir: $input.attr(\"dir\"),\r\n                autocomplete: $input.attr(\"autocomplete\"),\r\n                spellcheck: $input.attr(\"spellcheck\"),\r\n                style: $input.attr(\"style\")\r\n            });\r\n            $input.addClass(\"tt-input\").attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: false\r\n            }).css(withHint ? css.input : css.inputWithNoHint);\r\n            try {\r\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\r\n            } catch (e) {}\r\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\r\n        }\r\n        function getBackgroundStyles($el) {\r\n            return {\r\n                backgroundAttachment: $el.css(\"background-attachment\"),\r\n                backgroundClip: $el.css(\"background-clip\"),\r\n                backgroundColor: $el.css(\"background-color\"),\r\n                backgroundImage: $el.css(\"background-image\"),\r\n                backgroundOrigin: $el.css(\"background-origin\"),\r\n                backgroundPosition: $el.css(\"background-position\"),\r\n                backgroundRepeat: $el.css(\"background-repeat\"),\r\n                backgroundSize: $el.css(\"background-size\")\r\n            };\r\n        }\r\n        function destroyDomStructure($node) {\r\n            var $input = $node.find(\".tt-input\");\r\n            _.each($input.data(attrsKey), function(val, key) {\r\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\r\n            });\r\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\r\n            $node.remove();\r\n        }\r\n    }();\r\n    (function() {\r\n        var old, typeaheadKey, methods;\r\n        old = $.fn.typeahead;\r\n        typeaheadKey = \"ttTypeahead\";\r\n        methods = {\r\n            initialize: function initialize(o, datasets) {\r\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\r\n                o = o || {};\r\n                return this.each(attach);\r\n                function attach() {\r\n                    var $input = $(this), eventBus, typeahead;\r\n                    _.each(datasets, function(d) {\r\n                        d.highlight = !!o.highlight;\r\n                    });\r\n                    typeahead = new Typeahead({\r\n                        input: $input,\r\n                        eventBus: eventBus = new EventBus({\r\n                            el: $input\r\n                        }),\r\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\r\n                        minLength: o.minLength,\r\n                        autoselect: o.autoselect,\r\n                        datasets: datasets\r\n                    });\r\n                    $input.data(typeaheadKey, typeahead);\r\n                }\r\n            },\r\n            open: function open() {\r\n                return this.each(openTypeahead);\r\n                function openTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.open();\r\n                    }\r\n                }\r\n            },\r\n            close: function close() {\r\n                return this.each(closeTypeahead);\r\n                function closeTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.close();\r\n                    }\r\n                }\r\n            },\r\n            val: function val(newVal) {\r\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\r\n                function setVal() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.setVal(newVal);\r\n                    }\r\n                }\r\n                function getVal($input) {\r\n                    var typeahead, query;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        query = typeahead.getVal();\r\n                    }\r\n                    return query;\r\n                }\r\n            },\r\n            destroy: function destroy() {\r\n                return this.each(unattach);\r\n                function unattach() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.destroy();\r\n                        $input.removeData(typeaheadKey);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        $.fn.typeahead = function(method) {\r\n            if (methods[method]) {\r\n                return methods[method].apply(this, [].slice.call(arguments, 1));\r\n            } else {\r\n                return methods.initialize.apply(this, arguments);\r\n            }\r\n        };\r\n        $.fn.typeahead.noConflict = function noConflict() {\r\n            $.fn.typeahead = old;\r\n            return this;\r\n        };\r\n    })();\r\n    \r\n    \r\n    \r\n//})(window.jQuery);\r\n\r\n\r\n});\n",
        +    "define('searchView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/search.html',\r\n  'text!tpl/search_suggestion.html',\r\n  // Tools\r\n  'typeahead'\r\n], function(App, searchTpl, suggestionTpl) {\r\n\r\n  var searchView = Backbone.View.extend({\r\n    el: '#search',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      var tpl = _.template(searchTpl);\r\n      var className = 'form-control input-lg';\r\n      var placeholder = 'Search reference';\r\n      this.searchHtml = tpl({\r\n        'placeholder': placeholder,\r\n        'className': className\r\n      });\r\n      this.items = App.classes.concat(App.allItems);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render input field with Typehead activated.\r\n     */\r\n    render: function() {\r\n      // Append the view to the dom\r\n      this.$el.append(this.searchHtml);\r\n\r\n      // Render Typeahead\r\n      var $searchInput = this.$el.find('input[type=text]');\r\n      this.typeaheadRender($searchInput);\r\n      this.typeaheadEvents($searchInput);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Apply Twitter Typeahead to the search input field.\r\n     * @param {jquery} $input\r\n     */\r\n    typeaheadRender: function($input) {\r\n      var self = this;\r\n      $input.typeahead(null, {\r\n        'displayKey': 'name',\r\n        'minLength': 2,\r\n        //'highlight': true,\r\n        'source': self.substringMatcher(this.items),\r\n        'templates': {\r\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\r\n          'suggestion': _.template(suggestionTpl)\r\n        }\r\n      });\r\n    },\r\n    /**\r\n     * Setup typeahead custom events (item selected).\r\n     */\r\n    typeaheadEvents: function($input) {\r\n      var self = this;\r\n      $input.on('typeahead:selected', function(e, item, datasetName) {\r\n        var selectedItem = self.items[item.idx];\r\n        select(selectedItem);\r\n      });\r\n      $input.on('keydown', function(e) {\r\n        if (e.which === 13) { // enter\r\n          var txt = $input.val();\r\n          var f = _.find(self.items, function(it) { return it.name == txt; });\r\n          if (f) {\r\n            select(f);\r\n          }\r\n        } else if (e.which === 27) {\r\n          $input.blur();\r\n        }\r\n      });\r\n\r\n      function select(selectedItem) {\r\n        var hash = App.router.getHash(selectedItem);//\r\n        App.router.navigate(hash, {'trigger': true});\r\n        $('#item').focus();\r\n      }\r\n    },\r\n    /**\r\n     * substringMatcher function for Typehead (search for strings in an array).\r\n     * @param {array} array\r\n     * @returns {Function}\r\n     */\r\n    substringMatcher: function(array) {\r\n      return function findMatches(query, callback) {\r\n        var matches = [], substrRegex, arrayLength = array.length;\r\n\r\n        // regex used to determine if a string contains the substring `query`\r\n        substrRegex = new RegExp(query, 'i');\r\n\r\n        // iterate through the pool of strings and for any string that\r\n        // contains the substring `query`, add it to the `matches` array\r\n        for (var i=0; i < arrayLength; i++) {\r\n          var item = array[i];\r\n          if (substrRegex.test(item.name)) {\r\n            // typeahead expects suggestions to be a js object\r\n            matches.push({\r\n              'itemtype': item.itemtype,\r\n              'name': item.name,\r\n              'className': item.class,\r\n              'is_constructor': !!item.is_constructor,\r\n              'final': item.final,\r\n              'idx': i\r\n            });\r\n          }\r\n        }\r\n\r\n        callback(matches);\r\n      };\r\n    }\r\n\r\n  });\r\n\r\n  return searchView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\r\\n  <div class=\"reference-group clearfix main-ref-page\">  \\r\\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\r\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\r\\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\r\\n      <div class=\"reference-subgroup\">\\r\\n        <% if (subgroup.name !== \\'0\\') { %>\\r\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\r\\n        <% } %>\\r\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\r\\n        <% _.each(subgroup.items, function(item) { %>\\r\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\r\\n        <% }); %>\\r\\n        </ul>\\r\\n      </div>\\r\\n    <% }); %>\\r\\n    </div>\\r\\n  </div>\\r\\n<% }); %>\\r\\n';});\n\n",
        +    "define('listView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/list.html'\r\n], function (App, listTpl) {\r\n  var striptags = function(html) {\r\n    var div = document.createElement('div');\r\n    div.innerHTML = html;\r\n    return div.textContent;\r\n  };\r\n\r\n  var listView = Backbone.View.extend({\r\n    el: '#list',\r\n    events: {},\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function () {\r\n      this.listTpl = _.template(listTpl);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render the list.\r\n     */\r\n    render: function (items, listCollection) {\r\n      if (items && listCollection) {\r\n        var self = this;\r\n\r\n        // Render items and group them by module\r\n        // module === group\r\n        this.groups = {};\r\n        _.each(items, function (item, i) {\r\n\r\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n\r\n            var group = item.module || '_';\r\n            var subgroup = item.submodule || '_';\r\n            if (group === subgroup) {\r\n              subgroup = '0';\r\n            }\r\n            var hash = App.router.getHash(item);\r\n\r\n            // Create a group list\r\n            if (!self.groups[group]) {\r\n              self.groups[group] = {\r\n                name: group.replace('_', '&nbsp;'),\r\n                subgroups: {}\r\n              };\r\n            }\r\n\r\n            // Create a subgroup list\r\n            if (!self.groups[group].subgroups[subgroup]) {\r\n              self.groups[group].subgroups[subgroup] = {\r\n                name: subgroup.replace('_', '&nbsp;'),\r\n                items: []\r\n              };\r\n            }\r\n\r\n            // hide the un-interesting constants\r\n            if (group === 'Constants' && !item.example)\r\n              return;\r\n\r\n            if (item.class === 'p5') {\r\n\r\n              self.groups[group].subgroups[subgroup].items.push(item);\r\n\r\n            } else {\r\n\r\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\r\n                function(i){ return i.name == item.class; });\r\n\r\n              if (!found) {\r\n\r\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\r\n                var ind = hash.lastIndexOf('/');\r\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\r\n                self.groups[group].subgroups[subgroup].items.push({\r\n                  name: item.class,\r\n                  hash: hash\r\n                });\r\n              }\r\n\r\n            }\r\n          }\r\n        });\r\n\r\n        // Put the <li> items html into the list <ul>\r\n        var listHtml = self.listTpl({\r\n          'striptags': striptags,\r\n          'title': self.capitalizeFirst(listCollection),\r\n          'groups': self.groups,\r\n          'listCollection': listCollection\r\n        });\r\n\r\n        // Render the view\r\n        this.$el.html(listHtml);\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a list of items.\r\n     * @param {array} items Array of item objects.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function (listGroup) {\r\n      if (App[listGroup]) {\r\n        this.render(App[listGroup], listGroup);\r\n      }\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function (str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n\r\n\r\n\r\n  });\r\n\r\n  return listView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\r\\n\\r\\n<% if (item.example) { %>\\r\\n<div class=\"example\">\\r\\n  <h3 id=\"reference-example\">Examples</h3>\\r\\n\\r\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\r\\n    <% _.each(item.example, function(example, i){ %>\\r\\n      <%= example %>\\r\\n    <% }); %>\\r\\n  </div>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<div class=\"description\">\\r\\n    \\r\\n  <h3 id=\"reference-description\">Description</h3>\\r\\n\\r\\n  <% if (item.deprecated) { %>\\r\\n    <p>\\r\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n      \\r\\n\\r\\n  <span class=\\'description-text\\'><%= item.description %></span>\\r\\n\\r\\n  <% if (item.extends) { %>\\r\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.module === \\'p5.sound\\') { %>\\r\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\r\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\r\\n    </p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.constRefs) { %>\\r\\n    <p>Used by:\\r\\n  <%\\r\\n      var refs = item.constRefs;\\r\\n      for (var i = 0; i < refs.length; i ++) {\\r\\n        var ref = refs[i];\\r\\n        var name = ref;\\r\\n        if (name.substr(0, 3) === \\'p5.\\') {\\r\\n          name = name.substr(3);\\r\\n        }\\r\\n  if (i !== 0) {\\r\\n          if (i == refs.length - 1) {\\r\\n            %> and <%\\r\\n          } else {\\r\\n            %>, <%\\r\\n          }\\r\\n        }\\r\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\r\\n      }\\r\\n  %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n</div>\\r\\n\\r\\n<% if (isConstructor || !isClass) { %>\\r\\n\\r\\n<div>\\r\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\r\\n  <p>\\r\\n    <% syntaxes.forEach(function(syntax) { %>\\r\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\r\\n    <% }) %>\\r\\n  </p>\\r\\n</div>\\r\\n\\r\\n\\r\\n<% if (item.params) { %>\\r\\n  <div class=\"params\">\\r\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\r\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\r\\n    <% for (var i=0; i<item.params.length; i++) { %>\\r\\n      <% var p = item.params[i] %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><%=p.name%></div>\\r\\n        <% if (p.type) { %>\\r\\n          <div class=\\'paramtype\\'>\\r\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\r\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\r\\n          <% if (p.optional) { %> (Optional)<% } %>\\r\\n          </div>\\r\\n        <% } %>\\r\\n      </li>\\r\\n    <% } %>\\r\\n    </ul>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% if (item.return && item.return.type) { %>\\r\\n  <div>\\r\\n    <h3 id=\"reference-returns\">Returns</h3>\\r\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% } %>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/class.html',[],function () { return '\\r\\n<% if (typeof constructor !== \\'undefined\\') { %>\\r\\n<div class=\"constructor\">\\r\\n  <!--<h2>Constructor</h2>--> \\r\\n  <%=constructor%>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (fields.length > 0) { %>\\r\\n  <h4>Fields</h4>\\r\\n  <p>\\r\\n    <% _.each(fields, function(item) { %>\\r\\n      <a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%></a>: <%= item.description %>\\r\\n      <br>\\r\\n    <% }); %>\\r\\n  </p>\\r\\n<% } %>\\r\\n\\r\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (methods.length > 0) { %>\\r\\n  <h4>Methods</h4>\\r\\n  <p>\\r\\n    <table>\\r\\n    <% _.each(methods, function(item) { %>\\r\\n      <tr>\\r\\n      <td><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></td><td><div class=\"method_description\"><%= item.description %></div></td>\\r\\n      </tr>\\r\\n    <% }); %>\\r\\n    </table>\\r\\n  </p>\\r\\n<% } %>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\r\\n<br><br>\\r\\n\\r\\n<div>\\r\\n<% if (item.file && item.line) { %>\\r\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\r\\n<% } %>\\r\\n</div>\\r\\n\\r\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\r\\n<br><br>\\r\\n';});\n\n",
        +    "// Copyright (C) 2006 Google Inc.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n//      http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview\r\n * some functions for browser-side pretty printing of code contained in html.\r\n *\r\n * <p>\r\n * For a fairly comprehensive set of languages see the\r\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\r\n * file that came with this source.  At a minimum, the lexer should work on a\r\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\r\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\r\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\r\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\r\n * <p>\r\n * Usage: <ol>\r\n * <li> include this source file in an html page via\r\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\r\n * <li> define style rules.  See the example page for examples.\r\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\r\n *    {@code class=prettyprint.}\r\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\r\n *    printer needs to do more substantial DOM manipulations to support that, so\r\n *    some css styles may not be preserved.\r\n * </ol>\r\n * That's it.  I wanted to keep the API as simple as possible, so there's no\r\n * need to specify which language the code is in, but if you wish, you can add\r\n * another class to the {@code <pre>} or {@code <code>} element to specify the\r\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\r\n * starts with \"lang-\" followed by a file extension, specifies the file type.\r\n * See the \"lang-*.js\" files in this directory for code that implements\r\n * per-language file handlers.\r\n * <p>\r\n * Change log:<br>\r\n * cbeust, 2006/08/22\r\n * <blockquote>\r\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\r\n * </blockquote>\r\n * @requires console\r\n */\r\n\r\n// JSLint declarations\r\n/*global console, document, navigator, setTimeout, window, define */\r\n\r\n/** @define {boolean} */\r\nvar IN_GLOBAL_SCOPE = true;\r\n\r\n/**\r\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\r\n * UI events.\r\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\r\n */\r\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\r\n\r\n/**\r\n * Pretty print a chunk of code.\r\n * @param {string} sourceCodeHtml The HTML to pretty print.\r\n * @param {string} opt_langExtension The language name to use.\r\n *     Typically, a filename extension like 'cpp' or 'java'.\r\n * @param {number|boolean} opt_numberLines True to number lines,\r\n *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n * @return {string} code as html, but prettier\r\n */\r\nvar prettyPrintOne;\r\n/**\r\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n * {@code class=prettyprint} and prettify them.\r\n *\r\n * @param {Function} opt_whenDone called when prettifying is done.\r\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n *   containing all the elements to pretty print.\r\n *   Defaults to {@code document.body}.\r\n */\r\nvar prettyPrint;\r\n\r\n\r\n(function () {\r\n  var win = window;\r\n  // Keyword lists for various languages.\r\n  // We use things that coerce to strings to make them compact when minified\r\n  // and to defeat aggressive optimizers that fold large string constants.\r\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\r\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \r\n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\r\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\r\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\r\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\r\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\r\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\r\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\r\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\r\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\r\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\r\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\r\n      \"throws,transient\"];\r\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\r\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\r\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\r\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\r\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\r\n      \"var,virtual,where\"];\r\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\r\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\r\n      \"throw,true,try,unless,until,when,while,yes\";\r\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\r\n      \"Infinity,NaN\"];\r\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\r\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\r\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\r\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\r\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\r\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\r\n      \"False,True,None\"];\r\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\r\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\r\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\r\n      \"BEGIN,END\"];\r\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\r\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\r\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\r\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\r\n      \"function,in,local,set,then,until\"];\r\n  var ALL_KEYWORDS = [\r\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\r\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\r\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\r\n\r\n  // token style names.  correspond to css classes\r\n  /**\r\n   * token style for a string literal\r\n   * @const\r\n   */\r\n  var PR_STRING = 'str';\r\n  /**\r\n   * token style for a keyword\r\n   * @const\r\n   */\r\n  var PR_KEYWORD = 'kwd';\r\n  /**\r\n   * token style for a comment\r\n   * @const\r\n   */\r\n  var PR_COMMENT = 'com';\r\n  /**\r\n   * token style for a type\r\n   * @const\r\n   */\r\n  var PR_TYPE = 'typ';\r\n  /**\r\n   * token style for a literal value.  e.g. 1, null, true.\r\n   * @const\r\n   */\r\n  var PR_LITERAL = 'lit';\r\n  /**\r\n   * token style for a punctuation string.\r\n   * @const\r\n   */\r\n  var PR_PUNCTUATION = 'pun';\r\n  /**\r\n   * token style for plain text.\r\n   * @const\r\n   */\r\n  var PR_PLAIN = 'pln';\r\n\r\n  /**\r\n   * token style for an sgml tag.\r\n   * @const\r\n   */\r\n  var PR_TAG = 'tag';\r\n  /**\r\n   * token style for a markup declaration such as a DOCTYPE.\r\n   * @const\r\n   */\r\n  var PR_DECLARATION = 'dec';\r\n  /**\r\n   * token style for embedded source.\r\n   * @const\r\n   */\r\n  var PR_SOURCE = 'src';\r\n  /**\r\n   * token style for an sgml attribute name.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_NAME = 'atn';\r\n  /**\r\n   * token style for an sgml attribute value.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_VALUE = 'atv';\r\n\r\n  /**\r\n   * A class that indicates a section of markup that is not code, e.g. to allow\r\n   * embedding of line numbers within code listings.\r\n   * @const\r\n   */\r\n  var PR_NOCODE = 'nocode';\r\n\r\n  \r\n  \r\n  /**\r\n   * A set of tokens that can precede a regular expression literal in\r\n   * javascript\r\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\r\n   * has the full list, but I've removed ones that might be problematic when\r\n   * seen in languages that don't support regular expression literals.\r\n   *\r\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\r\n   * literal in a syntactically legal javascript program, and I've removed the\r\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\r\n   * as a count of inches.\r\n   *\r\n   * <p>The link above does not accurately describe EcmaScript rules since\r\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\r\n   * very well in practice.\r\n   *\r\n   * @private\r\n   * @const\r\n   */\r\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\r\n  \r\n  // CAVEAT: this does not properly handle the case where a regular\r\n  // expression immediately follows another since a regular expression may\r\n  // have flags for case-sensitivity and the like.  Having regexp tokens\r\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\r\n  // TODO: maybe style special characters inside a regexp as punctuation.\r\n\r\n  /**\r\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\r\n   * matches the union of the sets of strings matched by the input RegExp.\r\n   * Since it matches globally, if the input strings have a start-of-input\r\n   * anchor (/^.../), it is ignored for the purposes of unioning.\r\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\r\n   * @return {RegExp} a global regex.\r\n   */\r\n  function combinePrefixPatterns(regexs) {\r\n    var capturedGroupIndex = 0;\r\n  \r\n    var needToFoldCase = false;\r\n    var ignoreCase = false;\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.ignoreCase) {\r\n        ignoreCase = true;\r\n      } else if (/[a-z]/i.test(regex.source.replace(\r\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\r\n        needToFoldCase = true;\r\n        ignoreCase = false;\r\n        break;\r\n      }\r\n    }\r\n  \r\n    var escapeCharToCodeUnit = {\r\n      'b': 8,\r\n      't': 9,\r\n      'n': 0xa,\r\n      'v': 0xb,\r\n      'f': 0xc,\r\n      'r': 0xd\r\n    };\r\n  \r\n    function decodeEscape(charsetPart) {\r\n      var cc0 = charsetPart.charCodeAt(0);\r\n      if (cc0 !== 92 /* \\\\ */) {\r\n        return cc0;\r\n      }\r\n      var c1 = charsetPart.charAt(1);\r\n      cc0 = escapeCharToCodeUnit[c1];\r\n      if (cc0) {\r\n        return cc0;\r\n      } else if ('0' <= c1 && c1 <= '7') {\r\n        return parseInt(charsetPart.substring(1), 8);\r\n      } else if (c1 === 'u' || c1 === 'x') {\r\n        return parseInt(charsetPart.substring(2), 16);\r\n      } else {\r\n        return charsetPart.charCodeAt(1);\r\n      }\r\n    }\r\n  \r\n    function encodeEscape(charCode) {\r\n      if (charCode < 0x20) {\r\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\r\n      }\r\n      var ch = String.fromCharCode(charCode);\r\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\r\n          ? \"\\\\\" + ch : ch;\r\n    }\r\n  \r\n    function caseFoldCharset(charSet) {\r\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\r\n          new RegExp(\r\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\r\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\r\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\r\n              + '|\\\\\\\\[0-7]{1,2}'\r\n              + '|\\\\\\\\[\\\\s\\\\S]'\r\n              + '|-'\r\n              + '|[^-\\\\\\\\]',\r\n              'g'));\r\n      var ranges = [];\r\n      var inverse = charsetParts[0] === '^';\r\n  \r\n      var out = ['['];\r\n      if (inverse) { out.push('^'); }\r\n  \r\n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\r\n        var p = charsetParts[i];\r\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\r\n          out.push(p);\r\n        } else {\r\n          var start = decodeEscape(p);\r\n          var end;\r\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\r\n            end = decodeEscape(charsetParts[i + 2]);\r\n            i += 2;\r\n          } else {\r\n            end = start;\r\n          }\r\n          ranges.push([start, end]);\r\n          // If the range might intersect letters, then expand it.\r\n          // This case handling is too simplistic.\r\n          // It does not deal with non-latin case folding.\r\n          // It works for latin source code identifiers though.\r\n          if (!(end < 65 || start > 122)) {\r\n            if (!(end < 65 || start > 90)) {\r\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\r\n            }\r\n            if (!(end < 97 || start > 122)) {\r\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\r\n      // -> [[1, 12], [14, 14], [16, 17]]\r\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\r\n      var consolidatedRanges = [];\r\n      var lastRange = [];\r\n      for (var i = 0; i < ranges.length; ++i) {\r\n        var range = ranges[i];\r\n        if (range[0] <= lastRange[1] + 1) {\r\n          lastRange[1] = Math.max(lastRange[1], range[1]);\r\n        } else {\r\n          consolidatedRanges.push(lastRange = range);\r\n        }\r\n      }\r\n  \r\n      for (var i = 0; i < consolidatedRanges.length; ++i) {\r\n        var range = consolidatedRanges[i];\r\n        out.push(encodeEscape(range[0]));\r\n        if (range[1] > range[0]) {\r\n          if (range[1] + 1 > range[0]) { out.push('-'); }\r\n          out.push(encodeEscape(range[1]));\r\n        }\r\n      }\r\n      out.push(']');\r\n      return out.join('');\r\n    }\r\n  \r\n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\r\n      // Split into character sets, escape sequences, punctuation strings\r\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\r\n      // include any of the above.\r\n      var parts = regex.source.match(\r\n          new RegExp(\r\n              '(?:'\r\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\r\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\r\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\r\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\r\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\r\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\r\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\r\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\r\n              + ')',\r\n              'g'));\r\n      var n = parts.length;\r\n  \r\n      // Maps captured group numbers to the number they will occupy in\r\n      // the output or to -1 if that has not been determined, or to\r\n      // undefined if they need not be capturing in the output.\r\n      var capturedGroups = [];\r\n  \r\n      // Walk over and identify back references to build the capturedGroups\r\n      // mapping.\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          // groups are 1-indexed, so max group index is count of '('\r\n          ++groupIndex;\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue) {\r\n            if (decimalValue <= groupIndex) {\r\n              capturedGroups[decimalValue] = -1;\r\n            } else {\r\n              // Replace with an unambiguous escape sequence so that\r\n              // an octal escape sequence does not turn into a backreference\r\n              // to a capturing group from an earlier regex.\r\n              parts[i] = encodeEscape(decimalValue);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Renumber groups and reduce capturing groups to non-capturing groups\r\n      // where possible.\r\n      for (var i = 1; i < capturedGroups.length; ++i) {\r\n        if (-1 === capturedGroups[i]) {\r\n          capturedGroups[i] = ++capturedGroupIndex;\r\n        }\r\n      }\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          ++groupIndex;\r\n          if (!capturedGroups[groupIndex]) {\r\n            parts[i] = '(?:';\r\n          }\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue && decimalValue <= groupIndex) {\r\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Remove any prefix anchors so that the output will match anywhere.\r\n      // ^^ really does mean an anchored match though.\r\n      for (var i = 0; i < n; ++i) {\r\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\r\n      }\r\n  \r\n      // Expand letters to groups to handle mixing of case-sensitive and\r\n      // case-insensitive patterns if necessary.\r\n      if (regex.ignoreCase && needToFoldCase) {\r\n        for (var i = 0; i < n; ++i) {\r\n          var p = parts[i];\r\n          var ch0 = p.charAt(0);\r\n          if (p.length >= 2 && ch0 === '[') {\r\n            parts[i] = caseFoldCharset(p);\r\n          } else if (ch0 !== '\\\\') {\r\n            // TODO: handle letters in numeric escapes.\r\n            parts[i] = p.replace(\r\n                /[a-zA-Z]/g,\r\n                function (ch) {\r\n                  var cc = ch.charCodeAt(0);\r\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\r\n                });\r\n          }\r\n        }\r\n      }\r\n  \r\n      return parts.join('');\r\n    }\r\n  \r\n    var rewritten = [];\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\r\n      rewritten.push(\r\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\r\n    }\r\n  \r\n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\r\n  }\r\n\r\n  /**\r\n   * Split markup into a string of source code and an array mapping ranges in\r\n   * that string to the text nodes in which they appear.\r\n   *\r\n   * <p>\r\n   * The HTML DOM structure:</p>\r\n   * <pre>\r\n   * (Element   \"p\"\r\n   *   (Element \"b\"\r\n   *     (Text  \"print \"))       ; #1\r\n   *   (Text    \"'Hello '\")      ; #2\r\n   *   (Element \"br\")            ; #3\r\n   *   (Text    \"  + 'World';\")) ; #4\r\n   * </pre>\r\n   * <p>\r\n   * corresponds to the HTML\r\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\r\n   *\r\n   * <p>\r\n   * It will produce the output:</p>\r\n   * <pre>\r\n   * {\r\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\r\n   *   //                     1          2\r\n   *   //           012345678901234 5678901234567\r\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\r\n   * }\r\n   * </pre>\r\n   * <p>\r\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\r\n   * on for the other text nodes.\r\n   * </p>\r\n   *\r\n   * <p>\r\n   * The {@code} spans array is an array of pairs.  Even elements are the start\r\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\r\n   * that contain the text for those substrings.\r\n   * Substrings continue until the next index or the end of the source.\r\n   * </p>\r\n   *\r\n   * @param {Node} node an HTML DOM subtree containing source-code.\r\n   * @param {boolean} isPreformatted true if white-space in text nodes should\r\n   *    be considered significant.\r\n   * @return {Object} source code and the text nodes in which they occur.\r\n   */\r\n  function extractSourceSpans(node, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n  \r\n    var chunks = [];\r\n    var length = 0;\r\n    var spans = [];\r\n    var k = 0;\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1) {  // Element\r\n        if (nocode.test(node.className)) { return; }\r\n        for (var child = node.firstChild; child; child = child.nextSibling) {\r\n          walk(child);\r\n        }\r\n        var nodeName = node.nodeName.toLowerCase();\r\n        if ('br' === nodeName || 'li' === nodeName) {\r\n          chunks[k] = '\\n';\r\n          spans[k << 1] = length++;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      } else if (type == 3 || type == 4) {  // Text\r\n        var text = node.nodeValue;\r\n        if (text.length) {\r\n          if (!isPreformatted) {\r\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\r\n          } else {\r\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\r\n          }\r\n          // TODO: handle tabs here?\r\n          chunks[k] = text;\r\n          spans[k << 1] = length;\r\n          length += text.length;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      }\r\n    }\r\n  \r\n    walk(node);\r\n  \r\n    return {\r\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\r\n      spans: spans\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Apply the given language handler to sourceCode and add the resulting\r\n   * decorations to out.\r\n   * @param {number} basePos the index of sourceCode within the chunk of source\r\n   *    whose decorations are already present on out.\r\n   */\r\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\r\n    if (!sourceCode) { return; }\r\n    var job = {\r\n      sourceCode: sourceCode,\r\n      basePos: basePos\r\n    };\r\n    langHandler(job);\r\n    out.push.apply(out, job.decorations);\r\n  }\r\n\r\n  var notWs = /\\S/;\r\n\r\n  /**\r\n   * Given an element, if it contains only one child element and any text nodes\r\n   * it contains contain only space characters, return the sole child element.\r\n   * Otherwise returns undefined.\r\n   * <p>\r\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\r\n   * there is a single child element that contains all the non-space textual\r\n   * content, but not to return anything where there are multiple child elements\r\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\r\n   * is textual content.\r\n   */\r\n  function childContentWrapper(element) {\r\n    var wrapper = undefined;\r\n    for (var c = element.firstChild; c; c = c.nextSibling) {\r\n      var type = c.nodeType;\r\n      wrapper = (type === 1)  // Element Node\r\n          ? (wrapper ? element : c)\r\n          : (type === 3)  // Text Node\r\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\r\n          : wrapper;\r\n    }\r\n    return wrapper === element ? undefined : wrapper;\r\n  }\r\n\r\n  /** Given triples of [style, pattern, context] returns a lexing function,\r\n    * The lexing function interprets the patterns to find token boundaries and\r\n    * returns a decoration list of the form\r\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\r\n    * where index_n is an index into the sourceCode, and style_n is a style\r\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\r\n    * all characters in sourceCode[index_n-1:index_n].\r\n    *\r\n    * The stylePatterns is a list whose elements have the form\r\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\r\n    *\r\n    * Style is a style constant like PR_PLAIN, or can be a string of the\r\n    * form 'lang-FOO', where FOO is a language extension describing the\r\n    * language of the portion of the token in $1 after pattern executes.\r\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\r\n    * '(hello (world))', then that portion of the token will be passed to the\r\n    * registered lisp handler for formatting.\r\n    * The text before and after group 1 will be restyled using this decorator\r\n    * so decorators should take care that this doesn't result in infinite\r\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\r\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\r\n    * '<script>foo()<\\/script>', which would cause the current decorator to\r\n    * be called with '<script>' which would not match the same rule since\r\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\r\n    * the generic tag rule.  The handler registered for the 'js' extension would\r\n    * then be called with 'foo()', and finally, the current decorator would\r\n    * be called with '<\\/script>' which would not match the original rule and\r\n    * so the generic tag rule would identify it as a tag.\r\n    *\r\n    * Pattern must only match prefixes, and if it matches a prefix, then that\r\n    * match is considered a token with the same style.\r\n    *\r\n    * Context is applied to the last non-whitespace, non-comment token\r\n    * recognized.\r\n    *\r\n    * Shortcut is an optional string of characters, any of which, if the first\r\n    * character, gurantee that this pattern and only this pattern matches.\r\n    *\r\n    * @param {Array} shortcutStylePatterns patterns that always start with\r\n    *   a known character.  Must have a shortcut string.\r\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\r\n    *   order if the shortcut ones fail.  May have shortcuts.\r\n    *\r\n    * @return {function (Object)} a\r\n    *   function that takes source code and returns a list of decorations.\r\n    */\r\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\r\n    var shortcuts = {};\r\n    var tokenizer;\r\n    (function () {\r\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\r\n      var allRegexs = [];\r\n      var regexKeys = {};\r\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\r\n        var patternParts = allPatterns[i];\r\n        var shortcutChars = patternParts[3];\r\n        if (shortcutChars) {\r\n          for (var c = shortcutChars.length; --c >= 0;) {\r\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\r\n          }\r\n        }\r\n        var regex = patternParts[1];\r\n        var k = '' + regex;\r\n        if (!regexKeys.hasOwnProperty(k)) {\r\n          allRegexs.push(regex);\r\n          regexKeys[k] = null;\r\n        }\r\n      }\r\n      allRegexs.push(/[\\0-\\uffff]/);\r\n      tokenizer = combinePrefixPatterns(allRegexs);\r\n    })();\r\n\r\n    var nPatterns = fallthroughStylePatterns.length;\r\n\r\n    /**\r\n     * Lexes job.sourceCode and produces an output array job.decorations of\r\n     * style classes preceded by the position at which they start in\r\n     * job.sourceCode in order.\r\n     *\r\n     * @param {Object} job an object like <pre>{\r\n     *    sourceCode: {string} sourceText plain text,\r\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\r\n     *        sourceCode.\r\n     * }</pre>\r\n     */\r\n    var decorate = function (job) {\r\n      var sourceCode = job.sourceCode, basePos = job.basePos;\r\n      /** Even entries are positions in source in ascending order.  Odd enties\r\n        * are style markers (e.g., PR_COMMENT) that run from that position until\r\n        * the end.\r\n        * @type {Array.<number|string>}\r\n        */\r\n      var decorations = [basePos, PR_PLAIN];\r\n      var pos = 0;  // index into sourceCode\r\n      var tokens = sourceCode.match(tokenizer) || [];\r\n      var styleCache = {};\r\n\r\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\r\n        var token = tokens[ti];\r\n        var style = styleCache[token];\r\n        var match = void 0;\r\n\r\n        var isEmbedded;\r\n        if (typeof style === 'string') {\r\n          isEmbedded = false;\r\n        } else {\r\n          var patternParts = shortcuts[token.charAt(0)];\r\n          if (patternParts) {\r\n            match = token.match(patternParts[1]);\r\n            style = patternParts[0];\r\n          } else {\r\n            for (var i = 0; i < nPatterns; ++i) {\r\n              patternParts = fallthroughStylePatterns[i];\r\n              match = token.match(patternParts[1]);\r\n              if (match) {\r\n                style = patternParts[0];\r\n                break;\r\n              }\r\n            }\r\n\r\n            if (!match) {  // make sure that we make progress\r\n              style = PR_PLAIN;\r\n            }\r\n          }\r\n\r\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\r\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\r\n            isEmbedded = false;\r\n            style = PR_SOURCE;\r\n          }\r\n\r\n          if (!isEmbedded) { styleCache[token] = style; }\r\n        }\r\n\r\n        var tokenStart = pos;\r\n        pos += token.length;\r\n\r\n        if (!isEmbedded) {\r\n          decorations.push(basePos + tokenStart, style);\r\n        } else {  // Treat group 1 as an embedded block of source code.\r\n          var embeddedSource = match[1];\r\n          var embeddedSourceStart = token.indexOf(embeddedSource);\r\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\r\n          if (match[2]) {\r\n            // If embeddedSource can be blank, then it would match at the\r\n            // beginning which would cause us to infinitely recurse on the\r\n            // entire token, so we catch the right context in match[2].\r\n            embeddedSourceEnd = token.length - match[2].length;\r\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\r\n          }\r\n          var lang = style.substring(5);\r\n          // Decorate the left of the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart,\r\n              token.substring(0, embeddedSourceStart),\r\n              decorate, decorations);\r\n          // Decorate the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceStart,\r\n              embeddedSource,\r\n              langHandlerForExtension(lang, embeddedSource),\r\n              decorations);\r\n          // Decorate the right of the embedded section\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceEnd,\r\n              token.substring(embeddedSourceEnd),\r\n              decorate, decorations);\r\n        }\r\n      }\r\n      job.decorations = decorations;\r\n    };\r\n    return decorate;\r\n  }\r\n\r\n  /** returns a function that produces a list of decorations from source text.\r\n    *\r\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\r\n    * escape.  It does not recognize perl's qq() style strings.\r\n    * It has no special handling for double delimiter escapes as in basic, or\r\n    * the tripled delimiters used in python, but should work on those regardless\r\n    * although in those cases a single string literal may be broken up into\r\n    * multiple adjacent string literals.\r\n    *\r\n    * It recognizes C, C++, and shell style comments.\r\n    *\r\n    * @param {Object} options a set of optional parameters.\r\n    * @return {function (Object)} a function that examines the source code\r\n    *     in the input job and builds the decoration list.\r\n    */\r\n  function sourceDecorator(options) {\r\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\r\n    if (options['tripleQuotedStrings']) {\r\n      // '''multi-line-string''', 'single-line-string', and double-quoted\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\r\n           null, '\\'\"']);\r\n    } else if (options['multiLineStrings']) {\r\n      // 'multi-line-string', \"multi-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\r\n           null, '\\'\"`']);\r\n    } else {\r\n      // 'single-line-string', \"single-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,\r\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\r\n           null, '\"\\'']);\r\n    }\r\n    if (options['verbatimStrings']) {\r\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\r\n      fallthroughStylePatterns.push(\r\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\r\n    }\r\n    var hc = options['hashComments'];\r\n    if (hc) {\r\n      if (options['cStyleComments']) {\r\n        if (hc > 1) {  // multiline hash comments\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\r\n        } else {\r\n          // Stop C preprocessor declarations at an unclosed open comment\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\r\n               null, '#']);\r\n        }\r\n        // #include <stdio.h>\r\n        fallthroughStylePatterns.push(\r\n            [PR_STRING,\r\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\r\n             null]);\r\n      } else {\r\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\r\n      }\r\n    }\r\n    if (options['cStyleComments']) {\r\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\r\n      fallthroughStylePatterns.push(\r\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\r\n    }\r\n    var regexLiterals = options['regexLiterals'];\r\n    if (regexLiterals) {\r\n      /**\r\n       * @const\r\n       */\r\n      var regexExcls = regexLiterals > 1\r\n        ? ''  // Multiline regex literals\r\n        : '\\n\\r';\r\n      /**\r\n       * @const\r\n       */\r\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\r\n      /**\r\n       * @const\r\n       */\r\n      var REGEX_LITERAL = (\r\n          // A regular expression literal starts with a slash that is\r\n          // not followed by * or / so that it is not confused with\r\n          // comments.\r\n          '/(?=[^/*' + regexExcls + '])'\r\n          // and then contains any number of raw characters,\r\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\r\n          // escape sequences (\\x5C),\r\n          +    '|\\\\x5C' + regexAny\r\n          // or non-nesting character sets (\\x5B\\x5D);\r\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\r\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\r\n          // finally closed by a /.\r\n          + '/');\r\n      fallthroughStylePatterns.push(\r\n          ['lang-regex',\r\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\r\n           ]);\r\n    }\r\n\r\n    var types = options['types'];\r\n    if (types) {\r\n      fallthroughStylePatterns.push([PR_TYPE, types]);\r\n    }\r\n\r\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\r\n    if (keywords.length) {\r\n      fallthroughStylePatterns.push(\r\n          [PR_KEYWORD,\r\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\r\n           null]);\r\n    }\r\n\r\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\r\n\r\n    var punctuation =\r\n      // The Bash man page says\r\n\r\n      // A word is a sequence of characters considered as a single\r\n      // unit by GRUB. Words are separated by metacharacters,\r\n      // which are the following plus space, tab, and newline: { }\r\n      // | & $ ; < >\r\n      // ...\r\n      \r\n      // A word beginning with # causes that word and all remaining\r\n      // characters on that line to be ignored.\r\n\r\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\r\n      // comment but empirically\r\n      // $ echo {#}\r\n      // {#}\r\n      // $ echo \\$#\r\n      // $#\r\n      // $ echo }#\r\n      // }#\r\n\r\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\r\n\r\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\r\n      // suggests that this definition is compatible with a\r\n      // default mode that tries to use a single token definition\r\n      // to recognize both bash/python style comments and C\r\n      // preprocessor directives.\r\n\r\n      // This definition of punctuation does not include # in the list of\r\n      // follow-on exclusions, so # will not be broken before if preceeded\r\n      // by a punctuation character.  We could try to exclude # after\r\n      // [|&;<>] but that doesn't seem to cause many major problems.\r\n      // If that does turn out to be a problem, we should change the below\r\n      // when hc is truthy to include # in the run of punctuation characters\r\n      // only when not followint [|&;<>].\r\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\r\n    if (options['regexLiterals']) {\r\n      punctuation += '(?!\\s*\\/)';\r\n    }\r\n\r\n    fallthroughStylePatterns.push(\r\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\r\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\r\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_LITERAL,\r\n         new RegExp(\r\n             '^(?:'\r\n             // A hex number\r\n             + '0x[a-f0-9]+'\r\n             // or an octal or decimal number,\r\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\r\n             // possibly in scientific notation\r\n             + '(?:e[+\\\\-]?\\\\d+)?'\r\n             + ')'\r\n             // with an optional modifier like UL for unsigned long\r\n             + '[a-z]*', 'i'),\r\n         null, '0123456789'],\r\n        // Don't treat escaped quotes in bash as starting strings.\r\n        // See issue 144.\r\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\r\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\r\n\r\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\r\n  }\r\n\r\n  var decorateSource = sourceDecorator({\r\n        'keywords': ALL_KEYWORDS,\r\n        'hashComments': true,\r\n        'cStyleComments': true,\r\n        'multiLineStrings': true,\r\n        'regexLiterals': true\r\n      });\r\n\r\n  /**\r\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\r\n   * list item.\r\n   *\r\n   * @param {Node} node modified in place.  Its content is pulled into an\r\n   *     HTMLOListElement, and each line is moved into a separate list item.\r\n   *     This requires cloning elements, so the input might not have unique\r\n   *     IDs after numbering.\r\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\r\n   *     be treated as significant.\r\n   */\r\n  function numberLines(node, opt_startLineNum, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n    var lineBreak = /\\r\\n?|\\n/;\r\n  \r\n    var document = node.ownerDocument;\r\n  \r\n    var li = document.createElement('li');\r\n    while (node.firstChild) {\r\n      li.appendChild(node.firstChild);\r\n    }\r\n    // An array of lines.  We split below, so this is initialized to one\r\n    // un-split line.\r\n    var listItems = [li];\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1 && !nocode.test(node.className)) {  // Element\r\n        if ('br' === node.nodeName) {\r\n          breakAfter(node);\r\n          // Discard the <BR> since it is now flush against a </LI>.\r\n          if (node.parentNode) {\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        } else {\r\n          for (var child = node.firstChild; child; child = child.nextSibling) {\r\n            walk(child);\r\n          }\r\n        }\r\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\r\n        var text = node.nodeValue;\r\n        var match = text.match(lineBreak);\r\n        if (match) {\r\n          var firstLine = text.substring(0, match.index);\r\n          node.nodeValue = firstLine;\r\n          var tail = text.substring(match.index + match[0].length);\r\n          if (tail) {\r\n            var parent = node.parentNode;\r\n            parent.insertBefore(\r\n              document.createTextNode(tail), node.nextSibling);\r\n          }\r\n          breakAfter(node);\r\n          if (!firstLine) {\r\n            // Don't leave blank text nodes in the DOM.\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  \r\n    // Split a line after the given node.\r\n    function breakAfter(lineEndNode) {\r\n      // If there's nothing to the right, then we can skip ending the line\r\n      // here, and move root-wards since splitting just before an end-tag\r\n      // would require us to create a bunch of empty copies.\r\n      while (!lineEndNode.nextSibling) {\r\n        lineEndNode = lineEndNode.parentNode;\r\n        if (!lineEndNode) { return; }\r\n      }\r\n  \r\n      function breakLeftOf(limit, copy) {\r\n        // Clone shallowly if this node needs to be on both sides of the break.\r\n        var rightSide = copy ? limit.cloneNode(false) : limit;\r\n        var parent = limit.parentNode;\r\n        if (parent) {\r\n          // We clone the parent chain.\r\n          // This helps us resurrect important styling elements that cross lines.\r\n          // E.g. in <i>Foo<br>Bar</i>\r\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\r\n          var parentClone = breakLeftOf(parent, 1);\r\n          // Move the clone and everything to the right of the original\r\n          // onto the cloned parent.\r\n          var next = limit.nextSibling;\r\n          parentClone.appendChild(rightSide);\r\n          for (var sibling = next; sibling; sibling = next) {\r\n            next = sibling.nextSibling;\r\n            parentClone.appendChild(sibling);\r\n          }\r\n        }\r\n        return rightSide;\r\n      }\r\n  \r\n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\r\n  \r\n      // Walk the parent chain until we reach an unattached LI.\r\n      for (var parent;\r\n           // Check nodeType since IE invents document fragments.\r\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\r\n        copiedListItem = parent;\r\n      }\r\n      // Put it on the list of lines for later processing.\r\n      listItems.push(copiedListItem);\r\n    }\r\n  \r\n    // Split lines while there are lines left to split.\r\n    for (var i = 0;  // Number of lines that have been split so far.\r\n         i < listItems.length;  // length updated by breakAfter calls.\r\n         ++i) {\r\n      walk(listItems[i]);\r\n    }\r\n  \r\n    // Make sure numeric indices show correctly.\r\n    if (opt_startLineNum === (opt_startLineNum|0)) {\r\n      listItems[0].setAttribute('value', opt_startLineNum);\r\n    }\r\n  \r\n    var ol = document.createElement('ol');\r\n    ol.className = 'linenums';\r\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\r\n    for (var i = 0, n = listItems.length; i < n; ++i) {\r\n      li = listItems[i];\r\n      // Stick a class on the LIs so that stylesheets can\r\n      // color odd/even rows, or any other row pattern that\r\n      // is co-prime with 10.\r\n      li.className = 'L' + ((i + offset) % 10);\r\n      if (!li.firstChild) {\r\n        li.appendChild(document.createTextNode('\\xA0'));\r\n      }\r\n      ol.appendChild(li);\r\n    }\r\n  \r\n    node.appendChild(ol);\r\n  }\r\n  /**\r\n   * Breaks {@code job.sourceCode} around style boundaries in\r\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\r\n   * @param {Object} job like <pre>{\r\n   *    sourceCode: {string} source as plain text,\r\n   *    sourceNode: {HTMLElement} the element containing the source,\r\n   *    spans: {Array.<number|Node>} alternating span start indices into source\r\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\r\n   *       span.\r\n   *    decorations: {Array.<number|string} an array of style classes preceded\r\n   *       by the position at which they start in job.sourceCode in order\r\n   * }</pre>\r\n   * @private\r\n   */\r\n  function recombineTagsAndDecorations(job) {\r\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\r\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\r\n    var newlineRe = /\\n/g;\r\n  \r\n    var source = job.sourceCode;\r\n    var sourceLength = source.length;\r\n    // Index into source after the last code-unit recombined.\r\n    var sourceIndex = 0;\r\n  \r\n    var spans = job.spans;\r\n    var nSpans = spans.length;\r\n    // Index into spans after the last span which ends at or before sourceIndex.\r\n    var spanIndex = 0;\r\n  \r\n    var decorations = job.decorations;\r\n    var nDecorations = decorations.length;\r\n    // Index into decorations after the last decoration which ends at or before\r\n    // sourceIndex.\r\n    var decorationIndex = 0;\r\n  \r\n    // Remove all zero-length decorations.\r\n    decorations[nDecorations] = sourceLength;\r\n    var decPos, i;\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      if (decorations[i] !== decorations[i + 2]) {\r\n        decorations[decPos++] = decorations[i++];\r\n        decorations[decPos++] = decorations[i++];\r\n      } else {\r\n        i += 2;\r\n      }\r\n    }\r\n    nDecorations = decPos;\r\n  \r\n    // Simplify decorations.\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      var startPos = decorations[i];\r\n      // Conflate all adjacent decorations that use the same style.\r\n      var startDec = decorations[i + 1];\r\n      var end = i + 2;\r\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\r\n        end += 2;\r\n      }\r\n      decorations[decPos++] = startPos;\r\n      decorations[decPos++] = startDec;\r\n      i = end;\r\n    }\r\n  \r\n    nDecorations = decorations.length = decPos;\r\n  \r\n    var sourceNode = job.sourceNode;\r\n    var oldDisplay;\r\n    if (sourceNode) {\r\n      oldDisplay = sourceNode.style.display;\r\n      sourceNode.style.display = 'none';\r\n    }\r\n    try {\r\n      var decoration = null;\r\n      while (spanIndex < nSpans) {\r\n        var spanStart = spans[spanIndex];\r\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\r\n  \r\n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\r\n  \r\n        var end = Math.min(spanEnd, decEnd);\r\n  \r\n        var textNode = spans[spanIndex + 1];\r\n        var styledText;\r\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\r\n            // Don't introduce spans around empty text nodes.\r\n            && (styledText = source.substring(sourceIndex, end))) {\r\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\r\n          // code to display with spaces instead of line breaks.\r\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\r\n          // space to appear at the beginning of every line but the first.\r\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\r\n          if (isIE8OrEarlier) {\r\n            styledText = styledText.replace(newlineRe, '\\r');\r\n          }\r\n          textNode.nodeValue = styledText;\r\n          var document = textNode.ownerDocument;\r\n          var span = document.createElement('span');\r\n          span.className = decorations[decorationIndex + 1];\r\n          var parentNode = textNode.parentNode;\r\n          parentNode.replaceChild(span, textNode);\r\n          span.appendChild(textNode);\r\n          if (sourceIndex < spanEnd) {  // Split off a text node.\r\n            spans[spanIndex + 1] = textNode\r\n                // TODO: Possibly optimize by using '' if there's no flicker.\r\n                = document.createTextNode(source.substring(end, spanEnd));\r\n            parentNode.insertBefore(textNode, span.nextSibling);\r\n          }\r\n        }\r\n  \r\n        sourceIndex = end;\r\n  \r\n        if (sourceIndex >= spanEnd) {\r\n          spanIndex += 2;\r\n        }\r\n        if (sourceIndex >= decEnd) {\r\n          decorationIndex += 2;\r\n        }\r\n      }\r\n    } finally {\r\n      if (sourceNode) {\r\n        sourceNode.style.display = oldDisplay;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Maps language-specific file extensions to handlers. */\r\n  var langHandlerRegistry = {};\r\n  /** Register a language handler for the given file extensions.\r\n    * @param {function (Object)} handler a function from source code to a list\r\n    *      of decorations.  Takes a single argument job which describes the\r\n    *      state of the computation.   The single parameter has the form\r\n    *      {@code {\r\n    *        sourceCode: {string} as plain text.\r\n    *        decorations: {Array.<number|string>} an array of style classes\r\n    *                     preceded by the position at which they start in\r\n    *                     job.sourceCode in order.\r\n    *                     The language handler should assigned this field.\r\n    *        basePos: {int} the position of source in the larger source chunk.\r\n    *                 All positions in the output decorations array are relative\r\n    *                 to the larger source chunk.\r\n    *      } }\r\n    * @param {Array.<string>} fileExtensions\r\n    */\r\n  function registerLangHandler(handler, fileExtensions) {\r\n    for (var i = fileExtensions.length; --i >= 0;) {\r\n      var ext = fileExtensions[i];\r\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\r\n        langHandlerRegistry[ext] = handler;\r\n      } else if (win['console']) {\r\n        console['warn']('cannot override language handler %s', ext);\r\n      }\r\n    }\r\n  }\r\n  function langHandlerForExtension(extension, source) {\r\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\r\n      // Treat it as markup if the first non whitespace character is a < and\r\n      // the last non-whitespace character is a >.\r\n      extension = /^\\s*</.test(source)\r\n          ? 'default-markup'\r\n          : 'default-code';\r\n    }\r\n    return langHandlerRegistry[extension];\r\n  }\r\n  registerLangHandler(decorateSource, ['default-code']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [],\r\n          [\r\n           [PR_PLAIN,       /^[^<?]+/],\r\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\r\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\r\n           // Unescaped content in an unknown language\r\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\r\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\r\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\r\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\r\n           // Unescaped content in javascript.  (Or possibly vbscript).\r\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\r\n           // Contains unescaped stylesheet content\r\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\r\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\r\n          ]),\r\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [\r\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\r\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\r\n           ],\r\n          [\r\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\r\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\r\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\r\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\r\n           ]),\r\n      ['in.tag']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CPP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'types': C_TYPES\r\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': 'null,true,false'\r\n        }), ['json']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CSHARP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'verbatimStrings': true,\r\n          'types': C_TYPES\r\n        }), ['cs']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JAVA_KEYWORDS,\r\n          'cStyleComments': true\r\n        }), ['java']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': SH_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true\r\n        }), ['bash', 'bsh', 'csh', 'sh']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PYTHON_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'tripleQuotedStrings': true\r\n        }), ['cv', 'py', 'python']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PERL_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': 2  // multiline regex literals\r\n        }), ['perl', 'pl', 'pm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUBY_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': true\r\n        }), ['rb', 'ruby']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JSCRIPT_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'regexLiterals': true\r\n        }), ['javascript', 'js']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': COFFEE_KEYWORDS,\r\n          'hashComments': 3,  // ### style block comments\r\n          'cStyleComments': true,\r\n          'multilineStrings': true,\r\n          'tripleQuotedStrings': true,\r\n          'regexLiterals': true\r\n        }), ['coffee']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUST_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'multilineStrings': true\r\n        }), ['rc', 'rs', 'rust']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\r\n\r\n  function applyDecorator(job) {\r\n    var opt_langExtension = job.langExtension;\r\n\r\n    try {\r\n      // Extract tags, and convert the source code to plain text.\r\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\r\n      /** Plain text. @type {string} */\r\n      var source = sourceAndSpans.sourceCode;\r\n      job.sourceCode = source;\r\n      job.spans = sourceAndSpans.spans;\r\n      job.basePos = 0;\r\n\r\n      // Apply the appropriate language handler\r\n      langHandlerForExtension(opt_langExtension, source)(job);\r\n\r\n      // Integrate the decorations and tags back into the source code,\r\n      // modifying the sourceNode in place.\r\n      recombineTagsAndDecorations(job);\r\n    } catch (e) {\r\n      if (win['console']) {\r\n        console['log'](e && e['stack'] || e);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Pretty print a chunk of code.\r\n   * @param sourceCodeHtml {string} The HTML to pretty print.\r\n   * @param opt_langExtension {string} The language name to use.\r\n   *     Typically, a filename extension like 'cpp' or 'java'.\r\n   * @param opt_numberLines {number|boolean} True to number lines,\r\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n   */\r\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\r\n    var container = document.createElement('div');\r\n    // This could cause images to load and onload listeners to fire.\r\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\r\n    // We assume that the inner HTML is from a trusted source.\r\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\r\n    // when it is injected into a <pre> tag.\r\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\r\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\r\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\r\n    container = container.firstChild;\r\n    if (opt_numberLines) {\r\n      numberLines(container, opt_numberLines, true);\r\n    }\r\n\r\n    var job = {\r\n      langExtension: opt_langExtension,\r\n      numberLines: opt_numberLines,\r\n      sourceNode: container,\r\n      pre: 1\r\n    };\r\n    applyDecorator(job);\r\n    return container.innerHTML;\r\n  }\r\n\r\n   /**\r\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n    * {@code class=prettyprint} and prettify them.\r\n    *\r\n    * @param {Function} opt_whenDone called when prettifying is done.\r\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n    *   containing all the elements to pretty print.\r\n    *   Defaults to {@code document.body}.\r\n    */\r\n  function $prettyPrint(opt_whenDone, opt_root) {\r\n    var root = opt_root || document.body;\r\n    var doc = root.ownerDocument || document;\r\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\r\n    // fetch a list of nodes to rewrite\r\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\r\n    var elements = [];\r\n    for (var i = 0; i < codeSegments.length; ++i) {\r\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\r\n        elements.push(codeSegments[i][j]);\r\n      }\r\n    }\r\n    codeSegments = null;\r\n\r\n    var clock = Date;\r\n    if (!clock['now']) {\r\n      clock = { 'now': function () { return +(new Date); } };\r\n    }\r\n\r\n    // The loop is broken into a series of continuations to make sure that we\r\n    // don't make the browser unresponsive when rewriting a large page.\r\n    var k = 0;\r\n    var prettyPrintingJob;\r\n\r\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\r\n    var prettyPrintRe = /\\bprettyprint\\b/;\r\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\r\n    var preformattedTagNameRe = /pre|xmp/i;\r\n    var codeRe = /^code$/i;\r\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\r\n    var EMPTY = {};\r\n\r\n    function doWork() {\r\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\r\n                     clock['now']() + 250 /* ms */ :\r\n                     Infinity);\r\n      for (; k < elements.length && clock['now']() < endTime; k++) {\r\n        var cs = elements[k];\r\n\r\n        // Look for a preceding comment like\r\n        // <?prettify lang=\"...\" linenums=\"...\"?>\r\n        var attrs = EMPTY;\r\n        {\r\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\r\n            var nt = preceder.nodeType;\r\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\r\n            // like <!--?foo?-->, but in XML is a processing instruction\r\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\r\n            if (value\r\n                ? !/^\\??prettify\\b/.test(value)\r\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\r\n              // Skip over white-space text nodes but not others.\r\n              break;\r\n            }\r\n            if (value) {\r\n              attrs = {};\r\n              value.replace(\r\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\r\n                function (_, name, value) { attrs[name] = value; });\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        var className = cs.className;\r\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\r\n            // Don't redo this if we've already done it.\r\n            // This allows recalling pretty print to just prettyprint elements\r\n            // that have been added to the page since last call.\r\n            && !prettyPrintedRe.test(className)) {\r\n\r\n          // make sure this is not nested in an already prettified element\r\n          var nested = false;\r\n          for (var p = cs.parentNode; p; p = p.parentNode) {\r\n            var tn = p.tagName;\r\n            if (preCodeXmpRe.test(tn)\r\n                && p.className && prettyPrintRe.test(p.className)) {\r\n              nested = true;\r\n              break;\r\n            }\r\n          }\r\n          if (!nested) {\r\n            // Mark done.  If we fail to prettyprint for whatever reason,\r\n            // we shouldn't try again.\r\n            cs.className += ' prettyprinted';\r\n\r\n            // If the classes includes a language extensions, use it.\r\n            // Language extensions can be specified like\r\n            //     <pre class=\"prettyprint lang-cpp\">\r\n            // the language extension \"cpp\" is used to find a language handler\r\n            // as passed to PR.registerLangHandler.\r\n            // HTML5 recommends that a language be specified using \"language-\"\r\n            // as the prefix instead.  Google Code Prettify supports both.\r\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\r\n            var langExtension = attrs['lang'];\r\n            if (!langExtension) {\r\n              langExtension = className.match(langExtensionRe);\r\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\r\n              var wrapper;\r\n              if (!langExtension && (wrapper = childContentWrapper(cs))\r\n                  && codeRe.test(wrapper.tagName)) {\r\n                langExtension = wrapper.className.match(langExtensionRe);\r\n              }\r\n\r\n              if (langExtension) { langExtension = langExtension[1]; }\r\n            }\r\n\r\n            var preformatted;\r\n            if (preformattedTagNameRe.test(cs.tagName)) {\r\n              preformatted = 1;\r\n            } else {\r\n              var currentStyle = cs['currentStyle'];\r\n              var defaultView = doc.defaultView;\r\n              var whitespace = (\r\n                  currentStyle\r\n                  ? currentStyle['whiteSpace']\r\n                  : (defaultView\r\n                     && defaultView.getComputedStyle)\r\n                  ? defaultView.getComputedStyle(cs, null)\r\n                  .getPropertyValue('white-space')\r\n                  : 0);\r\n              preformatted = whitespace\r\n                  && 'pre' === whitespace.substring(0, 3);\r\n            }\r\n\r\n            // Look for a class like linenums or linenums:<n> where <n> is the\r\n            // 1-indexed number of the first line.\r\n            var lineNums = attrs['linenums'];\r\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\r\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\r\n              lineNums =\r\n                lineNums\r\n                ? lineNums[1] && lineNums[1].length\r\n                  ? +lineNums[1] : true\r\n                : false;\r\n            }\r\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\r\n\r\n            // do the pretty printing\r\n            prettyPrintingJob = {\r\n              langExtension: langExtension,\r\n              sourceNode: cs,\r\n              numberLines: lineNums,\r\n              pre: preformatted\r\n            };\r\n            applyDecorator(prettyPrintingJob);\r\n          }\r\n        }\r\n      }\r\n      if (k < elements.length) {\r\n        // finish up in a continuation\r\n        setTimeout(doWork, 250);\r\n      } else if ('function' === typeof opt_whenDone) {\r\n        opt_whenDone();\r\n      }\r\n    }\r\n\r\n    doWork();\r\n  }\r\n\r\n  /**\r\n   * Contains functions for creating and registering new language handlers.\r\n   * @type {Object}\r\n   */\r\n  var PR = win['PR'] = {\r\n        'createSimpleLexer': createSimpleLexer,\r\n        'registerLangHandler': registerLangHandler,\r\n        'sourceDecorator': sourceDecorator,\r\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\r\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\r\n        'PR_COMMENT': PR_COMMENT,\r\n        'PR_DECLARATION': PR_DECLARATION,\r\n        'PR_KEYWORD': PR_KEYWORD,\r\n        'PR_LITERAL': PR_LITERAL,\r\n        'PR_NOCODE': PR_NOCODE,\r\n        'PR_PLAIN': PR_PLAIN,\r\n        'PR_PUNCTUATION': PR_PUNCTUATION,\r\n        'PR_SOURCE': PR_SOURCE,\r\n        'PR_STRING': PR_STRING,\r\n        'PR_TAG': PR_TAG,\r\n        'PR_TYPE': PR_TYPE,\r\n        'prettyPrintOne':\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\r\n             : (prettyPrintOne = $prettyPrintOne),\r\n        'prettyPrint': prettyPrint =\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrint'] = $prettyPrint)\r\n             : (prettyPrint = $prettyPrint)\r\n      };\r\n\r\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\r\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\r\n  // The Asynchronous Module Definition (AMD) API specifies a\r\n  // mechanism for defining modules such that the module and its\r\n  // dependencies can be asynchronously loaded.\r\n  // ...\r\n  // To allow a clear indicator that a global define function (as\r\n  // needed for script src browser loading) conforms to the AMD API,\r\n  // any global define function SHOULD have a property called \"amd\"\r\n  // whose value is an object. This helps avoid conflict with any\r\n  // other existing JavaScript code that could have defined a define()\r\n  // function that does not conform to the AMD API.\r\n  if (typeof define === \"function\" && define['amd']) {\r\n    define(\"google-code-prettify\", [], function () {\r\n      return PR; \r\n    });\r\n  }\r\n})();\r\n\ndefine(\"prettify\", function(){});\n\n",
        +    "define('itemView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/item.html',\r\n  'text!tpl/class.html',\r\n  'text!tpl/itemEnd.html',\r\n  // Tools\r\n  'prettify'\r\n], function(App, itemTpl, classTpl, endTpl) {\r\n  'use strict';\r\n\r\n  var appVersion = App.project.version || 'master';\r\n\r\n  var itemView = Backbone.View.extend({\r\n    el: '#item',\r\n    init: function() {\r\n      this.$html = $('html');\r\n      this.$body = $('body');\r\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\r\n\r\n      this.tpl = _.template(itemTpl);\r\n      this.classTpl = _.template(classTpl);\r\n      this.endTpl = _.template(endTpl);\r\n\r\n      return this;\r\n    },\r\n    getSyntax: function(isMethod, cleanItem) {\r\n      var isConstructor = cleanItem.is_constructor;\r\n      var syntax = '';\r\n      if (isConstructor) {\r\n        syntax += 'new ';\r\n      } else if (cleanItem.static && cleanItem.class) {\r\n        syntax += cleanItem.class + '.';\r\n      }\r\n      syntax += cleanItem.name;\r\n\r\n      if (isMethod || isConstructor) {\r\n        syntax += '(';\r\n        if (cleanItem.params) {\r\n          for (var i = 0; i < cleanItem.params.length; i++) {\r\n            var p = cleanItem.params[i];\r\n            if (p.optional) {\r\n              syntax += '[';\r\n            }\r\n            syntax += p.name;\r\n            if (p.optdefault) {\r\n              syntax += '=' + p.optdefault;\r\n            }\r\n            if (p.optional) {\r\n              syntax += ']';\r\n            }\r\n            if (i !== cleanItem.params.length - 1) {\r\n              syntax += ', ';\r\n            }\r\n          }\r\n        }\r\n        syntax += ')';\r\n      }\r\n\r\n      return syntax;\r\n    },\r\n    // Return a list of valid syntaxes across all overloaded versions of\r\n    // this item.\r\n    //\r\n    // For reference, we ultimately want to replicate something like this:\r\n    //\r\n    // https://processing.org/reference/color_.html\r\n    getSyntaxes: function(isMethod, cleanItem) {\r\n      var overloads = cleanItem.overloads || [cleanItem];\r\n      return overloads.map(this.getSyntax.bind(this, isMethod));\r\n    },\r\n    render: function(item) {\r\n      if (item) {\r\n        var itemHtml = '';\r\n        var cleanItem = this.clean(item);\r\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\r\n        var collectionName = isClass\r\n            ? 'Constructor'\r\n            : this.capitalizeFirst(cleanItem.itemtype),\r\n          isConstructor = cleanItem.is_constructor;\r\n        cleanItem.isMethod = collectionName === 'Method';\r\n\r\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\r\n\r\n        // Set the item header (title)\r\n\r\n        // Set item contents\r\n        if (isClass) {\r\n          var constructor = this.tpl({\r\n            item: cleanItem,\r\n            isClass: true,\r\n            isConstructor: isConstructor,\r\n            syntaxes: syntaxes\r\n          });\r\n          cleanItem.constructor = constructor;\r\n\r\n          var contents = _.find(App.classes, function(c) {\r\n            return c.name === cleanItem.name;\r\n          });\r\n          cleanItem.things = contents.items;\r\n\r\n          itemHtml = this.classTpl(cleanItem);\r\n        } else {\r\n          cleanItem.constRefs =\r\n            item.module === 'Constants' && App.data.consts[item.name];\r\n\r\n          itemHtml = this.tpl({\r\n            item: cleanItem,\r\n            isClass: false,\r\n            isConstructor: false,\r\n            syntaxes: syntaxes\r\n          });\r\n        }\r\n\r\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\r\n\r\n        // Insert the view in the dom\r\n        this.$el.html(itemHtml);\r\n\r\n        renderCode(cleanItem.name);\r\n\r\n        // Set the document title based on the item name.\r\n        // If it is a method, add parentheses to the name\r\n        if (item.itemtype === 'method') {\r\n          App.pageView.appendToDocumentTitle(item.name + '()');\r\n        } else {\r\n          App.pageView.appendToDocumentTitle(item.name);\r\n        }\r\n\r\n        // Hook up alt-text for examples\r\n        setTimeout(function() {\r\n          var alts = $('.example-content')[0];\r\n          if (alts) {\r\n            alts = $(alts)\r\n              .data('alt')\r\n              .split('\\n');\r\n\r\n            var canvases = $('.cnv_div');\r\n            for (var j = 0; j < alts.length; j++) {\r\n              if (j < canvases.length) {\r\n                $(canvases[j]).append(\r\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\r\n                );\r\n              }\r\n            }\r\n          }\r\n        }, 1000);\r\n        Prism.highlightAll();\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Clean item properties: url encode properties containing paths.\r\n     * @param {object} item The item object.\r\n     * @returns {object} Returns the same item object with urlencoded paths.\r\n     */\r\n    clean: function(item) {\r\n      var cleanItem = item;\r\n\r\n      if (cleanItem.hasOwnProperty('file')) {\r\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\r\n      }\r\n      return cleanItem;\r\n    },\r\n    /**\r\n     * Show a single item.\r\n     * @param {object} item Item object.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function(item) {\r\n      if (item) {\r\n        this.render(item);\r\n      }\r\n\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      this.scrollTop();\r\n      $('#item').focus();\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a message if no item is found.\r\n     * @returns {object} This view.\r\n     */\r\n    nothingFound: function() {\r\n      this.$el.html(\r\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\r\n      );\r\n      App.pageView.hideContentViews();\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Scroll to the top of the window with an animation.\r\n     */\r\n    scrollTop: function() {\r\n      // Hack for Chrome/Firefox scroll animation\r\n      // Chrome scrolls 'body', Firefox scrolls 'html'\r\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\r\n      if (scroll) {\r\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\r\n      }\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function(str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n  });\r\n\r\n  return itemView;\r\n});\r\n\n",
        +    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\r\\n  <br>\\r\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\r\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\r\\n</div>\\r\\n\\r\\n<div id=\\'collection-list-categories\\'>\\r\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\r\\n<% var i=0; %>\\r\\n<% var max=Math.floor(groups.length/4); %>\\r\\n<% var rem=groups.length%4; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% var m = rem > 0 ? 1 : 0 %>\\r\\n  <% if (i === 0) { %>\\r\\n    <ul aria-labelledby=\"categories\">\\r\\n    <% } %>\\r\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\r\\n    <% if (i === (max+m-1)) { %>\\r\\n    </ul>\\r\\n  \\t<% rem-- %>\\r\\n  \\t<% i=0 %>\\r\\n  <% } else { %>\\r\\n  \\t<% i++ %>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        +    "define('menuView',[\r\n  'App',\r\n  'text!tpl/menu.html'\r\n], function(App, menuTpl) {\r\n\r\n  var menuView = Backbone.View.extend({\r\n    el: '#collection-list-nav',\r\n    /**\r\n     * Init.\r\n     * @returns {object} This view.\r\n     */\r\n    init: function() {\r\n      this.menuTpl = _.template(menuTpl);\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     * @returns {object} This view.\r\n     */\r\n    render: function() {\r\n\r\n      var groups = [];\r\n      _.each(App.modules, function (item, i) {\r\n        if (!item.is_submodule) {\r\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n            groups.push(item.name);\r\n          }\r\n        }\r\n        //}\r\n      });\r\n\r\n      // Sort groups by name A-Z\r\n      groups.sort();\r\n\r\n      var menuHtml = this.menuTpl({\r\n        'groups': groups\r\n      });\r\n\r\n      // Render the view\r\n      this.$el.html(menuHtml);\r\n    },\r\n\r\n    hide: function() {\r\n      this.$el.hide();\r\n    },\r\n\r\n    show: function() {\r\n      this.$el.show();\r\n    },\r\n\r\n    /**\r\n     * Update the menu.\r\n     * @param {string} el The name of the current route.\r\n     */\r\n    update: function(menuItem) {\r\n      //console.log(menuItem);\r\n      // this.$menuItems.removeClass('active');\r\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\r\n\r\n    }\r\n  });\r\n\r\n  return menuView;\r\n\r\n});\r\n\n",
        +    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\r\\n\\r\\n<p><%= module.description %></p>\\r\\n\\r\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\r\\n\\r\\n<% var t = 0; col = 0; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% if (t == 0) { %> \\r\\n    <div class=\"column_<%=col%>\">\\r\\n  <% } %>\\r\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\r\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\r\\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\r\\n    <% if (group.hash) { %> </a> <% } %>\\r\\n  <% } %>\\r\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\r\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\r\\n    <% t++; %>\\r\\n  <% }); %>\\r\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\r\\n    </div>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        +    "define(\r\n  'libraryView',[\r\n    'App',\r\n    // Templates\r\n    'text!tpl/library.html'\r\n  ],\r\n  function(App, libraryTpl) {\r\n    var libraryView = Backbone.View.extend({\r\n      el: '#list',\r\n      events: {},\r\n      /**\r\n       * Init.\r\n       */\r\n      init: function() {\r\n        this.libraryTpl = _.template(libraryTpl);\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Render the list.\r\n       */\r\n      render: function(m, listCollection) {\r\n        if (m && listCollection) {\r\n          var self = this;\r\n\r\n          // Render items and group them by module\r\n          // module === group\r\n          this.groups = {};\r\n          _.each(m.items, function(item, i) {\r\n            var module = item.module || '_';\r\n            var group;\r\n            // Override default group with a selected category\r\n            // TODO: Overwriting with the first category might not be the best choice\r\n            // We might also want to have links for categories\r\n            if (item.category && item.category[0]) {\r\n              group = item.category[0];\r\n              // Populate item.hash\r\n              App.router.getHash(item);\r\n\r\n              // Create a group list without link hash\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: undefined,\r\n                  items: []\r\n                };\r\n              }\r\n            } else {\r\n              group = item.class || '_';\r\n              var hash = App.router.getHash(item);\r\n\r\n              var ind = hash.lastIndexOf('/');\r\n              hash = hash.substring(0, ind);\r\n\r\n              // Create a group list\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: hash,\r\n                  items: []\r\n                };\r\n              }\r\n            }\r\n\r\n            self.groups[group].items.push(item);\r\n          });\r\n\r\n          // Sort groups by name A-Z\r\n          self.groups = _.sortBy(self.groups, this.sortByName);\r\n\r\n          // Put the <li> items html into the list <ul>\r\n          var libraryHtml = self.libraryTpl({\r\n            title: self.capitalizeFirst(listCollection),\r\n            module: m.module,\r\n            totalItems: m.items.length,\r\n            groups: self.groups\r\n          });\r\n\r\n          // Render the view\r\n          this.$el.html(libraryHtml);\r\n        }\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Show a list of items.\r\n       * @param {array} items Array of item objects.\r\n       * @returns {object} This view.\r\n       */\r\n      show: function(listGroup) {\r\n        if (App[listGroup]) {\r\n          this.render(App[listGroup], listGroup);\r\n        }\r\n        App.pageView.hideContentViews();\r\n\r\n        this.$el.show();\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Helper method to capitalize the first letter of a string\r\n       * @param {string} str\r\n       * @returns {string} Returns the string.\r\n       */\r\n      capitalizeFirst: function(str) {\r\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n      },\r\n      /**\r\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\r\n       * @param {string} a\r\n       * @param {string} b\r\n       * @returns {Array} Returns an array with elements sorted from A to Z.\r\n       */\r\n      sortAZ: function(a, b) {\r\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\r\n      },\r\n\r\n      sortByName: function(a, b) {\r\n        if (a.name === 'p5') return -1;\r\n        else return 0;\r\n      }\r\n    });\r\n\r\n    return libraryView;\r\n  }\r\n);\r\n\n",
        +    "define('pageView',[\r\n  'App',\r\n\r\n  // Views\r\n  'searchView',\r\n  'listView',\r\n  'itemView',\r\n  'menuView',\r\n  'libraryView'\r\n], function(App, searchView, listView, itemView, menuView, libraryView) {\r\n\r\n  // Store the original title parts so we can substitue different endings.\r\n  var _originalDocumentTitle = window.document.title;\r\n\r\n  var pageView = Backbone.View.extend({\r\n    el: 'body',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      App.$container = $('#container');\r\n      App.contentViews = [];\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     */\r\n    render: function() {\r\n\r\n      // Menu view\r\n      if (!App.menuView) {\r\n        App.menuView = new menuView();\r\n        App.menuView.init().render();\r\n      }\r\n\r\n      // Item view\r\n      if (!App.itemView) {\r\n        App.itemView = new itemView();\r\n        App.itemView.init().render();\r\n        // Add the item view to the views array\r\n        App.contentViews.push(App.itemView);\r\n      }\r\n\r\n      // List view\r\n      if (!App.listView) {\r\n        App.listView = new listView();\r\n        App.listView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.listView);\r\n      }\r\n\r\n      // Library view\r\n      if (!App.libraryView) {\r\n        App.libraryView = new libraryView();\r\n        App.libraryView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.libraryView);\r\n      }\r\n\r\n      // Search\r\n      if (!App.searchView) {\r\n        App.searchView = new searchView();\r\n        App.searchView.init().render();\r\n      }\r\n      return this;\r\n    },\r\n    /**\r\n     * Hide item and list views.\r\n     * @returns {object} This view.\r\n     */\r\n    hideContentViews: function() {\r\n      _.each(App.contentViews, function(view, i) {\r\n        view.$el.hide();\r\n      });\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Append the supplied name to the first part of original document title.\r\n     * If no name is supplied, the title will reset to the original one.\r\n     */\r\n    appendToDocumentTitle: function(name){\r\n      if(name){\r\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\r\n        window.document.title = [firstTitlePart, name].join(\" | \");\r\n      } else {\r\n        window.document.title = _originalDocumentTitle;\r\n      }\r\n    }    \r\n  });\r\n\r\n  return pageView;\r\n\r\n});\r\n\n",
        +    "define('router',[\r\n  'App'\r\n], function(App) {\r\n\r\n  'use strict'; //\r\n\r\n  var Router = Backbone.Router.extend({\r\n\r\n    routes: {\r\n      '': 'list',\r\n      'p5': 'list',\r\n      'p5/': 'list',\r\n      'classes': 'list',\r\n      'search': 'search',\r\n      'libraries/:lib': 'library',\r\n      ':searchClass(/:searchItem)': 'get'\r\n    },\r\n    /**\r\n     * Whether the json API data was loaded.\r\n     */\r\n    _initialized: false,\r\n    /**\r\n     * Initialize the app: load json API data and create searchable arrays.\r\n     */\r\n    init: function(callback) {\r\n      var self = this;\r\n      require(['pageView'], function(pageView) {\r\n\r\n        // If already initialized, move away from here!\r\n        if (self._initialized) {\r\n          if (callback)\r\n            callback();\r\n          return;\r\n        }\r\n\r\n        // Update initialization state: must be done now to avoid recursive mess\r\n        self._initialized = true;\r\n\r\n        // Render views\r\n        if (!App.pageView) {\r\n          App.pageView = new pageView();\r\n          App.pageView.init().render();\r\n        }\r\n\r\n        // If a callback is set (a route has already been called), run it\r\n        // otherwise, show the default list\r\n        if (callback)\r\n          callback();\r\n        else\r\n          self.list();\r\n      });\r\n    },\r\n    /**\r\n     * Start route. Simply check if initialized.\r\n     */\r\n    start: function() {\r\n      this.init();\r\n    },\r\n    /**\r\n     * Show item details by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     */\r\n    get: function(searchClass, searchItem) {\r\n\r\n      // if looking for a library page, redirect\r\n      if (searchClass === 'p5.sound' && !searchItem) {\r\n        window.location.hash = '/libraries/'+searchClass;\r\n        return;\r\n      }\r\n\r\n      var self = this;\r\n      this.init(function() {\r\n        var item = self.getItem(searchClass, searchItem);\r\n\r\n        App.menuView.hide();\r\n\r\n        if (item) {\r\n          App.itemView.show(item);\r\n        } else {\r\n          //App.itemView.nothingFound();\r\n\r\n          self.list();\r\n        }\r\n\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Returns one item object by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     * @returns {object} The item found or undefined if nothing was found.\r\n     */\r\n    getItem: function(searchClass, searchItem) {\r\n      var classes = App.classes,\r\n              items = App.allItems,\r\n              classesCount = classes.length,\r\n              itemsCount = items.length,\r\n              className = searchClass ? searchClass.toLowerCase() : undefined,\r\n              itemName = searchItem ? searchItem : undefined,\r\n              found;\r\n\r\n      // Only search for a class, if itemName is undefined\r\n      if (className && !itemName) {\r\n        for (var i = 0; i < classesCount; i++) {\r\n          if (classes[i].name.toLowerCase() === className) {\r\n            found = classes[i];\r\n            _.each(found.items, function(i, idx) {\r\n              i.hash = App.router.getHash(i);\r\n            });\r\n            break;\r\n          }\r\n        }\r\n        // Search for a class item\r\n      } else if (className && itemName) {\r\n        // Search case sensitively\r\n        for (var i = 0; i < itemsCount; i++) {\r\n          if (items[i].class.toLowerCase() === className &&\r\n            items[i].name === itemName) {\r\n            found = items[i];\r\n            break;\r\n          }\r\n        }\r\n\r\n        // If no match was found, fallback to search case insensitively\r\n        if(!found){\r\n          for (var i = 0; i < itemsCount; i++) {\r\n            if(items[i].class.toLowerCase() === className &&\r\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\r\n              found = items[i];\r\n              break;\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      return found;\r\n    },\r\n    /**\r\n     * List items.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    list: function(collection) {\r\n\r\n      collection = 'allItems';\r\n\r\n      // Make sure collection is valid\r\n      if (App.collections.indexOf(collection) < 0) {\r\n        return;\r\n      }\r\n\r\n      this.init(function() {\r\n        App.menuView.show(collection);\r\n        App.menuView.update(collection);\r\n        App.listView.show(collection);\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Display information for a library.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    library: function(collection) {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.libraryView.show(collection.substring(3)); //remove p5.\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Close all content views.\r\n     */\r\n    search: function() {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.pageView.hideContentViews();\r\n      });\r\n    },\r\n\r\n    /**\r\n     * Create an hash/url for the item.\r\n     * @param {Object} item A class, method, property or event object.\r\n     * @returns {String} The hash string, including the '#'.\r\n     */\r\n     getHash: function(item) {\r\n\r\n       if (!item.hash) {\r\n\r\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\r\n\r\n         if (item.class) {\r\n           var clsFunc = '#/' + item.class + '.' + item.name;\r\n           var idx = clsFunc.lastIndexOf('.');\r\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\r\n         } else {\r\n          item.hash = '#/' + item.name;\r\n         }\r\n       }\r\n\r\n       return item.hash;\r\n    }\r\n  });\r\n\r\n  \r\n  function styleCodeLinks() {\r\n    var links = document.getElementsByTagName(\"a\");\r\n    for (var iLink = 0; iLink < links.length; iLink++) {\r\n      var link = links[iLink];\r\n      if (link.hash.startsWith('#/p5')) {\r\n        link.classList.add('code');\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n  // Get the router\r\n  App.router = new Router();\r\n\r\n  // Start history\r\n  Backbone.history.start();\r\n\r\n  return App.router;\r\n\r\n});\r\n\n",
        +    "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
             "}());"
           ]
         }
        \ No newline at end of file
        diff --git a/src/templates/pages/reference/index.html b/src/templates/pages/reference/index.html
        new file mode 100644
        index 0000000000..133d930e39
        --- /dev/null
        +++ b/src/templates/pages/reference/index.html
        @@ -0,0 +1,278 @@
        +<!DOCTYPE html>
        +<html class="no-js" lang="en">
        +  <head>
        +    <meta charset="utf-8">
        +    <meta http-equiv="X-UA-Compatible" content="IE=edge">
        +    <meta name="viewport" content="width=device-width">
        +    <meta name="description" content="p5.js a JS client-side library for creating graphic and interactive experiences, based on the core principles of Processing.">
        +    <title tabindex="1">reference | p5.js</title>
        +    <link rel="stylesheet" href="/../assets/css/all.css">
        +    <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
        +
        +    <link rel="shortcut icon" href="/../assets/img/favicon.ico">
        +    <link rel="icon" href="/../assets/img/favicon.ico">
        +
        +
        +    <script src="/../assets/js/vendor/jquery-1.12.4.min.js"></script>
        +    <script src="/../assets/js/vendor/ace-nc/ace.js"></script>
        +    <script src="/../assets/js/vendor/ace-nc/mode-javascript.js"></script>
        +    <script src="/../assets/js/vendor/prism.js"></script>
        +    <script src="/../assets/js/init.js"></script>
        +
        +
        +    <style>
        +    @font-face {
        +      font-family: myFirstFont;
        +      src: url(assets/p5_featured/nea-p5js/assets/Museo_Slab_500_2.otf);
        +    }
        +    #top {
        +      font-family: myFirstFont !important;
        +      color: white;
        +      font-size: 12px;
        +      padding: 7px;
        +      padding-left: 20px;
        +      line-height: 20px;
        +      background-color: #ED225D;
        +      position: fixed;
        +      bottom: 0;
        +      left: 0;
        +      width: 100%;
        +      z-index: 5;
        +      display: none;
        +    }
        +
        +    #top a {
        +      color: white !important;
        +      text-decoration: underline;
        +    }
        +
        +
        +    footer { padding-bottom: 26px; }
        +    </style>
        +  </head>
        +  <body>
        +
        +    <a href="#content" class="sr-only">Skip to content</a>
        +
        +    <!-- p5*js language buttons -->
        +    <div id="i18n-btn">
        +      <h2 id="i18n-settings" class="sr-only">Language Settings</h2>
        +      <ul id="i18n-buttons" aria-labelledby="i18n-settings">
        +        <li><a href='#' lang='en' data-lang='en'>English</a></li>
        +        <li><a href='#' lang='es' data-lang='es'>Español</a></li>
        +        <li><a href='#' lang='zh-Hans' data-lang='zh-Hans'>简体中文</a></li>
        +      </ul>
        +    </div>    <!-- .container -->
        +    <div class="container">
        +
        +      <!-- logo -->
        +      <header id="lockup">
        +        <a href="/">
        +          <img src="../assets/img/p5js.svg" alt="p5 homepage" id="logo_image" class="logo" />
        +          <div id="p5_logo"></div>
        +        </a>
        +        <p class='tagline'>Processing fun times JavaScript quirkiness</p>
        +        <p class='tagline'>Processing simplicity times JavaScript flexibility</p>
        +        <p class='tagline'>Processing intuition times JavaScript power</p>
        +        <p class='tagline'>Processing creativity times JavaScript dynamism</p>
        +        <p class='tagline'>Processing community times JavaScript community</p>
        +        <p class='tagline'>the power of Processing times the reach of JavaScript</p>
        +      </header>
        +      <!-- close logo -->
        +
        +
        +
        +<div id="reference-page">
        +
        +
        +  <!-- site navigation -->
        +  <div class="column-span">
        +    <nav>
        +      <h2 id="menu-title" class="sr-only">Site Navigation</h2>
        +      <ul id="menu" aria-labelledby="menu-title">
        +        <li><a href="/">Home</a></li>
        +        <li><a href="/download/">Download</a></li>
        +        <li><a href="/get-started/">Get Started</a></li>
        +        <li><a href="/reference/">Reference</a></li>
        +        <li><a href="/libraries/">Libraries</a></li>
        +        <li><a href="/learn/">Learn</a></li>
        +        <li><a href="/examples/">Examples</a></li>
        +        <li><a href="/books/">Books</a></li>
        +        <li><a href="/community/">Community</a></li>
        +        <li><a href="https://discourse.processing.org/c/p5js" target=_blank class="other-link">Forum</a></li>
        +        <li><a href="http://github.com/processing/p5.js" target=_blank class="other-link">GitHub</a></li>
        +        <li><a href="http://twitter.com/p5xjs" target=_blank class="other-link">Twitter</a></li>
        +      </ul>
        +    </nav>
        +  </div>
        +
        +  <div class="column-span">
        +
        +    <main id="content" >
        +      <h1>Reference</h1>
        +
        +      <div id="search" class="search-wrapper" role="search"></div>
        +      <div id="collection-list-nav"></div>
        +
        +          <!--class="container-fluid"-->
        +      <div id="list" tabindex="2" class="list-wrapper allItems-collection"></div>
        +      <div id="item" tabindex="1" class="item-wrapper apidocs"></div>
        +      <div id="file" class="file-wrapper"></div>
        +
        +    </main>
        +
        +
        +    <footer>
        +      <h2 class="sr-only">Credits</h2>
        +      <p> p5.js was created by <a href='http://lauren-mccarthy.com' target="_blank">Lauren McCarthy</a> and is developed by a community of collaborators, with support from the <a href="http://processing.org/foundation/" target="_blank">Processing Foundation</a>  and
        +      <a href="http://itp.nyu.edu/itp/" target="_blank">NYU ITP</a>. Identity and graphic design by <a href="http://jereljohnson.com/" target="_blank">Jerel Johnson</a>. <a href="/copyright.html">&copy; Info.</a></p>
        +    </footer>
        +
        +  </div> <!-- end column-span -->
        +
        +  <script src="//fast.fonts.net/jsapi/5ace315e-3b19-4568-9e85-5bfcb29004c0.js"></script>
        +  <script src='/assets/js/p5.min.js'></script>
        +  <script src='/assets/js/p5.dom.min.js'></script>
        +  <script src='/assets/js/p5.sound.min.js'></script>
        +  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
        +  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
        +  <script src="./assets/js/require.min.js"></script>
        +  <!-- <script src="https://p5js.org/assets/js/render.js"></script> -->
        +  <script src="/assets/js/render.js"></script>
        +  <script src="./assets/js/reference.js"></script>
        +
        +  <script>
        +
        +    var translations;
        +
        +    $(document).ready(function() {
        +      var langs = ['es', 'zh-Hans'];
        +      var routes = window.location.pathname.split('/');
        +      var lang = routes[1];
        +      if (langs.indexOf(lang) != -1) {
        +        $.getJSON('/assets/reference/'+lang+'.json', function(data) {
        +          translations = data;
        +
        +          window.addEventListener('reference-rendered', function() {
        +            console.log("rendered");
        +            updateLanguage();
        +          }, false);
        +        });
        +      }
        +    });
        +
        +    function updateLanguage() {
        +      if (translations) {
        +        // reference title
        +        $('h1').html(translations['h1']);
        +        // reference tagline
        +        $('#reference-tagline').html(translations['reference-tagline']);
        +        // reference tagline
        +        $('#search input').attr('placeholder', translations['reference-search']);
        +        $('#search input').attr('title', translations['reference-search']);
        +        // reference menu
        +        $('#reference-menu-home').html(translations['reference-menu-home']);
        +        $('#reference-menu-download').html(translations['reference-menu-download']);
        +        $('#reference-menu-get-started').html(translations['reference-menu-get-started']);
        +        $('#reference-menu-reference').html(translations['reference-menu-reference']);
        +        $('#reference-menu-libraries').html(translations['reference-menu-libraries']);
        +        $('#reference-menu-learn').html(translations['reference-menu-learn']);
        +        $('#reference-menu-examples').html(translations['reference-menu-examples']);
        +        $('#reference-menu-books').html(translations['reference-menu-books']);
        +        $('#reference-menu-community').html(translations['reference-menu-community']);
        +        $('#reference-menu-forum').html(translations['reference-menu-forum']);
        +        // reference description
        +        $('#reference-description1').html(translations['reference-description1']);
        +        $('#reference-description2').html(translations['reference-description2']);
        +        $('#reference-description3').html(translations['reference-description3']);
        +        $('#reference-description4').html(translations['reference-description4']);
        +        // reference contribute
        +        $('#reference-contribute1').html(translations['reference-contribute1']);
        +        $('#reference-contribute2').html(translations['reference-contribute2']);
        +        // reference error
        +        $('#reference-error1').html(translations['reference-error1']);
        +        $('#reference-error2').html(translations['reference-error2']);
        +        $('#reference-error3').html(translations['reference-error3']);
        +        $('#reference-error4').html(translations['reference-error4']);
        +        $('#reference-error5').html(translations['reference-error5']);
        +        // reference texts
        +        $('#reference-example').html(translations['reference-example']);
        +        $('#reference-description').html(translations['reference-description'])
        +        $('#reference-extends').html(translations['reference-extends']);
        +        $('#reference-parameters').html(translations['reference-parameters']);
        +        $('#reference-syntax').html(translations['reference-syntax']);
        +        $('#reference-returns').html(translations['reference-returns']);
        +        // reference footer
        +        $('#footer1').html(translations['footer1']);
        +        $('#footer2').html(translations['footer2']);
        +        $('#footer3').html(translations['footer3']);
        +        $('#footer4').html(translations['footer4']);
        +        $('.group-name, .subgroup-name').each(function() {
        +          $(this).text(translations[$(this).text()]);
        +        });
        +        var routes = window.location.hash.split('/');
        +        var obj = routes[1];
        +        var name = routes[2];
        +        if (translations[obj] && translations[obj][name]) {
        +          var entry = translations[obj][name];
        +          $('.description-text').html('<p>'+entry.description+'</p>');
        +          $('.returns').html(entry.returns);
        +          $('.params').find('tr').each(function(i) {
        +            if (i < entry.params.length) {
        +              $(this).children('td').eq(1).html(entry.params[i])
        +            }
        +          });
        +        }
        +      }
        +    }
        +    </script>
        +
        +
        +  <!-- outside of column for footer to go across both -->
        +
        +  <p class="clearfix"> &nbsp; </p>
        +
        +  <object type="image/svg+xml" data="../assets/img/thick-asterisk-alone.svg" id="asterisk-design-element" aria-hidden="true">
        +       *<!-- to do: add fallback image in CSS -->
        +  </object>
        +
        +</div><!-- end id="reference-page"  -->
        +
        +
        +    </div> <!-- close class='container'-->
        +
        +
        +    <nav id="family" aria-labelledby="processing-sites-heading">
        +      <h2 id="processing-sites-heading" class="sr-only">Processing Sister Sites</h2>
        +      <ul id="processing-sites" aria-labelledby="processing-sites-heading">
        +        <li><a href="http://processing.org">Processing</a></li>
        +        <li><a class="here" href="/">p5.js</a></li>
        +        <li><a href="http://py.processing.org/">Processing.py</a></li>
        +        <li><a href="http://android.processing.org/">Processing for Android</a></li>
        +        <li><a href="http://pi.processing.org/">Processing for Pi</a></li>
        +        <li><a href="https://processingfoundation.org/">Processing Foundation</a></li>
        +      </ul>
        +
        +    <!--   <p class="right">
        +      </p> -->
        +    </nav>
        +    <script>
        +      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        +    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        +    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        +    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
        +    ga('create', 'UA-53383000-1', 'auto');
        +    ga('send', 'pageview');
        +
        +    $(window).ready(function() {
        +      if (window.location.pathname !== '/' && window.location.pathname !== '/index.html') {
        +        $('#top').remove();
        +      } else {
        +        $('#top').show();
        +      }
        +    });
        +    </script>
        +
        +
        +  </body>
        +</html>
        \ No newline at end of file
        diff --git a/src/templates/partials/i18n.hbs b/src/templates/partials/i18n.hbs
        index cecbc119eb..8f7138ae7d 100644
        --- a/src/templates/partials/i18n.hbs
        +++ b/src/templates/partials/i18n.hbs
        @@ -1,5 +1,5 @@
         ---
        -title: language buttons
        +titne: language buttons
         ---
         <!-- p5*js language buttons -->
         <div id="i18n-btn">
        @@ -8,5 +8,6 @@ title: language buttons
             <li><a href='#' lang='en' data-lang='en'>English</a></li>
             <li><a href='#' lang='es' data-lang='es'>Español</a></li>
             <li><a href='#' lang='zh-Hans' data-lang='zh-Hans'>简体中文</a></li>
        +    <li><a href='#' lang='ko' data-lang='ko'>한국어</a></li>
           </ul>
         </div>
        \ No newline at end of file
        
        From af71b6b3ad164eaed1eb33d3d296b591a5fc5d15 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 25 Apr 2020 20:24:19 +0900
        Subject: [PATCH 10/36] second push to Korean translation with merge conflicts
         fixed
        
        ---
         .../ko/00_Structure/00_Coordinates.js         |  36 -----
         .../ko/00_Structure/01_Width_and_Height.js    |   7 -
         .../ko/00_Structure/02_Setup_and_Draw.js      |  23 ---
         .../examples/ko/00_Structure/03_No_Loop.js    |  24 ---
         src/data/examples/ko/00_Structure/04_Loop.js  |  22 ---
         .../examples/ko/00_Structure/05_Redraw.js     |  18 ---
         .../examples/ko/00_Structure/06_Functions.js  |   7 -
         .../examples/ko/00_Structure/07_Recursion.js  |   7 -
         .../ko/00_Structure/08_Create_Graphics.js     |  11 --
         .../ko/01_Form/00_Points_and_Lines.js         |  19 ---
         src/data/examples/ko/01_Form/02_Pie_Chart.js  |  10 --
         .../examples/ko/01_Form/03_Regular_Polygon.js |   8 -
         src/data/examples/ko/01_Form/04_Star.js       |   7 -
         .../examples/ko/01_Form/05_Triangle_Strip.js  |   7 -
         src/data/examples/ko/01_Form/06_Bezier.js     |  10 +-
         .../examples/ko/01_Form/07_3D_Primitives.js   |  12 +-
         src/data/examples/ko/02_Data/00_Variables.js  |   8 +-
         .../examples/ko/02_Data/01_True_and_False.js  |  17 ---
         .../examples/ko/02_Data/03_Variable_Scope.js  |  43 +-----
         src/data/examples/ko/02_Data/04_Numbers.js    |  17 ---
         src/data/examples/ko/03_Arrays/00_Array.js    |  11 --
         src/data/examples/ko/03_Arrays/01_Array_2d.js |  23 ---
         .../examples/ko/03_Arrays/02_Array_Objects.js |  13 --
         .../examples/ko/04_Control/00_Iteration.js    |  17 ---
         .../ko/04_Control/01_Embedded_Iteration.js    |   5 -
         .../ko/04_Control/02_Conditionals_1.js        |  16 --
         .../ko/04_Control/03_Conditionals_2.js        |  21 ---
         .../ko/04_Control/04_Logical_Operators.js     |  26 ----
         .../ko/05_Image/00_Load_and_Display_Image.js  |  22 ---
         .../ko/05_Image/01_Background_Image.js        |  16 --
         .../examples/ko/05_Image/02_Transparency.js   |  21 ---
         .../examples/ko/05_Image/03_Alpha_Mask.js     |  10 --
         .../examples/ko/05_Image/04_Create_Image.js   |   8 +-
         .../examples/ko/05_Image/05_Pointillism.js    |  10 --
         src/data/examples/ko/07_Color/00_Hue.js       |   7 -
         .../examples/ko/07_Color/01_Saturation.js     |   8 -
         .../examples/ko/07_Color/02_Brightness.js     |  23 ---
         .../ko/07_Color/03_Color_Variables.js         |  11 --
         .../examples/ko/07_Color/04_Relativity.js     |  11 --
         .../ko/07_Color/05_Linear_Gradient.js         |  18 +--
         .../examples/ko/07_Color/07_Lerp_Color.js     |   6 -
         .../ko/08_Math/00_incrementdecrement.js       |   6 -
         .../ko/08_Math/01_operatorprecedence.js       |  42 +-----
         src/data/examples/ko/08_Math/02_distance1d.js |   6 -
         src/data/examples/ko/08_Math/03_distance2d.js |   7 -
         src/data/examples/ko/08_Math/04_sine.js       |   5 -
         src/data/examples/ko/08_Math/05_sincosine.js  |   8 -
         src/data/examples/ko/08_Math/06_sinewave.js   |  27 ----
         .../examples/ko/08_Math/07_additivewave.js    |  42 ------
         .../ko/08_Math/08_polartocartesian.js         |  31 ----
         src/data/examples/ko/08_Math/09_arctangent.js |   5 -
         .../examples/ko/08_Math/10_Interpolate.js     |  19 ---
         .../examples/ko/08_Math/11_doubleRandom.js    |   8 +-
         src/data/examples/ko/08_Math/12_random.js     |   6 +-
         src/data/examples/ko/08_Math/13_noise1D.js    |  22 ---
         src/data/examples/ko/08_Math/14_noisewave.js  |  33 ----
         src/data/examples/ko/08_Math/15_Noise2D.js    |  28 ----
         src/data/examples/ko/08_Math/16_Noise3D.js    |  33 ----
         .../examples/ko/08_Math/17_Randomchords.js    |  31 +---
         src/data/examples/ko/08_Math/18_Map.js        |  15 --
         .../ko/08_Math/19_parametricEquation.js       |  43 ++++++
         src/data/examples/ko/09_Simulate/00_Forces.js |  84 +----------
         .../ko/09_Simulate/01_ParticleSystem.js       |  13 +-
         .../examples/ko/09_Simulate/02_Flocking.js    | 139 -----------------
         .../examples/ko/09_Simulate/03_WolframCA.js   |  36 -----
         .../examples/ko/09_Simulate/04_GameOfLife.js  |  55 -------
         .../09_Simulate/05_MultipleParticleSystems.js |  70 +--------
         .../examples/ko/09_Simulate/06_Spirograph.js  |  64 +-------
         .../examples/ko/09_Simulate/07_LSystems.js    |  91 -----------
         src/data/examples/ko/09_Simulate/08_Spring.js |  58 +------
         .../examples/ko/09_Simulate/09_Springs.js     |  76 ++--------
         .../examples/ko/09_Simulate/10_SoftBody.js    |  70 +--------
         .../ko/09_Simulate/11_SmokeParticleSystem.js  | 102 +------------
         .../ko/09_Simulate/12_BrownianMotion.js       |  22 ---
         src/data/examples/ko/09_Simulate/13_Chain.js  |  16 --
         .../09_Simulate/14_SnowflakeParticleSystem.js |  49 +-----
         .../ko/09_Simulate/15_penrose_tiles.js        |  43 ------
         .../ko/09_Simulate/16_Recursive_Tree.js       |  40 -----
         .../examples/ko/09_Simulate/17_Mandelbrot.js  |  59 --------
         src/data/examples/ko/09_Simulate/18_Koch.js   | 141 ++++++++++++++++++
         .../examples/ko/09_Simulate/19_Bubblesort.js  |  66 ++++++++
         .../ko/09_Simulate/20_SteepingFeet.js         |  81 ++++++++++
         .../examples/ko/09_Simulate/21_Particle.js    |  68 +++++++++
         .../examples/ko/10_Interaction/10_Tickle.js   |  29 ----
         .../examples/ko/10_Interaction/20_Follow1.js  |   9 +-
         .../examples/ko/10_Interaction/21_Follow2.js  |   8 -
         .../examples/ko/10_Interaction/22_Follow3.js  |   8 -
         .../examples/ko/10_Interaction/23_snake.js    |  54 +++----
         .../ko/10_Interaction/24_Wavemaker.js         |  35 +----
         .../examples/ko/10_Interaction/25_reach1.js   |   7 -
         .../examples/ko/10_Interaction/26_reach2.js   |  12 --
         .../examples/ko/10_Interaction/27_reach3.js   |  12 --
         .../ko/10_Interaction/28_ArduinoSensor.js     |  38 +++++
         .../ko/10_Interaction/29_kaleidoscope.js      |  76 ++++++++++
         src/data/examples/ko/11_Objects/01_Objects.js |  26 +---
         .../ko/11_Objects/02_Multiple_Objects.js      |  21 +--
         .../ko/11_Objects/03_Objects_Array.js         |  12 +-
         .../03_Objects_Optional_Arguments.js          |  15 --
         .../examples/ko/11_Objects/04_Inheritance.js  |   9 --
         .../ko/11_Objects/05_Composite_Objects.js     |  98 ++++++++++++
         .../examples/ko/12_Lights/02_Directional.js   |   9 --
         src/data/examples/ko/12_Lights/05_Mixture.js  |  16 --
         .../13_Motion/01_non_orthogonal_reflection.js |  80 +---------
         .../examples/ko/13_Motion/02_Linear_Motion.js |   8 -
         src/data/examples/ko/13_Motion/03_Bounce.js   |  33 ----
         .../ko/13_Motion/04_Bouncy_Bubbles.js         |   8 +-
         src/data/examples/ko/13_Motion/05_Morph.js    |  78 +---------
         .../ko/13_Motion/06_Moving_On_Curves.js       |  20 ---
         .../ko/15_Instance_Mode/01_Instantiating.js   |  10 --
         .../15_Instance_Mode/02_Instance_Container.js |  12 --
         .../examples/ko/16_Dom/03_Input_Button.js     |  12 +-
         src/data/examples/ko/16_Dom/04_Slider.js      |  14 +-
         src/data/examples/ko/16_Dom/07_Modify_DOM.js  |  24 +--
         src/data/examples/ko/16_Dom/08_Video.js       |  20 ---
         .../examples/ko/16_Dom/09_Video_Canvas.js     |  28 +---
         .../examples/ko/16_Dom/10_Video_Pixels.js     |  13 --
         src/data/examples/ko/16_Dom/11_Capture.js     |  14 +-
         src/data/examples/ko/16_Dom/12_Drop.js        |  23 ---
         .../ko/17_Drawing/00_Continuous_Lines.js      |   9 --
         src/data/examples/ko/17_Drawing/01_Pattern.js |  21 +--
         src/data/examples/ko/17_Drawing/02_Pulses.js  |  14 +-
         .../examples/ko/18_Transform/00_Translate.js  |  38 +----
         src/data/examples/ko/18_Transform/01_Scale.js |  34 ++---
         .../examples/ko/18_Transform/02_Rotate.js     |  33 ----
         src/data/examples/ko/18_Transform/03_Arm.js   |  45 +-----
         .../examples/ko/19_Typography/00_Letters.js   |  42 ------
         .../examples/ko/19_Typography/01_Words.js     |  37 -----
         src/data/examples/ko/20_3D/00_geometries.js   |   5 -
         .../examples/ko/20_3D/01_sine_cosine_in_3D.js |   5 -
         src/data/examples/ko/20_3D/04_textures.js     |  17 +--
         src/data/examples/ko/20_3D/05_ray_casting.js  | 100 +++++++++++++
         .../examples/ko/20_3D/07_orbit_control.js     |   9 --
         src/data/examples/ko/20_3D/08_basic_shader.js |  27 ++++
         .../ko/20_3D/09_shader_as_a_texture.js        |  68 +++++++++
         .../ko/20_3D/10_passing_shader_uniforms.js    |  34 +++++
         .../ko/20_3D/11_shader_using_webcam.js        |  37 +++++
         src/data/examples/ko/21_Input/00_Clock.js     |  24 ---
         src/data/examples/ko/21_Input/01_Constrain.js |   6 -
         src/data/examples/ko/21_Input/02_Easing.js    |  10 --
         src/data/examples/ko/21_Input/03_Keyboard.js  |  19 ---
         src/data/examples/ko/21_Input/04_Mouse1D.js   |   7 -
         src/data/examples/ko/21_Input/05_Mouse2D.js   |   6 -
         .../examples/ko/21_Input/06_MouseIsPressed.js |   6 -
         .../ko/21_Input/07_Mouse_Functions.js         |  15 +-
         .../examples/ko/21_Input/08_Mouse_Signals.js  |  13 --
         .../examples/ko/21_Input/09_Storing_Input.js  |  19 ---
         .../ko/22_Advanced_Data/00_Load_Saved_JSON.js |  66 --------
         .../examples/ko/33_Sound/01_Preload_Sound.js  |  21 ---
         .../examples/ko/33_Sound/02_soundFormats.js   |  49 +-----
         src/data/examples/ko/33_Sound/03_Play_Mode.js |  12 --
         .../examples/ko/33_Sound/04_Pan_SoundFile.js  |  14 --
         .../examples/ko/33_Sound/05_Sound_Effect.js   |  50 -------
         .../ko/33_Sound/06_Manipulate_Sound.js        |  36 -----
         .../ko/33_Sound/07_Amplitude_Analysis.js      |  38 -----
         .../examples/ko/33_Sound/08_Noise_Envelope.js |  43 ------
         .../examples/ko/33_Sound/09_Note_Envelope.js  |  31 ----
         .../ko/33_Sound/10_Oscillator_Waveform.js     |  21 ---
         .../examples/ko/33_Sound/11_Live_Input.js     |  29 ----
         .../examples/ko/33_Sound/12_FFT_Spectrum.js   |  10 +-
         .../examples/ko/33_Sound/13_Mic_Threshold.js  |  31 ----
         src/data/examples/ko/33_Sound/16_Delay.js     |  28 ----
         src/data/examples/ko/33_Sound/17_Reverb.js    |  22 ---
         .../ko/33_Sound/18_Convolution_Reverb.js      |  58 -------
         .../examples/ko/33_Sound/19_Record_Save.js    |  47 ------
         .../examples/ko/33_Sound/21_FreqModulation.js | 111 --------------
         .../ko/33_Sound/22_AmplitudeModulation.js     |  70 ---------
         .../35_Mobile/00_Acceleration_Ball_Bounce.js  |  22 +--
         .../examples/ko/35_Mobile/01_Simple_Draw.js   |   5 -
         .../ko/35_Mobile/02_Acceleration_Color.js     |   5 -
         .../ko/35_Mobile/03_Shake_Ball_Bounce.js      |  39 +----
         .../examples/ko/35_Mobile/04_Tilted_3D_Box.js |   5 -
         src/data/examples/ko/90_Hello_P5/01_shapes.js |  23 ---
         .../ko/90_Hello_P5/02_interactivity.js        |  29 ----
         .../ko/90_Hello_P5/03_interactivity.js        |  18 +--
         .../examples/ko/90_Hello_P5/04_animate.js     |  24 ---
         .../examples/ko/90_Hello_P5/04_flocking.js    | 118 ---------------
         .../examples/ko/90_Hello_P5/05_weather.js     |  47 ------
         .../examples/ko/90_Hello_P5/06_drawing.js     |  83 -----------
         src/data/examples/ko/90_Hello_P5/07_song.js   |  81 +---------
         src/data/ko.yml                               |  12 +-
         src/data/reference/ko.json                    |  10 +-
         181 files changed, 1040 insertions(+), 4335 deletions(-)
         create mode 100644 src/data/examples/ko/08_Math/19_parametricEquation.js
         create mode 100644 src/data/examples/ko/09_Simulate/18_Koch.js
         create mode 100644 src/data/examples/ko/09_Simulate/19_Bubblesort.js
         create mode 100644 src/data/examples/ko/09_Simulate/20_SteepingFeet.js
         create mode 100644 src/data/examples/ko/09_Simulate/21_Particle.js
         create mode 100644 src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
         create mode 100644 src/data/examples/ko/10_Interaction/29_kaleidoscope.js
         create mode 100644 src/data/examples/ko/11_Objects/05_Composite_Objects.js
         create mode 100644 src/data/examples/ko/20_3D/05_ray_casting.js
         create mode 100644 src/data/examples/ko/20_3D/08_basic_shader.js
         create mode 100644 src/data/examples/ko/20_3D/09_shader_as_a_texture.js
         create mode 100644 src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
         create mode 100644 src/data/examples/ko/20_3D/11_shader_using_webcam.js
        
        diff --git a/src/data/examples/ko/00_Structure/00_Coordinates.js b/src/data/examples/ko/00_Structure/00_Coordinates.js
        index 661645754e..b7a9e4091b 100644
        --- a/src/data/examples/ko/00_Structure/00_Coordinates.js
        +++ b/src/data/examples/ko/00_Structure/00_Coordinates.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 좌표
          * @description 모든 도형들은 좌표값으로 지정된 화면 위치에 나타납니다.
          * 픽셀 단위를 기준으로 원점(0,0)으로부터의 거리 
        @@ -8,42 +7,20 @@
          */
         function setup() {
           // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        -=======
        - * @name Coordinates
        - * @description All shapes drawn to the screen have a position that is
        - * specified as a coordinate. All coordinates are measured as the distance from
        - * the origin in units of pixels. The origin [0, 0] is the coordinate in the
        - * upper left of the window and the coordinate in the lower right is [width-1,
        - * height-1].
        - */
        -function setup() {
        -  // Sets the screen to be 720 pixels wide and 400 pixels high
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           createCanvas(720, 400);
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 배경색을 검정색(0)으로 지정, noFill()로 면채우기 기능 해제
           background(0);
           noFill();
             
           // point()의 괄호 안 두 인수로 좌표값 지정
           // 첫번째 인수는 x값을, 두번째 인수는 y값 의미
        -=======
        -  // Set the background to black and turn off the fill color
        -  background(0);
        -  noFill();
        -
        -  // The two parameters of the point() method each specify
        -  // coordinates.
        -  // The first parameter is the x-coordinate and the second is the Y
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(255);
           point(width * 0.5, height * 0.5);
           point(width * 0.5, height * 0.25);
         
        -<<<<<<< HEAD
           // 좌표를 활용해 점 뿐 아니라 모든 도형을 그릴 수 있습니다.
           // 각 함수별 괄호에 적힌 매개 변수들은 각기 다른 목적을 위해 사용됩니다.
           // 예를들어 line()함수에 쓰인 처음 두 매개 변수들은 각각 첫번째 그리고 두번째 끝점을 지정합니다.
        @@ -52,19 +29,6 @@ function draw() {
         
           // rect()함수의 처음 두 매개 변수는 상단 모서리의 좌표값을 의미하고,
           // 그 다음 두 매개 변수는 너비와 높이를 지정합니다.
        -=======
        -  // Coordinates are used for drawing all shapes, not just points.
        -  // Parameters for different functions are used for different
        -  // purposes. For example, the first two parameters to line()
        -  // specify the coordinates of the first endpoint and the second
        -  // two parameters specify the second endpoint
        -  stroke(0, 153, 255);
        -  line(0, height * 0.33, width, height * 0.33);
        -
        -  // By default, the first two parameters to rect() are the
        -  // coordinates of the upper-left corner and the second pair
        -  // is the width and height
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(255, 153, 0);
           rect(width * 0.25, height * 0.1, width * 0.5, height * 0.8);
         }
        diff --git a/src/data/examples/ko/00_Structure/01_Width_and_Height.js b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        index e853fcc2d9..933addbe47 100644
        --- a/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        +++ b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        @@ -1,14 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 너비와 높이
          * @description '너비(width)'와 '높이(height)' 변수들은 createCanvas() 함수에 따라
          * 정의된, 윈도우 화면의 너비 및 높이 값을 포함합니다.
        -=======
        - * @name Width and Height
        - * @description The 'width' and 'height' variables contain the
        - * width and height of the display window as defined in the createCanvas()
        - * function.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        index 059f798246..b5517e7754 100644
        --- a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        +++ b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 설정하고 그리기
          * @description draw()함수 안에의 코드는 위에서 아래 방향으로
          * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
        @@ -18,28 +17,6 @@ function setup() {
         // 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
           background(0); // 배경색을 검정색(0)으로 지정
        -=======
        - * @name Setup and Draw
        - * @description The code inside the draw() function runs continuously from top
        - * to bottom until the program is stopped.
        - */
        -let y = 100;
        -
        -// The statements in the setup() function
        -// execute once when the program begins
        -function setup() {
        -  // createCanvas must be the first statement
        -  createCanvas(720, 400);
        -  stroke(255); // Set line drawing color to white
        -  frameRate(30);
        -}
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        -function draw() {
        -  background(0); // Set the background to black
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/03_No_Loop.js b/src/data/examples/ko/00_Structure/03_No_Loop.js
        index d8b4c16d9a..107d2edf8b 100644
        --- a/src/data/examples/ko/00_Structure/03_No_Loop.js
        +++ b/src/data/examples/ko/00_Structure/03_No_Loop.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 루프 해제
          * @description noLoop()함수는 draw()함수가 반복없이 단 한번만 실행되게 합니다.
          * noLoop()를 호출하지 않는다면 draw()함수는 계속해서 반복 실행될 것입니다.
        @@ -11,39 +10,16 @@ function setup() {
           // createCanvas가 그 첫 선언문입니다.
           createCanvas(720, 400);
           stroke(255); // 선색을 흰색(255)으로 지정
        -=======
        - * @name No Loop
        - * @description The noLoop() function causes draw() to only execute once.
        - * Without calling noLoop(), the code inside draw() is run continually.
        - */
        -let y;
        -
        -// The statements in the setup() function
        -// execute once when the program begins
        -function setup() {
        -  // createCanvas should be the first statement
        -  createCanvas(720, 400);
        -  stroke(255); // Set line drawing color to white
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noLoop();
         
           y = height * 0.5;
         }
         
        -<<<<<<< HEAD
         // 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
         // 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
         // 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
           background(0); // 배경색을 검정색(0)으로 지정
        -=======
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        -function draw() {
        -  background(0); // Set the background to black
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/04_Loop.js b/src/data/examples/ko/00_Structure/04_Loop.js
        index 577c7b5b6f..058a1d55a4 100644
        --- a/src/data/examples/ko/00_Structure/04_Loop.js
        +++ b/src/data/examples/ko/00_Structure/04_Loop.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 루프
          * @description draw()함수 안에의 코드는 위에서 아래 방향으로
          * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
        @@ -17,27 +16,6 @@ function setup() {
         // 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
           background(0); // 배경색을 검정색(0)으로 지정
        -=======
        - * @name Loop
        - * @description The code inside the draw() function runs continuously from top
        - * to bottom until the program is stopped.
        - */
        -let y = 100;
        -
        -// The statements in the setup() function
        -// execute once when the program begins
        -function setup() {
        -  createCanvas(720, 400); // Size must be the first statement
        -  stroke(255); // Set line drawing color to white
        -  frameRate(30);
        -}
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        -function draw() {
        -  background(0); // Set the background to black
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/05_Redraw.js b/src/data/examples/ko/00_Structure/05_Redraw.js
        index a157b90d34..b4895ea150 100644
        --- a/src/data/examples/ko/00_Structure/05_Redraw.js
        +++ b/src/data/examples/ko/00_Structure/05_Redraw.js
        @@ -1,23 +1,12 @@
         /*
        -<<<<<<< HEAD
          * @name 다시 그리기
          * @description redraw()함수는 draw()함수를 다시 한번 실행합니다.
          * 이 예제에서 draw()는 마우스가 클릭될 때마다 매번 재실행됩니다.
        -=======
        - * @name Redraw
        - * @description The redraw() function makes draw() execute once. In this example,
        - * draw() is executed once every time the mouse is clicked.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let y;
         
        -<<<<<<< HEAD
         // setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
        -=======
        -// The statements in the setup() function
        -// execute once when the program begins
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function setup() {
           createCanvas(720, 400);
           stroke(255);
        @@ -25,16 +14,9 @@ function setup() {
           y = height * 0.5;
         }
         
        -<<<<<<< HEAD
         // 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
         // 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
         // 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
        -=======
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function draw() {
           background(0);
           y = y - 4;
        diff --git a/src/data/examples/ko/00_Structure/06_Functions.js b/src/data/examples/ko/00_Structure/06_Functions.js
        index b7afbb2d5e..47f31593aa 100644
        --- a/src/data/examples/ko/00_Structure/06_Functions.js
        +++ b/src/data/examples/ko/00_Structure/06_Functions.js
        @@ -1,14 +1,7 @@
         /*
        -<<<<<<< HEAD
          *@name 그 외 함수들
          *@description 각 drawTarget()함수로 과녁판 형상의 도형 여러개를 쉽게 만들 수 있습니다.
          *호출된 drawTarget()함수들은 각기 다른 과녁판 도형의 위치, 크기 그리고 고리 개수를 지정합니다.
        -=======
        - *@name Functions
        - *@description The drawTarget() function makes it easy to draw many distinct
        - *targets. Each call to drawTarget() specifies the position, size, and number of
        - *rings for each target.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/00_Structure/07_Recursion.js b/src/data/examples/ko/00_Structure/07_Recursion.js
        index 2a334a44fa..9833a01bae 100644
        --- a/src/data/examples/ko/00_Structure/07_Recursion.js
        +++ b/src/data/examples/ko/00_Structure/07_Recursion.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          *@name 재귀 함수
          *@description 재귀 함수는 자기 자신을 다시 호출하는 함수를 말합니다.
          * drawCircle()함수가 블록 말미에 그 자신을 다시 호출하는 것을 볼 수 있습니다.
          * 이 경우, drawCircle()함수의 변수인 "level"의 값이 1과 같아질 때까지 계속해서 재호출됩니다.
        -=======
        - *@name Recursion
        - *@description A demonstration of recursion, which means functions call themselves.
        - * Notice how the drawCircle() function calls itself at the end of its block.
        - * It continues to do this until the variable "level" is equal to 1.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/00_Structure/08_Create_Graphics.js b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        index d489d6e308..5af2a082bf 100644
        --- a/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        +++ b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 그래픽 만들기
          * @description 새로운 p5.Renderer 오브젝트를 만들고 반환합니다.
          * 아래의 클래스는 특정 사각 스크린의 바깥 영역에 그래픽 버퍼를 만드는 데에 사용됩니다.
          * 두 인수들은 사각 스크린의 너비와 높이값을 픽셀 단위로 각각 지정합니다.
        -=======
        - * @name Create Graphics
        - * @description Creates and returns a new p5.Renderer object. Use this
        - * class if you need to draw into an off-screen graphics buffer. The two parameters
        - * define the width and height in pixels.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let pg;
        @@ -31,10 +24,6 @@ function draw() {
           pg.stroke(255);
           pg.ellipse(mouseX - 150, mouseY - 75, 60, 60);
         
        -<<<<<<< HEAD
           //image() 선언문으로 사각 스크린 바깥에 위치한 그래픽 버퍼를 그립니다.
        -=======
        -  //Draw the offscreen buffer to the screen with image()
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           image(pg, 150, 75);
         }
        diff --git a/src/data/examples/ko/01_Form/00_Points_and_Lines.js b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        index ca63da99f5..a7e1028623 100644
        --- a/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        +++ b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 점과 선
          * @description 점과 선을 활용하여 기본적인 기하 형태를 그릴 수 있습니다.
          * 도형의 크기 조정을 위해 변수인 'd'값을 바꿔보세요.
          * 4개의 변수들은 d값을 기준으로 위치값을 설정합니다.
        -=======
        - * @name Points and Lines
        - * @description Points and lines can be used to draw basic geometry.
        - * Change the value of the variable 'd' to scale the form. The four
        - * variables set the positions based on the value of 'd'.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           let d = 70;
        @@ -18,33 +11,21 @@ function setup() {
           let p3 = p2 + d;
           let p4 = p3 + d;
         
        -<<<<<<< HEAD
           // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        -=======
        -  // Sets the screen to be 720 pixels wide and 400 pixels high
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           createCanvas(720, 400);
           background(0);
           noSmooth();
         
           translate(140, 0);
         
        -<<<<<<< HEAD
           // 회색의 사각형 그리기
        -=======
        -  // Draw gray box
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(153);
           line(p3, p3, p2, p3);
           line(p2, p3, p2, p2);
           line(p2, p2, p3, p2);
           line(p3, p2, p3, p3);
         
        -<<<<<<< HEAD
           // 흰색 점들 그리기
        -=======
        -  // Draw white points
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(255);
           point(p1, p1);
           point(p1, p3);
        diff --git a/src/data/examples/ko/01_Form/02_Pie_Chart.js b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        index aa207adc89..248006533f 100644
        --- a/src/data/examples/ko/01_Form/02_Pie_Chart.js
        +++ b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        @@ -1,23 +1,13 @@
         /*
        -<<<<<<< HEAD
          * @name 파이형 차트
          * @description arc()함수를 사용하여 배열에 저장된 데이터로 파이형 차트를 생성해보세요.
        -=======
        - * @name Pie Chart
        - * @description Uses the arc() function to generate a pie chart from the data
        - * stored in an array.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let angles = [30, 10, 45, 35, 60, 38, 75, 67];
         
         function setup() {
           createCanvas(720, 400);
           noStroke();
        -<<<<<<< HEAD
           noLoop(); // 프로그램 시작시 한 번 실행 뒤 멈추기
        -=======
        -  noLoop(); // Run once and stop
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/01_Form/03_Regular_Polygon.js b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        index fda6c7fbbf..0fd70871c0 100644
        --- a/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        +++ b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        @@ -1,16 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 정다각형
          * @description 가장 좋아하는 정다각형이 있나요? 오각형? 육각형? 칠각형? 아니면, 이십각형은요?
          * 이 예제에서 소개하는 polygon()함수는 그 어떠한 정다각형도 그릴 수 있습니다.
          * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
        -=======
        - * @name Regular Polygon
        - * @description What is your favorite? Pentagon? Hexagon? Heptagon? No?
        - * What about the icosagon? The polygon() function created for this example is
        - * capable of drawing any regular polygon. Try placing different numbers into
        - * the polygon() function calls within draw() to explore.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/04_Star.js b/src/data/examples/ko/01_Form/04_Star.js
        index 2ece7ece75..7e98f1d2b4 100644
        --- a/src/data/examples/ko/01_Form/04_Star.js
        +++ b/src/data/examples/ko/01_Form/04_Star.js
        @@ -1,14 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 별모양
          * @description 이 예제에서 소개하는 star()함수는 여러가지 다양한 모양을 그립니다. 
          * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
        -=======
        - * @name Star
        - * @description The star() function created for this example is capable of
        - * drawing a wide range of different forms. Try placing different numbers
        - * into the star() function calls within draw() to explore.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/05_Triangle_Strip.js b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        index 7b60634c4d..62308eea3d 100644
        --- a/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        +++ b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 삼각형 고리
          * @description 이라 그린버그(Ira Greenberg) 제작 예제. vertex()함수와
          * beginShape(TRIANGLE_STRIP) 모드를 이용하여 닫힌 고리를 하나 생성하세요. 
          * outsideRadius와 insideRadius 변수를 이용하여 각 고리의 지름(radius)을 조정할 수 있습니다.
        -=======
        - * @name Triangle Strip
        - * @description Example by Ira Greenberg. Generate a closed ring using the
        - * vertex() function and beginShape(TRIANGLE_STRIP) mode. The outsideRadius
        - * and insideRadius variables control ring's radii respectively.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let x;
         let y;
        diff --git a/src/data/examples/ko/01_Form/06_Bezier.js b/src/data/examples/ko/01_Form/06_Bezier.js
        index 0e2acfd3e8..8e779bb045 100644
        --- a/src/data/examples/ko/01_Form/06_Bezier.js
        +++ b/src/data/examples/ko/01_Form/06_Bezier.js
        @@ -1,15 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 베지어 곡선
        - * @description bezier()함수의 처음 두 인수들은 각각 곡선의 시작점과 끝점을 지정합니다.
        + * @description bezier()함수의 처음 두 매개변수들은 각각 곡선의 시작점과 끝점을 지정합니다.
          * 중간의 인수들은 곡선의 모양을 조정하는 '조정점(control point)'들입니다.
        -=======
        - * @name Bezier
        - * @description The first two parameters for the bezier() function specify the
        - * first point in the curve and the last two parameters specify the last point.
        - * The middle parameters set the control points that define the shape of the
        - * curve.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/07_3D_Primitives.js b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        index 2cd05b102e..4c6245d0e6 100644
        --- a/src/data/examples/ko/01_Form/07_3D_Primitives.js
        +++ b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 3D 기본 조형
          * @frame 720,400 (optional)
        - * @description 3D 오브젝트를 합성 공간에 수학적으로 배치하기.
        - * box()와 sphere()함수는 최소 한 개의 인수를 사용하여 그 크기를 조정할 수 있습니다.
        + * @description 3D 객체를 합성 공간 속에 수학적으로 배치하기.
        + * box()와 sphere()함수는 최소 한 개의 매개변수를 사용하여 그 크기를 조정할 수 있습니다.
          * 도형의 위치는 translate()함수를 통해 조정할 수 있습니다.
        -=======
        - * @name 3D Primitives
        - * @frame 720,400 (optional)
        - * @description Placing mathematically 3D objects in synthetic space.
        - * The box() and sphere() functions take at least one parameter to specify their
        - * size. These shapes are positioned using the translate() function.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/02_Data/00_Variables.js b/src/data/examples/ko/02_Data/00_Variables.js
        index 3db72719fc..115ee139d5 100644
        --- a/src/data/examples/ko/02_Data/00_Variables.js
        +++ b/src/data/examples/ko/02_Data/00_Variables.js
        @@ -1,12 +1,6 @@
         /*
        -<<<<<<< HEAD
        - * @name 변수들
        + * @name 변수
          * @description 변수는 값을 저장하기 위해 사용됩니다. 예제의 변수값을 바꿔 구성을 변형해보세요.
        -=======
        - * @name Variables
        - * @description Variables are used for storing values. In this example, change
        - * the values of variables to affect the composition.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/02_Data/01_True_and_False.js b/src/data/examples/ko/02_Data/01_True_and_False.js
        index 7656a8070b..4ebc9f2224 100644
        --- a/src/data/examples/ko/02_Data/01_True_and_False.js
        +++ b/src/data/examples/ko/02_Data/01_True_and_False.js
        @@ -1,18 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 참과 거짓
          * @description 불리언(Boolean) 변수는 오직 'true(참)'과 'false(거짓)'이라는 두 개의 값만 갖습니다.
          * 불리언과 함께 제어문을 사용하여 프로그램의 흐름을 조정하는 것이 일반적인 방식입니다. 
          * 이 예제에서는, b값이 'true(참)'일 때 세로선들이 그려지고
          * b값이 'false(거짓)'일 때 가로선들이 그려집니다.
        -=======
        - * @name True and False
        - * @description A Boolean variable has only two possible values: true or false.
        - * It is common to use Booleans with control statements to determine the flow
        - * of a program. In this example, when the boolean value "b" is true, vertical
        - * lines are drawn and when the boolean value "b" is false, horizontal
        - * lines are drawn.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        @@ -27,20 +18,12 @@ function setup() {
             b = i < middle;
         
             if (b === true) {
        -<<<<<<< HEAD
               // 세로선
        -=======
        -      // Vertical line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               line(i, d, i, height - d);
             }
         
             if (b === false) {
        -<<<<<<< HEAD
               // 가로선
        -=======
        -      // Horizontal line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               line(middle, i - middle + d, width - d, i - middle + d);
             }
           }
        diff --git a/src/data/examples/ko/02_Data/03_Variable_Scope.js b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        index 72e700689f..92b74cc6fe 100644
        --- a/src/data/examples/ko/02_Data/03_Variable_Scope.js
        +++ b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        @@ -1,23 +1,12 @@
         /*
        -<<<<<<< HEAD
          * @name 변수 범위
          * @description 변수는 '전역(global) 변수'로서 선언되거나, 그 범위를 조정하여 '지역(local) 변수'로 사용할 수 있습니다.
          * 예를 들어, setup() 및 draw()함수 안에 선언된 변수들은 해당 함수들의 범위 내에서만 사용되는 '지역 변수'가 됩니다.
        - * '전역 변수'의 경우, setup() 및 draw()함수 범위 외에서 사용 가능합니다. 
        + * '전역 변수'의 경우, setup() 및 draw()함수 범위 외에서 사용 가능합니다.
          * 어떤 함수의 '지역 변수'가 '전역 변수'와 동일한 이름으로 선언된 경우,
          * 이 변수는 해당 함수에 한해 지역 변수로서 처리됩니다.
        -=======
        - * @name Variable Scope
        - * @description Variables have a global or function "scope". For example,
        - * variables declared within either the setup() or draw() functions may be
        - * only used in these functions. Global variables, variables declared outside
        - * of setup() and draw(), may be used anywhere within the program. If a function
        - * variable is declared with the same name as a global variable, the program
        - * will use the function variable to make its calculations within the current
        - * scope.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
        -let a = 80; // Create a global variable "a"
        +let a = 80; // 전역 변수 "a" 생성하기
         
         function setup() {
           createCanvas(720, 400);
        @@ -27,56 +16,30 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 전역 변수 a를 사용하여 선 그리기
           line(a, 0, a, height);
         
           // 반복문 안에 지역 변수 a를 사용하기
        -=======
        -  // Draw a line using the global variable "a"
        -  line(a, 0, a, height);
        -
        -  // Use a local variable a in for loop
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let a = 120; a < 200; a += 3) {
             line(a, 0, a, height);
           }
         
        -<<<<<<< HEAD
           // 사용자가 만든 함수 drawAnotherLine() 호출하기
           drawAnotherLine();
         
           // 사용자가 만든 함수 drawYetAnotherLine() 호출하기
        -=======
        -  // Make a call to the custom function drawAnotherLine()
        -  drawAnotherLine();
        -
        -  // Make a call to the custom function drawYetAnotherLine()
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           drawYetAnotherLine();
         }
         
         function drawAnotherLine() {
        -<<<<<<< HEAD
           // 이 함수에 대한 지역 변수로서 새로운 a 선언하기
           let a = 320;
           // 지역 변수 a를 사용하여 선 그리기  line(a, 0, a, height);
        +  line(a, 0, a, height);
         }
         
         function drawYetAnotherLine() {
           // 새로운 지역 변수 a를 선언하지 않았으므로,
           // 이 선은 위에서 선언된 전역 변수 a(값 80)를 사용하여 그려집니다.
        -=======
        -  // Create a new variable "a" local to this function
        -  let a = 320;
        -  // Draw a line using the local variable "a"
        -  line(a, 0, a, height);
        -}
        -
        -function drawYetAnotherLine() {
        -  // Because no new local variable "a" is set,
        -  // this line draws using the original global
        -  // variable "a" which is set to the value 20.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           line(a + 3, 0, a + 3, height);
         }
        diff --git a/src/data/examples/ko/02_Data/04_Numbers.js b/src/data/examples/ko/02_Data/04_Numbers.js
        index 89d5b41395..56dd62c09e 100644
        --- a/src/data/examples/ko/02_Data/04_Numbers.js
        +++ b/src/data/examples/ko/02_Data/04_Numbers.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 숫자값
          * @frame 720,400
          * @description 숫자값은 소수점과 함께, 또는 없이 사용할 수 있습니다.
        @@ -8,17 +7,6 @@
          */
         let a = 0; // "a"를 숫자형 전역 변수로 선언
         let b = 0; // "b"를 숫자형 전역 변수로 선언
        -=======
        - * @name Numbers
        - * @frame 720,400
        - * @description Numbers can be written with or without decimals. An integer
        - * (more commonly called an int) is a number without a decimal point. A float
        - * is a floating-point number, which means it is a number that has a decimal
        - * place.
        - */
        -let a = 0; // Create a global variable "a" of type Number
        -let b = 0; // Create a global variable "b" of type Number
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(720, 400);
        @@ -28,13 +16,8 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           a = a + 1; // a를 정수 단위로 증가
           b = b + 0.2; // b를 실수 단위로 증가
        -=======
        -  a = a + 1; // Increment a with an integer
        -  b = b + 0.2; //Increment b with a float
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           line(a, 0, a, height / 2);
           line(b, height / 2, b, height);
         
        diff --git a/src/data/examples/ko/03_Arrays/00_Array.js b/src/data/examples/ko/03_Arrays/00_Array.js
        index f4c93a046b..4f624aaaa8 100644
        --- a/src/data/examples/ko/03_Arrays/00_Array.js
        +++ b/src/data/examples/ko/03_Arrays/00_Array.js
        @@ -1,21 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 배열
          * @description 배열은 데이터의 리스트를 말합니다. 배열 속 각 데이터는 
          * 배열에서의 위치를 나타내는 색인(index) 번호로 식별됩니다. 배열의 시작은 0을 기준으로 합니다.
          * 따라서, 배열의 첫 번째 데이터는 [0]이고 두 번째 데이터는 [1]로 식별됩니다.
          * 이 예제에서는 "coswave"라는 배열을 만들고, 이를 코사인 값으로 채웁니다.
          * 데이터는 실행 화면상 세 가지의 다른 방법으로 표현됩니다.
        -=======
        - * @name Array
        - * @description An array is a list of data. Each piece of data in an array
        - * is identified by an index number representing its position in
        - * the array. Arrays are zero based, which means that the first
        - * element in the array is [0], the second element is [1], and so on.
        - * In this example, an array named "coswave" is created and
        - * filled with the cosine values. This data is displayed three
        - * separate ways on the screen.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let coswave = [];
         
        diff --git a/src/data/examples/ko/03_Arrays/01_Array_2d.js b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        index 718007ec85..47da9cc5f1 100644
        --- a/src/data/examples/ko/03_Arrays/01_Array_2d.js
        +++ b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 2D 배열
          * @description 2차원(2D) 배열 작성을 위한 구문입니다.
          * 2D 배열의 값은 두 개의 색인(index)값을 통해 가져올 수 있습니다.
          * 2D 배열은 이미지를 저장하는 데에 유용합니다. 
          * 이 예제에서 각 점의 색상은 이미지 중심으로부터의 거리에 따라 지정됩니다.
        -=======
        - * @name Array 2D
        - * @description Demonstrates the syntax for creating a two-dimensional (2D)
        - * array. Values in a 2D array are accessed through two index values.
        - * 2D arrays are useful for storing images. In this example, each dot
        - * is colored in relation to its distance from the center of the image.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let distances = [];
         let maxDistance;
        @@ -21,36 +13,21 @@ function setup() {
           createCanvas(720, 360);
           maxDistance = dist(width / 2, height / 2, width, height);
           for (let x = 0; x < width; x++) {
        -<<<<<<< HEAD
             distances[x] = []; // 중첩 배열 만들기
        -=======
        -    distances[x] = []; // create nested array
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             for (let y = 0; y < height; y++) {
               let distance = dist(width / 2, height / 2, x, y);
               distances[x][y] = (distance / maxDistance) * 255;
             }
           }
           spacer = 10;
        -<<<<<<< HEAD
           noLoop(); // 한번 실행 후 멈추기
        -=======
        -  noLoop(); // Run once and stop
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
           background(0);
        -<<<<<<< HEAD
           // 이 함수에 내장된 반복문은 앞서 선언된 spacer변수에 따라 배열값 사이의 간격을 생성하게 됩니다.
           // 따라서, 이 함수로 그려진 것보다 더 많은 값이 배열에 있는 셈입니다.
           // spacer 변수의 값을 변경하여 점들 간의 밀도를 조정해보세요.
        -=======
        -  // This embedded loop skips over values in the arrays based on
        -  // the spacer variable, so there are more values in the array
        -  // than are drawn here. Change the value of the spacer variable
        -  // to change the density of the points
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let x = 0; x < width; x += spacer) {
             for (let y = 0; y < height; y += spacer) {
               stroke(distances[x][y]);
        diff --git a/src/data/examples/ko/03_Arrays/02_Array_Objects.js b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        index d055944a40..8379a2066e 100644
        --- a/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        +++ b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 객체 배열
          * @description 사용자가 정의한 객체 배열을 만듭니다.
        -=======
        - * @name Array Objects
        - * @description Demonstrates the syntax for creating an array of custom objects.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         class Module {
        @@ -20,11 +15,7 @@ class Module {
             this.yDir = 1;
           }
         
        -<<<<<<< HEAD
           // 사용자 정의한 메소드를 통해 변수들을 업데이트합니다.
        -=======
        -  // Custom method for updating the variables
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           update() {
             this.x = this.x + this.speed * this.xDir;
             if (this.x >= this.unit || this.x <= 0) {
        @@ -38,11 +29,7 @@ class Module {
             }
           }
         
        -<<<<<<< HEAD
           // 사용자가 정의한 메소드를 통해 오브젝트를 그립니다.
        -=======
        -  // Custom method for drawing the object
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           draw() {
             fill(255);
             ellipse(this.xOff + this.x, this.yOff + this.y, 6, 6);
        diff --git a/src/data/examples/ko/04_Control/00_Iteration.js b/src/data/examples/ko/04_Control/00_Iteration.js
        index d0cc0f782f..5bfeee8b68 100644
        --- a/src/data/examples/ko/04_Control/00_Iteration.js
        +++ b/src/data/examples/ko/04_Control/00_Iteration.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name for 반복문
          * @description "for"구조를 사용하여 반복 형식을 만듭니다.
        -=======
        - * @name Iteration
        - * @description Iteration with a "for" structure to construct repetitive forms.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let y;
         let num = 14;
        @@ -15,11 +10,7 @@ function setup() {
           background(102);
           noStroke();
         
        -<<<<<<< HEAD
           // 흰색 막대기들 그리기
        -=======
        -  // Draw white bars
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(255);
           y = 60;
           for (let i = 0; i < num / 3; i++) {
        @@ -27,11 +18,7 @@ function setup() {
             y += 20;
           }
         
        -<<<<<<< HEAD
           // 회색 막대기들
        -=======
        -  // Gray bars
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(51);
           y = 40;
           for (let i = 0; i < num; i++) {
        @@ -44,11 +31,7 @@ function setup() {
             y += 20;
           }
         
        -<<<<<<< HEAD
           // 얇은 선들
        -=======
        -  // Thin lines
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           y = 45;
           fill(0);
           for (let i = 0; i < num - 1; i++) {
        diff --git a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        index 950ffca52b..33c571bb01 100644
        --- a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        +++ b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name for 내장 반복문
          * @description "for" 반복문 구조를 이중 사용하여 2차원 도형을 반복할 수 있습니다.
        -=======
        - * @name Embedded Iteration
        - * @description Embedding "for" structures allows repetition in two dimensions.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 360);
        diff --git a/src/data/examples/ko/04_Control/02_Conditionals_1.js b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        index d8b3d52339..3d809536b0 100644
        --- a/src/data/examples/ko/04_Control/02_Conditionals_1.js
        +++ b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        @@ -1,34 +1,18 @@
         /*
        -<<<<<<< HEAD
          * @name 조건문 1
          * @description 조건문은 마치 질문과도 같습니다.
          * 프로그램은 조건문이 던지는 질문이 참인지 거짓인지에 따라
          * 특정 선언문을 실행할 지 여부를 결정합니다.
          * 조건문으로 던지는 질문들은 언제나 논리 또는 관계 선언문의 형식을 갖습니다. 
          * 이 예제의 경우, 변수 i가 0이라는 조건이 충족될 시 선이 그려집니다.
        -=======
        - * @name Conditionals 1
        - * @description Conditions are like questions.
        - * They allow a program to decide to take one action if
        - * the answer to a question is true or to do another action
        - * if the answer to the question is false.
        - * The questions asked within a program are always logical
        - * or relational statements. For example, if the variable 'i' is
        - * equal to zero then draw a line.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 360);
           background(0);
         
           for (let i = 10; i < width; i += 10) {
        -<<<<<<< HEAD
             // i가 20으로 나누어 떨어진다면, 첫번째 선을 그린다.
             // 그렇지 않을 경우, 두번째 선을 그린다.
        -=======
        -    // If 'i' divides by 20 with no remainder draw the first line
        -    // else draw the second line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (i % 20 === 0) {
               stroke(255);
               line(i, 80, i, height / 2);
        diff --git a/src/data/examples/ko/04_Control/03_Conditionals_2.js b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        index c9ea3e5446..bde90ef016 100644
        --- a/src/data/examples/ko/04_Control/03_Conditionals_2.js
        +++ b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        @@ -1,23 +1,14 @@
         /*
        -<<<<<<< HEAD
          * @name 조건문 2
          * @description 조건문 1 예제에 "else"라는 키워드를 더해 조건문의 문법을 확장해봅시다.
          * "else"를 사용하면 연속하여 2개 이상의 질문을 던질 수 있습니다.
          * 이 때, 각각의 질문은 서로 다른 행위를 요청할 수 있습니다.
        -=======
        - * @name Conditionals 2
        - * @description We extend the language of conditionals from the previous
        - * example by adding the keyword "else". This allows conditionals
        - * to ask two or more sequential questions, each with a different
        - * action.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 360);
           background(0);
         
           for (let i = 2; i < width - 2; i += 4) {
        -<<<<<<< HEAD
             // i가 20으로 나누어 떨어질 경우
             if (i % 20 === 0) {
               stroke(255);
        @@ -28,18 +19,6 @@ function setup() {
               line(i, 20, i, 180);
               // 위의 두 조건 모두 충족하지 않을 경우
               // 이 선을 그린다.
        -=======
        -    // If 'i' divides by 20 with no remainder
        -    if (i % 20 === 0) {
        -      stroke(255);
        -      line(i, 80, i, height / 2);
        -      // If 'i' divides by 10 with no remainder
        -    } else if (i % 10 === 0) {
        -      stroke(153);
        -      line(i, 20, i, 180);
        -      // If neither of the above two conditions are met
        -      // then draw this line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             } else {
               stroke(102);
               line(i, height / 2, i, height - 20);
        diff --git a/src/data/examples/ko/04_Control/04_Logical_Operators.js b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        index 02f18577f1..4f3436dce7 100644
        --- a/src/data/examples/ko/04_Control/04_Logical_Operators.js
        +++ b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 논리적 연산자
          * @description 논리 연산자인 AND (&&) 와 OR (||) 는 
          * 간단한 관계 선언문에 좀 더 복잡한 조건을 더할 때 쓰입니다.
          * NOT (!) 연산자는 불리언 선언문을 부정할 때 쓰입니다.
        -=======
        - * @name Logical Operators
        - * @description The logical operators for AND (&&) and OR (||) are used to
        - * combine simple relational statements into more complex expressions.
        - * The NOT (!) operator is used to negate a boolean statement.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let test = false;
         
        @@ -18,48 +11,29 @@ function setup() {
           background(126);
         
           for (let i = 5; i <= height; i += 5) {
        -<<<<<<< HEAD
             // 논리적 연산자 AND
        -=======
        -    // Logical AND
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             stroke(0);
             if (i > 35 && i < 100) {
               line(width / 4, i, width / 2, i);
               test = false;
             }
         
        -<<<<<<< HEAD
             // 논리적 연산자 OR
        -=======
        -    // Logical OR
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             stroke(76);
             if (i <= 35 || i >= 100) {
               line(width / 2, i, width, i);
               test = true;
             }
         
        -<<<<<<< HEAD
             // 불리언 값이 참(true)인지 여부를 테스트
             // "if(test)"이 "if(test == true)"와 동일한지 여부를 확인
        -=======
        -    // Testing if a boolean value is "true"
        -    // The expression "if(test)" is equivalent to "if(test == true)"
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (test) {
               stroke(0);
               point(width / 3, i);
             }
         
        -<<<<<<< HEAD
        -      
             // 불리언 값이 거짓(false)인지 여부를 테스트
             // "if(!test)"이 "if(test == false)"와 동일한지 여부를 확인
        -=======
        -    // Testing if a boolean value is "false"
        -    // The expression "if(!test)" is equivalent to "if(test == false)"
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (!test) {
               stroke(255);
               point(width / 4, i);
        diff --git a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        index b4e7935709..5111273db6 100644
        --- a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        +++ b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 이미지 불러오기 및 보이기
          * @description 이미지를 실제 또는 다른 크기로 지정하여 화면상 불러오고 보이게 할 수 있습니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        @@ -16,26 +15,5 @@ function draw() {
           // 이미지를 화면상 좌표 (0,0) 위치에 실제 크기로 보이게 한다.
           image(img, 0, 0);
           // 이미지를 화면상 좌표 (0,높이/2) 위치에 절반 크기로 보이게 한다.
        -=======
        - * @name Load and Display Image
        - * @description Images can be loaded and displayed to the screen at their
        - * actual size or any other size.
        - * <p><em><span class="small"> To run this example locally, you will need an 
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        -
        - */
        -let img; // Declare variable 'img'.
        -
        -function setup() {
        -  createCanvas(720, 400);
        -  img = loadImage('assets/moonwalk.jpg'); // Load the image
        -}
        -
        -function draw() {
        -  // Displays the image at its actual size at point (0,0)
        -  image(img, 0, 0);
        -  // Displays the image at point (0, height/2) at half size
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           image(img, 0, height / 2, img.width / 2, img.height / 2);
         }
        diff --git a/src/data/examples/ko/05_Image/01_Background_Image.js b/src/data/examples/ko/05_Image/01_Background_Image.js
        index 6e1274d696..2dd361abad 100644
        --- a/src/data/examples/ko/05_Image/01_Background_Image.js
        +++ b/src/data/examples/ko/05_Image/01_Background_Image.js
        @@ -1,34 +1,18 @@
         /*
        -<<<<<<< HEAD
          * @name 배경 이미지
          * @description 이 예제는 배경 이미지를 불러오는 가장 빠른 방법을 소개합니다. This example presents the fastest way to load a
          * 이미지 파일을 배경으로 쓰기 위해선, 이미지의 너비와 높이를 
          * 프로그램 화면 크기와 동일하게 맞추면 됩니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        -=======
        - * @name Background Image
        - * @description This example presents the fastest way to load a
        - * background image. To load an image as the background,
        - * it must be the same width and height as the program.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let bg;
         let y = 0;
         
         function setup() {
        -<<<<<<< HEAD
           // 이미지 파일을 배경으로 쓰기 위해, createCanvas() 메소드의 인수에
           // 이미지 크기와 동일한 사이즈를 기입하면 됩니다.
           // 이 예제의 경우, 이미지 크기는 720x400 픽셀입니다.
        -=======
        -  // The background image must be the same size as the parameters
        -  // into the createCanvas() method. In this program, the size of
        -  // the image is 720x400 pixels.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           bg = loadImage('assets/moonwalk.jpg');
           createCanvas(720, 400);
         }
        diff --git a/src/data/examples/ko/05_Image/02_Transparency.js b/src/data/examples/ko/05_Image/02_Transparency.js
        index 5665a76889..dd608742d3 100644
        --- a/src/data/examples/ko/05_Image/02_Transparency.js
        +++ b/src/data/examples/ko/05_Image/02_Transparency.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 투명도
          * @description 마우스 포인터를 좌우로 움직혀 이미지의 위치를 옮겨보세요.
          * 이 예제의 경우, tint()함수로 알파값이 수정된 이미지를 원본 이미지에 위에 겹쳐 보여줍니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        -=======
        - * @name Transparency
        - * @description Move the pointer left and right across the image to change its
        - * position. This program overlays one image over another by modifying the
        - * alpha value of the image with the tint() function.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let img;
         let offset = 0;
        @@ -21,7 +11,6 @@ let easing = 0.05;
         
         function setup() {
           createCanvas(720, 400);
        -<<<<<<< HEAD
           img = loadImage('assets/moonwalk.jpg'); // 프로그램상 이미지 불러오기
         }
         
        @@ -30,15 +19,5 @@ function draw() {
           let dx = mouseX - img.width / 2 - offset;
           offset += dx * easing;
           tint(255, 127); // 이미지를 투명도 50%로 보이게하기
        -=======
        -  img = loadImage('assets/moonwalk.jpg'); // Load an image into the program
        -}
        -
        -function draw() {
        -  image(img, 0, 0); // Display at full opacity
        -  let dx = mouseX - img.width / 2 - offset;
        -  offset += dx * easing;
        -  tint(255, 127); // Display at half opacity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           image(img, offset, 0);
         }
        diff --git a/src/data/examples/ko/05_Image/03_Alpha_Mask.js b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        index 94fe5218d4..ad500307c6 100644
        --- a/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        +++ b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 알파 마스크
          * @description 이미지 일부의 투명도를 설정하기 위해 마스크를 불러옵니다.
          * 이미지와 마스크는 p5.Image의 mask() 메소드를 통해 합쳐집니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        -=======
        - * @name Alpha Mask
        - * @description Loads a "mask" for an image to specify the transparency in
        - * different parts of the image. The two images are blended together using
        - * the mask() method of p5.Image.
        - * <p><em><span class="small"> To run this example locally, you will need two
        - * image files, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let img;
         let imgMask;
        diff --git a/src/data/examples/ko/05_Image/04_Create_Image.js b/src/data/examples/ko/05_Image/04_Create_Image.js
        index bb37872c51..a051fcb02e 100644
        --- a/src/data/examples/ko/05_Image/04_Create_Image.js
        +++ b/src/data/examples/ko/05_Image/04_Create_Image.js
        @@ -1,15 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 이미지 만들기
          * @description createImage() 함수로 재밌는 픽셀 버퍼를 만들 수 있습니다.
          * 이 예제는 그래디언트 이미지를 만듭니다.
        -=======
        - * @name Create Image
        - * @description The createImage() function provides a fresh buffer of pixels to
        - * play with. This example creates an image gradient.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
        -let img; // Declare variable 'img'.
        +let img; // 'img' 변수 선언하기
         
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/05_Image/05_Pointillism.js b/src/data/examples/ko/05_Image/05_Pointillism.js
        index 97ab086689..04a9391294 100644
        --- a/src/data/examples/ko/05_Image/05_Pointillism.js
        +++ b/src/data/examples/ko/05_Image/05_Pointillism.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 점묘법
          * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스의 가로 위치는 점의 크기를 조정합니다. 
          * 픽셀에 따라 색칠된 원형(ellipse)으로 간단한 점묘법 효과를 만듭니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        -=======
        - * @name Pointillism
        - * @description By Dan Shiffman. Mouse horizontal location controls size of
        - * dots. Creates a simple pointillist effect using ellipses colored according
        - * to pixels in an image.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let img;
         let smallPoint, largePoint;
        diff --git a/src/data/examples/ko/07_Color/00_Hue.js b/src/data/examples/ko/07_Color/00_Hue.js
        index 530705c4b4..3719823704 100644
        --- a/src/data/examples/ko/07_Color/00_Hue.js
        +++ b/src/data/examples/ko/07_Color/00_Hue.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 색조
          * @description 색조는 오브젝트에 반사되거나 이를 통해 전달된 색상을 말하며,
          * 일반적으로 색상명(빨강, 파랑, 노랑 등)으로 불립니다.
          * 마우스 커서를 세로축으로 움직여 막대기의 색조를 변경해 보세요.
        -=======
        - * @name Hue
        - * @description Hue is the color reflected from or transmitted through an
        - * object and is typically referred to as the name of the color (red, blue,
        - * yellow, etc.) Move the cursor vertically over each bar to alter its hue.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/ko/07_Color/01_Saturation.js b/src/data/examples/ko/07_Color/01_Saturation.js
        index 50ced941fc..0e9cb3fff6 100644
        --- a/src/data/examples/ko/07_Color/01_Saturation.js
        +++ b/src/data/examples/ko/07_Color/01_Saturation.js
        @@ -1,16 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 채도
          * @description 채도는 회색이 차지하는 비율에 따른, 색조의 짙음 또는 맑음 정도를 말합니다.
          * 포화된 색은 맑고, 불포화된 색은 높은 비율의 회색조를 갖습니다.
          * 마우스 커서를 세로축으로 움직여 막대기의 채도를 변경해 보세요.
        -=======
        - * @name Saturation
        - * @description Saturation is the strength or purity of the color and
        - * represents the amount of gray in proportion to the hue. A "saturated"
        - * color is pure and an "unsaturated" color has a large percentage of gray.
        - * Move the cursor vertically over each bar to alter its saturation.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/ko/07_Color/02_Brightness.js b/src/data/examples/ko/07_Color/02_Brightness.js
        index 424e06e3bf..46352ed4bb 100644
        --- a/src/data/examples/ko/07_Color/02_Brightness.js
        +++ b/src/data/examples/ko/07_Color/02_Brightness.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 밝기
          * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스와 각 픽셀 간의 거리값을 
          * 계산하여 이미지 일부의 밝기를 조정합니다. 
          * <p><em><span class="small"> 로컬 컴퓨터에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
        -=======
        - * @name Brightness
        - * @description By Dan Shiffman. This program adjusts the brightness of a part
        - * of the image by calculating the distance of each pixel to the mouse.
        - * <p><em><span class="small"> To run this example locally, you will need
        - * at least an image file and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let img;
         
        @@ -29,34 +21,19 @@ function setup() {
         function draw() {
           for (let x = 0; x < img.width; x++) {
             for (let y = 0; y < img.height; y++) {
        -<<<<<<< HEAD
               // 2D 그리드로부터 1차원 위치 계산
               let loc = (x + y * img.width) * 4;
               // 이미지에서 R,G,B값 받기
               let r, g, b;
               r = img.pixels[loc];
               // 마우스와의 거리에 따라 변경할 밝기 계산
        -=======
        -      // Calculate the 1D location from a 2D grid
        -      let loc = (x + y * img.width) * 4;
        -      // Get the R,G,B values from image
        -      let r, g, b;
        -      r = img.pixels[loc];
        -      // Calculate an amount to change brightness based on proximity to the mouse
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               let maxdist = 50;
               let d = dist(x, y, mouseX, mouseY);
               let adjustbrightness = (255 * (maxdist - d)) / maxdist;
               r += adjustbrightness;
        -<<<<<<< HEAD
               // RGB의 색상 범위가 0-255에 국한되도록 설정
               r = constrain(r, 0, 255);
               // 새로운 색상 생성 후 화면에 픽셀 위치 고정
        -=======
        -      // Constrain RGB to make sure they are within 0-255 color range
        -      r = constrain(r, 0, 255);
        -      // Make a new color and set pixel in the window
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               //color c = color(r, g, b);
               let pixloc = (y * width + x) * 4;
               pixels[pixloc] = r;
        diff --git a/src/data/examples/ko/07_Color/03_Color_Variables.js b/src/data/examples/ko/07_Color/03_Color_Variables.js
        index d6f42df03d..5c3aa3d911 100644
        --- a/src/data/examples/ko/07_Color/03_Color_Variables.js
        +++ b/src/data/examples/ko/07_Color/03_Color_Variables.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 색상 변수
          * @description (Albers에게 바칩니다.) 이 예제는 색상 조정을 위한 변수 생성 방법을 다룹니다.
          * 이 때, 변수들은 숫자가 아닌 특정 명칭으로 지정됩니다.
        -=======
        - * @name Color Variables
        - * @description (Homage to Albers.) This example creates variables for colors
        - * that may be referred to in the program by a name, rather than a number.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400);
        @@ -18,13 +12,8 @@ function setup() {
           let middle = color(204, 153, 0);
           let outside = color(153, 51, 0);
         
        -<<<<<<< HEAD
           // 아래의 변수 선언문은 위의 선언문들과 동일합니다.
           // 둘 중 원하는 형식을 사용하면 됩니다.
        -=======
        -  // These statements are equivalent to the statements above.
        -  // Programmers may use the format they prefer.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           //let inside = color('#CC6600');
           //let middle = color('#CC9900');
           //let outside = color('#993300');
        diff --git a/src/data/examples/ko/07_Color/04_Relativity.js b/src/data/examples/ko/07_Color/04_Relativity.js
        index 7788296f68..f54aef95d9 100644
        --- a/src/data/examples/ko/07_Color/04_Relativity.js
        +++ b/src/data/examples/ko/07_Color/04_Relativity.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 상대성
          * @description 각 색상은 다른 색상과의 관계 속에서 인식됩니다. 
          * 상단과 하단의 막대기들은 둘 다 동일한 색상 요소들을 갖지만,
          * 색상 요소들의 배열에 따라 마치 다른 색조를 갖는 듯 보입니다.
        -=======
        - * @name Relativity
        - * @description Each color is perceived in relation to other colors. The top
        - * and bottom bars each contain the same component colors, but a different
        - * display order causes individual colors to appear differently.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let a, b, c, d, e;
         
        @@ -21,11 +14,7 @@ function setup() {
           c = color(42, 106, 105);
           d = color(165, 89, 20);
           e = color(146, 150, 127);
        -<<<<<<< HEAD
           noLoop(); // 반복없이 한번만 그리기
        -=======
        -  noLoop(); // Draw only one time
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/07_Color/05_Linear_Gradient.js b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        index f73ad3f442..95c2feb2ca 100644
        --- a/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        +++ b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        @@ -1,14 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 선형 그래디언트
          * @description lerpColor() 함수는 두 가지 색상을 보간하는 데에 쓰입니다.
        -=======
        - * @name Linear Gradient
        - * @description The lerpColor() function is useful for interpolating between
        - * two colors.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
        -// Constants
        +// 상수
         const Y_AXIS = 1;
         const X_AXIS = 2;
         let b1, b2, c1, c2;
        @@ -16,7 +10,7 @@ let b1, b2, c1, c2;
         function setup() {
           createCanvas(710, 400);
         
        -  // Define colors
        +  // 색상 정의하기
           b1 = color(255);
           b2 = color(0);
           c1 = color(204, 102, 0);
        @@ -26,10 +20,10 @@ function setup() {
         }
         
         function draw() {
        -  // Background
        +  // 배경
           setGradient(0, 0, width / 2, height, b1, b2, X_AXIS);
           setGradient(width / 2, 0, width / 2, height, b2, b1, X_AXIS);
        -  // Foreground
        +  // 전경
           setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
           setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
         }
        @@ -38,7 +32,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
           noFill();
         
           if (axis === Y_AXIS) {
        -    // Top to bottom gradient
        +    // 위에서 아래 방향 그래디언트
             for (let i = y; i <= y + h; i++) {
               let inter = map(i, y, y + h, 0, 1);
               let c = lerpColor(c1, c2, inter);
        @@ -46,7 +40,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
               line(x, i, x + w, i);
             }
           } else if (axis === X_AXIS) {
        -    // Left to right gradient
        +    // 왼쪽에서 오른쪽 방향 그래디언트
             for (let i = x; i <= x + w; i++) {
               let inter = map(i, x, x + w, 0, 1);
               let c = lerpColor(c1, c2, inter);
        diff --git a/src/data/examples/ko/07_Color/07_Lerp_Color.js b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        index 0deff288fd..0c1324183f 100644
        --- a/src/data/examples/ko/07_Color/07_Lerp_Color.js
        +++ b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 선형 보간(lerp) 색상
          * @description 무작위의 도형을 반복하고,
          * 빨강색과 파란색을 선형적으로 보간합니다.
        -=======
        - * @name Lerp Color
        - * @description Loop random shapes,
        - * lerp color from red to blue.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/08_Math/00_incrementdecrement.js b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        index 021d1668a7..2fa2db7120 100644
        --- a/src/data/examples/ko/08_Math/00_incrementdecrement.js
        +++ b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 증가와 감소
          * @description "a++"는 "a = a + 1"와 같은 표현입니다.
          * "a--"는 "a = a - 1"과 같은 표현입니다.
        -=======
        - * @name Increment Decrement
        - * @description Writing "a++" is equivalent to "a = a + 1".
        - * Writing "a--" is equivalent to "a = a - 1".
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let a;
         let b;
        diff --git a/src/data/examples/ko/08_Math/01_operatorprecedence.js b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        index cd3248c6b7..16ce85b29b 100644
        --- a/src/data/examples/ko/08_Math/01_operatorprecedence.js
        +++ b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 연산자 우선 순위
          * @description 연산자의 실행 순서를 명시하는 경우를 제하고, 모든 선언문은 연산자 우선 순위에 따라
          * 처리됩니다. 예를 들어, "4+2*8"에서 2는 가장 먼저 8에 곱해지고, 그 결과값이 4에 더해집니다.
        @@ -17,28 +16,6 @@
         // 논리 연산자 AND: &&
         // 논리 연산자 OR: ||
         // 할당 연산자: = += -= *= /= %=
        -=======
        - * @name Operator Precedence
        - * @description If you don't explicitly state the order in which an
        - * expression is evaluated, they are evaluated based on the operator
        - * precedence. For example, in the statement "4+2*8", the 2 will
        - * first be multiplied by 8 and then the result will be added to 4.
        - * This is because the "*" has a higher precedence than the "+". To avoid
        - * ambiguity in reading the program, it is recommended that is statement
        - * is written as "4+(2*8)". The order of evaluation can be controlled
        - * through placement of parenthesis in the code. A table of operator
        - * precedence follows below.
        - */
        -// The highest precedence is at the top of the list and
        -// the lowest is at the bottom.
        -// Multiplicative: * / %
        -// Additive: + -
        -// Relational: < > <= >=
        -// Equality: == !=
        -// Logical AND: &&
        -// Logical OR: ||
        -// Assignment: = += -= *= /= %=
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function setup() {
           createCanvas(710, 400);
           background(51);
        @@ -47,42 +24,25 @@ function setup() {
         
           stroke(204);
           for (let i = 0; i < width - 20; i += 4) {
        -<<<<<<< HEAD
             // 70이 30을 더한 결과값이
             // 현재 "i"값보다 큰 지의 여부를 평가
             // 처리 순서를 명확히하고자 "if (i > (30 + 70)) {"로 작성
        -=======
        -    // The 30 is added to 70 and then evaluated
        -    // if it is greater than the current value of "i"
        -    // For clarity, write as "if (i > (30 + 70)) {"
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (i > 30 + 70) {
               line(i, 0, i, 50);
             }
           }
         
           stroke(255);
        -<<<<<<< HEAD
           // 2와 8을 곱한 뒤, 그 결과값에 4를 더함
           // 처리 순서를 명확히하고자, "rect(5 + (2 * 8), 0, 90, 20);"로 작성
        -=======
        -  // The 2 is multiplied by the 8 and the result is added to the 4
        -  // For clarity, write as "rect(5 + (2 * 8), 0, 90, 20);"
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rect(4 + 2 * 8, 52, 290, 48);
           rect((4 + 2) * 8, 100, 290, 49);
         
           stroke(153);
        -  for (let i = 0; i < width; i += 2) {
        -<<<<<<< HEAD
        +  for (let i = 0; i < width; i += 2) {<<<<<<< HEAD
             // 비교 선언문을 가장 먼저 처리한 뒤,
             // 다음으로 논리 연산자 AND, 마지막으로 논리 연산자 OR 순으로 처리.
             // 처리 순서를 명확히하고자 다음과 같이 작성:
        -=======
        -    // The relational statements are evaluated
        -    // first, and then the logical AND statements and
        -    // finally the logical OR. For clarity, write as:
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             // "if(((i > 20) && (i < 50)) || ((i > 100) && (i < width-20))) {"
             if ((i > 20 && i < 50) || (i > 100 && i < width - 20)) {
               line(i, 151, i, height - 1);
        diff --git a/src/data/examples/ko/08_Math/02_distance1d.js b/src/data/examples/ko/08_Math/02_distance1d.js
        index 3c61c197f0..36e93c6904 100644
        --- a/src/data/examples/ko/08_Math/02_distance1d.js
        +++ b/src/data/examples/ko/08_Math/02_distance1d.js
        @@ -1,12 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 1D 거리
          * @description 마우스를 좌우로 움직여, 화면 속 도형의 움직임 속도와 방향을 조정해보세요.
        -=======
        - * @name Distance 1D
        - * @description Move the mouse left and right to control
        - * the speed and direction of the moving shapes.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let xpos1;
         let xpos2;
        diff --git a/src/data/examples/ko/08_Math/03_distance2d.js b/src/data/examples/ko/08_Math/03_distance2d.js
        index 4416e7b9b3..3fa5d7efa0 100644
        --- a/src/data/examples/ko/08_Math/03_distance2d.js
        +++ b/src/data/examples/ko/08_Math/03_distance2d.js
        @@ -1,14 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 2D 거리
          * @description 이미지 위로 마우스를 움직여, 매트릭스를 흐리게 또는 뚜렷하게 만들어보세요.
          * 각 타원과 마우스 간의 거리에 비례하여 원형의 크기가 조정됩니다.
        -=======
        - * @name Distance 2D
        - * @description Move the mouse across the image to obscure
        - * and reveal the matrix. Measures the distance from the mouse
        - * to each circle and sets the size proportionally.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let max_distance;
         
        diff --git a/src/data/examples/ko/08_Math/04_sine.js b/src/data/examples/ko/08_Math/04_sine.js
        index 586af08bcb..566b2faa99 100644
        --- a/src/data/examples/ko/08_Math/04_sine.js
        +++ b/src/data/examples/ko/08_Math/04_sine.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 싸인
          * @description sin() 함수로 도형의 크기를 부드럽게 조정합니다.
        -=======
        - * @name Sine
        - * @description Smoothly scaling size with the sin() function.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let diameter;
         let angle = 0;
        diff --git a/src/data/examples/ko/08_Math/05_sincosine.js b/src/data/examples/ko/08_Math/05_sincosine.js
        index 62a78835b1..dbb6fd2b42 100644
        --- a/src/data/examples/ko/08_Math/05_sincosine.js
        +++ b/src/data/examples/ko/08_Math/05_sincosine.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 싸인 코싸인
          * @description sin()와 cos() 함수를 이용한 선형적 움직임.
          * 0과 PI*2 사이의 숫자(TWO_PI의 경우, 약 6.28)를 위의 함수에 넣으면
          * -1과 1 사이의 값이 반환됩니다.
          * 이러한 반환값은 더 큰 움직임을 만드는 척도로서 쓰입니다.
        -=======
        - * @name Sine Cosine
        - * @description Linear movement with sin() and cos().
        - * Numbers between 0 and PI*2 (TWO_PI which angles roughly 6.28)
        - * are put into these functions and numbers between -1 and 1 are returned.
        - * These values are then scaled to produce larger movements.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let angle1 = 0;
         let angle2 = 0;
        diff --git a/src/data/examples/ko/08_Math/06_sinewave.js b/src/data/examples/ko/08_Math/06_sinewave.js
        index 0638d55013..46ca3fe589 100644
        --- a/src/data/examples/ko/08_Math/06_sinewave.js
        +++ b/src/data/examples/ko/08_Math/06_sinewave.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 싸인파
          * @description 간단한 싸인파를 만듭니다.
          * 다니엘 쉬프만(Daniel Shiffman)이 원본 제작.
        @@ -12,20 +11,6 @@ let amplitude = 75.0; // 파형의 높이
         let period = 500.0; // 파형이 반복되기 전까지 생성되는 픽셀 갯수
         let dx; // x 증가값
         let yvalues; // 파형의 최고 높이를 저장하기 위한 배열
        -=======
        - * @name Sine Wave
        - * @description Render a simple sine wave.
        - * Original by Daniel Shiffman.
        - */
        -
        -let xspacing = 16; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let theta = 0.0; // Start angle at 0
        -let amplitude = 75.0; // Height of wave
        -let period = 500.0; // How many pixels before the wave repeats
        -let dx; // Value for incrementing x
        -let yvalues; // Using an array to store height values for the wave
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(710, 400);
        @@ -41,18 +26,10 @@ function draw() {
         }
         
         function calcWave() {
        -<<<<<<< HEAD
           // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
           theta += 0.02;
         
           // 매 x값마다 싸인 함수를 이용해 y값을 계산
        -=======
        -  // Increment theta (try different values for
        -  // 'angular velocity' here)
        -  theta += 0.02;
        -
        -  // For every x value, calculate a y value with sine function
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let x = theta;
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = sin(x) * amplitude;
        @@ -63,11 +40,7 @@ function calcWave() {
         function renderWave() {
           noStroke();
           fill(255);
        -<<<<<<< HEAD
           // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
        -=======
        -  // A simple way to draw the wave with an ellipse at each location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let x = 0; x < yvalues.length; x++) {
             ellipse(x * xspacing, height / 2 + yvalues[x], 16, 16);
           }
        diff --git a/src/data/examples/ko/08_Math/07_additivewave.js b/src/data/examples/ko/08_Math/07_additivewave.js
        index 67adc0826c..46694c8c10 100644
        --- a/src/data/examples/ko/08_Math/07_additivewave.js
        +++ b/src/data/examples/ko/08_Math/07_additivewave.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 파형 추가
          * @description 두 개의 파형을 합쳐 좀 더 복잡한 파도 모양을 만듭니다.
          * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
        @@ -13,23 +12,6 @@ let amplitude = new Array(maxwaves); // 파형의 높이
         // X를 증가하는 값으로, period와 xspacing로 계산됨
         let dx = new Array(maxwaves);
         // 파형의 최고 높이를 저장하기 위한 배열 (반드시 필요한 건 아님)
        -=======
        - * @name Additive Wave
        - * @description Create a more complex wave by adding two waves together.
        - * Original by Daniel Shiffman
        - */
        -let xspacing = 8; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let maxwaves = 4; // total # of waves to add together
        -
        -let theta = 0.0;
        -let amplitude = new Array(maxwaves); // Height of wave
        -// Value for incrementing X, to be calculated
        -// as a function of period and xspacing
        -let dx = new Array(maxwaves);
        -// Using an array to store height values
        -// for the wave (not entirely necessary)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let yvalues;
         
         function setup() {
        @@ -40,11 +22,7 @@ function setup() {
         
           for (let i = 0; i < maxwaves; i++) {
             amplitude[i] = random(10, 30);
        -<<<<<<< HEAD
             let period = random(100, 300); // 파형이 반복되기 전까지 생성되는 픽셀 갯수
        -=======
        -    let period = random(100, 300); // Num pixels before wave repeats
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             dx[i] = (TWO_PI / period) * xspacing;
           }
         
        @@ -58,35 +36,19 @@ function draw() {
         }
         
         function calcWave() {
        -<<<<<<< HEAD
           // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
           theta += 0.02;
         
           // 모든 높이값을 0으로 설정
        -=======
        -  // Increment theta (try different values
        -  // for 'angular velocity' here
        -  theta += 0.02;
        -
        -  // Set all height values to zero
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = 0;
           }
         
        -<<<<<<< HEAD
           // 파형 높이값 축적하기
           for (let j = 0; j < maxwaves; j++) {
             let x = theta;
             for (let i = 0; i < yvalues.length; i++) {
               // 매번 모든 파형들은 싸인 대신 코싸인으로 처리
        -=======
        -  // Accumulate wave height values
        -  for (let j = 0; j < maxwaves; j++) {
        -    let x = theta;
        -    for (let i = 0; i < yvalues.length; i++) {
        -      // Every other wave is cosine instead of sine
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               if (j % 2 == 0) yvalues[i] += sin(x) * amplitude[j];
               else yvalues[i] += cos(x) * amplitude[j];
               x += dx[j];
        @@ -95,11 +57,7 @@ function calcWave() {
         }
         
         function renderWave() {
        -<<<<<<< HEAD
           // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
        -=======
        -  // A simple way to draw the wave with an ellipse at each location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noStroke();
           fill(255, 50);
           ellipseMode(CENTER);
        diff --git a/src/data/examples/ko/08_Math/08_polartocartesian.js b/src/data/examples/ko/08_Math/08_polartocartesian.js
        index 89e88067ed..16907e4cfd 100644
        --- a/src/data/examples/ko/08_Math/08_polartocartesian.js
        +++ b/src/data/examples/ko/08_Math/08_polartocartesian.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 극좌표를 직교 좌표로
          * @description 극좌표(지름 r, 세타 theta)를 직교 좌표(x,y)로 변환
          * : x = rcos(theta) y = rsin(theta)
        @@ -8,16 +7,6 @@
         let r;
         
         // 각도, 각속도, 가속
        -=======
        - * @name PolarToCartesian
        - * @description Convert a polar coordinate (r,theta)
        - * to cartesian (x,y): x = rcos(theta) y = rsin(theta)
        - * Original by Daniel Shiffman.
        - */
        -let r;
        -
        -// Angle and angular velocity, accleration
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let theta;
         let theta_vel;
         let theta_acc;
        @@ -25,11 +14,7 @@ let theta_acc;
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 모든값 초기화
        -=======
        -  // Initialize all values
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           r = height * 0.45;
           theta = 0;
           theta_vel = 0;
        @@ -39,7 +24,6 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           // 원점을 화면 중간 위치에 해당하는 좌표값으로 설정
           translate(width / 2, height / 2);
         
        @@ -48,28 +32,13 @@ function draw() {
           let y = r * sin(theta);
         
           // 직교 좌표에서 타원 그리기
        -=======
        -  // Translate the origin point to the center of the screen
        -  translate(width / 2, height / 2);
        -
        -  // Convert polar to cartesian
        -  let x = r * cos(theta);
        -  let y = r * sin(theta);
        -
        -  // Draw the ellipse at the cartesian coordinate
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           ellipseMode(CENTER);
           noStroke();
           fill(200);
           ellipse(x, y, 32, 32);
         
        -<<<<<<< HEAD
           // 가속도와 속도를 각도에 적용하기
           // (이 예제에서 r은 고정됩니다.)
        -=======
        -  // Apply acceleration and velocity to angle
        -  // (r remains static in this example)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           theta_vel += theta_acc;
           theta += theta_vel;
         }
        diff --git a/src/data/examples/ko/08_Math/09_arctangent.js b/src/data/examples/ko/08_Math/09_arctangent.js
        index 387cca2288..21c053b7fd 100644
        --- a/src/data/examples/ko/08_Math/09_arctangent.js
        +++ b/src/data/examples/ko/08_Math/09_arctangent.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 아크탄젠트
          * @description 마우스를 움직여 눈의 방향을 바꿔보세요. <br>atan2()함수는 마우스 커서와 눈의 각도를 계산합니다.
        -=======
        - * @name Arctangent
        - * @description Move the mouse to change the direction of the eyes.<br>The atan2() function computes the angle from each eye to the cursor.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let e1, e2, e3;
         
        diff --git a/src/data/examples/ko/08_Math/10_Interpolate.js b/src/data/examples/ko/08_Math/10_Interpolate.js
        index ff45815456..eff9e09115 100644
        --- a/src/data/examples/ko/08_Math/10_Interpolate.js
        +++ b/src/data/examples/ko/08_Math/10_Interpolate.js
        @@ -1,20 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 선형 보간법
          * @frame 720, 400
          * @description 화면 위로 마우스를 움직이면 타원이 따라옵니다.
          * 애니메이션의 매 프레임 사이에, 타원은 현재 위치에서 커서를 향해 지정된 거리(0.05)의 일부만큼 움직입니다.
          * 이는 lerp() 함수를 사용하여 구현된 것입니다.
          * 이 예제는 인풋>이징(Easing) 예제와 동일한 효과를 만들지만, lerp()만으로 구현한다는 점에서 다릅니다.
        -=======
        - * @name Linear Interpolation
        - * @frame 720, 400
        - * @description Move the mouse across the screen and the symbol will follow.
        - * Between drawing each frame of the animation, the ellipse moves part
        - * of the distance (0.05) from its current position toward the cursor using
        - * the lerp() function.
        - * This is the same as the Easing under input only with lerp() instead..
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let x = 0;
        @@ -28,20 +18,11 @@ function setup() {
         function draw() {
           background(51);
         
        -<<<<<<< HEAD
           // lerp()는 특정 값만큼 증가하는 두 개의 숫자로부터 결과값을 계산합니다.
           // amt인수는 이 두 개의 숫자를 선형적으로 결정하는데,
           // 0.0은 처음 위치, 0.1은 첫번째 점과 아주 가까운 위치, 0.5는 앞의 두 점의 중간 위치인 식입니다.
         
           // 매 프레임마다 마우스 위치를 향해 5%의 거리를 움직이도록 합니다.
        -=======
        -  // lerp() calculates a number between two numbers at a specific increment.
        -  // The amt parameter is the amount to interpolate between the two values
        -  // where 0.0 equal to the first point, 0.1 is very near the first point, 0.5
        -  // is half-way in between, etc.
        -
        -  // Here we are moving 5% of the way to the mouse location each frame
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           x = lerp(x, mouseX, 0.05);
           y = lerp(y, mouseY, 0.05);
         
        diff --git a/src/data/examples/ko/08_Math/11_doubleRandom.js b/src/data/examples/ko/08_Math/11_doubleRandom.js
        index 5abd9f7b01..de03e23121 100644
        --- a/src/data/examples/ko/08_Math/11_doubleRandom.js
        +++ b/src/data/examples/ko/08_Math/11_doubleRandom.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Double Random
        + * @name 이중 랜덤
          * @frame 720,400 (optional)
        - * @description Using two random() calls and the point()
        - * function to create an irregular sawtooth line.
        - * Original by by Ira Greenberg.
        + * @description random() 호출과 point()함수를 이중으로 사용하여 
        + * 불규칙한 톱니 모양의 선을 만듭니다.
        + * 원본 제작: 이라 그린버그(Ira Greenberg)
          */
         let totalPts = 300;
         let steps = totalPts + 1;
        diff --git a/src/data/examples/ko/08_Math/12_random.js b/src/data/examples/ko/08_Math/12_random.js
        index 6475297be5..558f3beebf 100644
        --- a/src/data/examples/ko/08_Math/12_random.js
        +++ b/src/data/examples/ko/08_Math/12_random.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Random
        - * @description Random numbers create the basis of this image.
        - * Each time the program is loaded the result is different.
        + * @name 랜덤
        + * @description 난수(random number)에 근간을 둔 이미지입니다.
        + * 프로그램이 불러오기될 때마다 결과가 달라집니다.
          */
         function setup() {
           createCanvas(710, 400);
        diff --git a/src/data/examples/ko/08_Math/13_noise1D.js b/src/data/examples/ko/08_Math/13_noise1D.js
        index 6d2e12767c..6d9fb9ca69 100644
        --- a/src/data/examples/ko/08_Math/13_noise1D.js
        +++ b/src/data/examples/ko/08_Math/13_noise1D.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 1D 노이즈
          * @description 1차원 펄린 노이즈를 사용해 위치를 지정합니다.
        -=======
        - * @name Noise1D
        - * @description Using 1D Perlin Noise to assign location.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let xoff = 0.0;
         let xincrement = 0.01;
        @@ -17,7 +12,6 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 알파값이 섞인 배경 생성
           fill(0, 10);
           rect(0, 0, width, height);
        @@ -32,22 +26,6 @@ function draw() {
           xoff += xincrement;
         
           // 펄린 노이즈가 생성한 값으로 타원 그리기
        -=======
        -  // Create an alpha blended background
        -  fill(0, 10);
        -  rect(0, 0, width, height);
        -
        -  //let n = random(0,width);  // Try this line instead of noise
        -
        -  // Get a noise value based on xoff and scale
        -  // it according to the window's width
        -  let n = noise(xoff) * width;
        -
        -  // With each cycle, increment xoff
        -  xoff += xincrement;
        -
        -  // Draw the ellipse at the value produced by perlin noise
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(200);
           ellipse(n, height / 2, 64, 64);
         }
        diff --git a/src/data/examples/ko/08_Math/14_noisewave.js b/src/data/examples/ko/08_Math/14_noisewave.js
        index 06877dc386..ca8d2ad731 100644
        --- a/src/data/examples/ko/08_Math/14_noisewave.js
        +++ b/src/data/examples/ko/08_Math/14_noisewave.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 노이즈 파형
          * @description 펄린 노이즈를 사용하여 파도같은 패턴을 만듭니다.
          * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
          */
         let yoff = 0.0; // 펄린 노이즈의 2차원
        -=======
        - * @name Noise Wave
        - * @description Using Perlin Noise to generate a wave-like pattern.
        - * Original by Daniel Shiffman.
        - */
        -let yoff = 0.0; // 2nd dimension of perlin noise
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(710, 400);
        @@ -21,7 +13,6 @@ function draw() {
           background(51);
         
           fill(255);
        -<<<<<<< HEAD
           // 파형의 점들을 이용한 다각형 그리기
           beginShape();
         
        @@ -44,30 +35,6 @@ function draw() {
             xoff += 0.05;
           }
           // 노이즈의 y차원 증가하기
        -=======
        -  // We are going to draw a polygon out of the wave points
        -  beginShape();
        -
        -  let xoff = 0; // Option #1: 2D Noise
        -  // let xoff = yoff; // Option #2: 1D Noise
        -
        -  // Iterate over horizontal pixels
        -  for (let x = 0; x <= width; x += 10) {
        -    // Calculate a y value according to noise, map to
        -
        -    // Option #1: 2D Noise
        -    let y = map(noise(xoff, yoff), 0, 1, 200, 300);
        -
        -    // Option #2: 1D Noise
        -    // let y = map(noise(xoff), 0, 1, 200,300);
        -
        -    // Set the vertex
        -    vertex(x, y);
        -    // Increment x dimension for noise
        -    xoff += 0.05;
        -  }
        -  // increment y dimension for noise
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           yoff += 0.01;
           vertex(width, height);
           vertex(0, height);
        diff --git a/src/data/examples/ko/08_Math/15_Noise2D.js b/src/data/examples/ko/08_Math/15_Noise2D.js
        index 271165bd83..16091565b7 100644
        --- a/src/data/examples/ko/08_Math/15_Noise2D.js
        +++ b/src/data/examples/ko/08_Math/15_Noise2D.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 2D 노이즈
          * @frame 710,400 (optional)
          * @description 여러 인수를 사용하여 2D 노이즈를 만들어보세요.
        -=======
        - * @name Noise2D
        - * @frame 710,400 (optional)
        - * @description Create a 2D noise with different parameters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          *
          */
         
        @@ -20,51 +14,29 @@ function setup() {
         
         function draw() {
           background(0);
        -<<<<<<< HEAD
           // 이미지의 좌측 절반 그리기
           for (let y = 0; y < height - 30; y++) {
             for (let x = 0; x < width / 2; x++) {
               // noiceDetail, 픽셀 옥타브와 번짐 정도
        -=======
        -  // Draw the left half of image
        -  for (let y = 0; y < height - 30; y++) {
        -    for (let x = 0; x < width / 2; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               noiseDetail(2, 0.2);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -<<<<<<< HEAD
           // 이미지의 우측 절반 그리기
           for (let y = 0; y < height - 30; y++) {
             for (let x = width / 2; x < width; x++) {
               // noiceDetail, 픽셀 옥타브와 번짐 정도
        -=======
        -  // Draw the right half of image
        -  for (let y = 0; y < height - 30; y++) {
        -    for (let x = width / 2; x < width; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               noiseDetail(5, 0.5);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -<<<<<<< HEAD
           //두 화면의 디테일 구성하기
           textSize(18);
           fill(255, 255, 255);
           text('2옥타브와 0.2 번짐 정도의 2D 노이즈', 10, 350);
           text('1옥타브와 0.7 번짐 정도의 2D 노이즈', 330, 350);
        -=======
        -  //Show the details of two partitions
        -  textSize(18);
        -  fill(255, 255, 255);
        -  text('Noice2D with 2 octaves and 0.2 falloff', 10, 350);
        -  text('Noice2D with 1 octaves and 0.7 falloff', 330, 350);
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
        diff --git a/src/data/examples/ko/08_Math/16_Noise3D.js b/src/data/examples/ko/08_Math/16_Noise3D.js
        index 3b4e3f4a0b..907a90cfb1 100644
        --- a/src/data/examples/ko/08_Math/16_Noise3D.js
        +++ b/src/data/examples/ko/08_Math/16_Noise3D.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 3D 노이즈
          * @frame 710,400 (optional)
          * @description 3D 노이즈를 사용하여 간단한 동적 텍스쳐를 만듭니다.
        @@ -9,67 +8,35 @@ let noiseVal;
         //x를 0.01씩 증가
         let x_increment = 0.01;
         //draw()함수 사이클 마다 z를 0.02씩 증가
        -=======
        - * @name Noise3D
        - * @frame 710,400 (optional)
        - * @description Using 3D noise to create simple animated texture.
        - */
        -
        -let noiseVal;
        -//Increment x by 0.01
        -let x_increment = 0.01;
        -//Increment z by 0.02 every draw() cycle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let z_increment = 0.02;
         
         //Offset values
         let z_off, y_off, x_off;
         
         function setup() {
        -<<<<<<< HEAD
           //캔버스 만들기
           createCanvas(640, 360);
           //프레임 속도 조정
           frameRate(20);
           //z_off의 초기값
        -=======
        -  //Create the Canvas
        -  createCanvas(640, 360);
        -  //Define frame rate
        -  frameRate(20);
        -  //Initial value of z_off
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           z_off = 0;
         }
         
         function draw() {
           x_off = 0;
           y_off = 0;
        -<<<<<<< HEAD
           //배경을 검정색으로 설정
           background(0);
           //노이즈 디테일 조정
           noiseDetail(8, 0.65);
         
           //매 x,y마다 노이즈값 계산
        -=======
        -  //Make the background black
        -  background(0);
        -  //Adjust the noice detail
        -  noiseDetail(8, 0.65);
        -
        -  //For each x,y calculate noice value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let y = 0; y < height; y++) {
             x_off += x_increment;
             y_off = 0;
         
             for (let x = 0; x < width; x++) {
        -<<<<<<< HEAD
               //각 픽셀을 계산하고 그리기
        -=======
        -      //Calculate and Draw each pixel
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               noiseVal = noise(x_off, y_off, z_off);
               stroke(noiseVal * 255);
               y_off += x_increment;
        diff --git a/src/data/examples/ko/08_Math/17_Randomchords.js b/src/data/examples/ko/08_Math/17_Randomchords.js
        index a4b670ed2c..a5a69dddb4 100644
        --- a/src/data/examples/ko/08_Math/17_Randomchords.js
        +++ b/src/data/examples/ko/08_Math/17_Randomchords.js
        @@ -1,62 +1,35 @@
         /*
        -<<<<<<< HEAD
        - * @name 무작위 선들
        - * @description 원형을 그리는 무작위 선들을 축적합니다.
        + * @name 랜덤 선들
        + * @description 원형을 그리는 무작위의 선들을 축적합니다.
          * 불투명하게 처리된 선들이 축적될수록 마치 명암이 적용된 구처럼 보입니다.
          * 애티쉬 바티아(Aatish Bhatia) 기여, <a href ="http://inconvergent.net/">앤더스 호프(Anders Hoff)</a>로부터 영감을 받음.
        -=======
        - * @name Random Chords
        - * @description Accumulates random chords of a circle. Each chord in translucent
        - * so they accumulate to give the illusion of a shaded sphere.
        - * Contributed by Aatish Bhatia, inspired by <a href ="http://inconvergent.net/">Anders Hoff</a>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         function setup() {
           createCanvas(400, 400);
           background(255, 255, 255);
         
        -<<<<<<< HEAD
           // 알파값을 활용하여 선의 불투명도 조정
        -=======
        -  // translucent stroke using alpha value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(0, 0, 0, 15);
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 매 프레임마다 두 개의 선을 무작위로 그린다
        -=======
        -  // draw two random chords each frame
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           randomChord();
           randomChord();
         }
         
         function randomChord() {
        -<<<<<<< HEAD
           // 원형 위 점 하나를 무작위로 찾는다
        -=======
        -  // find a random point on a circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let angle1 = random(0, 2 * PI);
           let xpos1 = 200 + 200 * cos(angle1);
           let ypos1 = 200 + 200 * sin(angle1);
         
        -<<<<<<< HEAD
           // 원형 위 또다른 점 하나를 무작위로 찾는다
        -=======
        -  // find another random point on the circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let angle2 = random(0, 2 * PI);
           let xpos2 = 200 + 200 * cos(angle2);
           let ypos2 = 200 + 200 * sin(angle2);
         
        -<<<<<<< HEAD
           // 둘 사이에 선을 긋는다
        -=======
        -  // draw a line between them
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           line(xpos1, ypos1, xpos2, ypos2);
         }
        diff --git a/src/data/examples/ko/08_Math/18_Map.js b/src/data/examples/ko/08_Math/18_Map.js
        index ef4adc1c4c..43f81c9bdd 100644
        --- a/src/data/examples/ko/08_Math/18_Map.js
        +++ b/src/data/examples/ko/08_Math/18_Map.js
        @@ -1,18 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 매핑(map)
          * @description map()함수 사용하면 그 어떠한 숫자든 여러분의 프로젝트에 더 많은 도움이 될
          * 숫자로 매핑됩니다.
          * 예를 들어, 마우스 위치값을 사용하여 도형의 크기와 색상을 조정할 수 있습니다.
          * 이 예제에서는 마우스의 x 좌표(0과 360사이의 숫자)가 원형의 색상과 크기를 정의하는 새로운 숫자들로 처리됩니다.
        -=======
        - * @name Map
        - * @description Use the map() function to take any number and scale it to a
        - * new number that is more useful for the project that you are working on.
        - * For example, use the numbers from the mouse position to control the size or color of a shape.
        - * In this example, the mouse’s x-coordinate (numbers between 0 and 360) are scaled to new numbers
        - * to define the color and size of a circle.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(640, 400);
        @@ -21,15 +12,9 @@ function setup() {
         
         function draw() {
           background(0);
        -<<<<<<< HEAD
           // 0부터 640에 이르는 mouseX 값을 0부터 175의 범위로 조정
           let c = map(mouseX, 0, width, 0, 175);
           // 0부터 640에 이르는 mouseX 값을 40부터 300의 범위로 조정
        -=======
        -  // Scale the mouseX value from 0 to 640 to a range between 0 and 175
        -  let c = map(mouseX, 0, width, 0, 175);
        -  // Scale the mouseX value from 0 to 640 to a range between 40 and 300
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let d = map(mouseX, 0, width, 40, 300);
           fill(255, c, 0);
           ellipse(width/2, height/2, d, d);
        diff --git a/src/data/examples/ko/08_Math/19_parametricEquation.js b/src/data/examples/ko/08_Math/19_parametricEquation.js
        new file mode 100644
        index 0000000000..598c45ee3c
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/19_parametricEquation.js
        @@ -0,0 +1,43 @@
        +/*
        + * @name 매개변수 방정식
        + * @description 매겨번수 방정식은 x와 y 좌표값이 다른 문자로서 표기된 식을 말합니다.
        + * 이러한 문자를 매개변수라 부르며, 일반적으로 t 또는 θ로 표기됩니다.
        + * 알렉산더 밀러(Alexander Miller)의 유투브 채널로부터 영감을 얻었습니다.
        + */
        +
        +function setup(){
        +  createCanvas(720,400);
        +}
        +
        +// x와 y의 매개 변수는 일반적으로 세타(theta)를 뜻하는 't' 또는 그 기호(θ)로 표기됩니다.
        +let t = 0;
        +function draw(){
        +  background('#fff');
        +  translate(width/2,height/2);
        +  stroke('#0f0f0f');
        +  strokeWeight(1.5);
        +  //100개의 선 추가를 위한 반복문
        +  for(let i = 0;i<100;i++){
        +    line(x1(t+i),y1(t+i),x2(t+i)+20,y2(t+i)+20);
        +  }
        +  t+=0.15;
        +}
        +// 선의 초기 x 좌표값을 변경하는 함수 
        +function x1(t){
        +  return sin(t/10)*125+sin(t/20)*125+sin(t/30)*125;
        +}
        +
        +// 선의 초기 y 좌표값을 변경하는 함수
        +function y1(t){
        +  return cos(t/10)*125+cos(t/20)*125+cos(t/30)*125;
        +}
        +
        +// 선의 최종 x 좌표값을 변경하는 함수
        +function x2(t){
        +  return sin(t/15)*125+sin(t/25)*125+sin(t/35)*125;
        +}
        +
        +// 선의 최종 y 좌표값을 변경하는 함수
        +function y2(t){
        +  return cos(t/15)*125+cos(t/25)*125+cos(t/35)*125;
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/00_Forces.js b/src/data/examples/ko/09_Simulate/00_Forces.js
        index ae0d523619..ee8b1df54a 100644
        --- a/src/data/examples/ko/09_Simulate/00_Forces.js
        +++ b/src/data/examples/ko/09_Simulate/00_Forces.js
        @@ -1,7 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 힘
        - * @description 바디 오브젝트에 작용하는 여러가지 물리학적 힘
        + * @description 바디 객체에 작용하는 여러가지 물리학적 힘
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         // 바디에 적용되는 여러가지 물리학적 힘(Mover 클래스)
        @@ -9,18 +8,6 @@
         // 바디는 물 속에서 유체 저항을 경험합니다.
         
         // 5개의 움직이는 형체
        -=======
        - * @name Forces
        - * @description Demonstration of multiple force acting on bodies
        - * (<a href="http://natureofcode.com">natureofcode.com</a>)
        - */
        -// Demonstration of multiple force acting on
        -// bodies (Mover class)
        -// Bodies experience gravity continuously
        -// Bodies experience fluid resistance when in "water"
        -
        -// Five moving bodies
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let movers = [];
         
         // Liquid
        @@ -29,27 +16,18 @@ let liquid;
         function setup() {
           createCanvas(640, 360);
           reset();
        -<<<<<<< HEAD
        -  // 액체 오브젝트 생성
        -=======
        -  // Create liquid object
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // liquid(액체) 객체 생성
           liquid = new Liquid(0, height / 2, width, height / 2, 0.1);
         }
         
         function draw() {
           background(127);
         
        -<<<<<<< HEAD
           // 물 그리기
        -=======
        -  // Draw water
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           liquid.display();
         
           for (let i = 0; i < movers.length; i++) {
         
        -<<<<<<< HEAD
             // Mover가 액체인가요?
             if (liquid.contains(movers[i])) {
               // 항력 계산하기
        @@ -64,22 +42,6 @@ function draw() {
             movers[i].applyForce(gravity);
         
             // 업데이트하고 화면에 보이기(display)
        -=======
        -    // Is the Mover in the liquid?
        -    if (liquid.contains(movers[i])) {
        -      // Calculate drag force
        -      let dragForce = liquid.calculateDrag(movers[i]);
        -      // Apply drag force to Mover
        -      movers[i].applyForce(dragForce);
        -    }
        -
        -    // Gravity is scaled by mass here!
        -    let gravity = createVector(0, 0.1 * movers[i].mass);
        -    // Apply gravity
        -    movers[i].applyForce(gravity);
        -
        -    // Update and display
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             movers[i].update();
             movers[i].display();
             movers[i].checkEdges();
        @@ -92,11 +54,7 @@ function mousePressed() {
           reset();
         }
         
        -<<<<<<< HEAD
         // 모든 Mover 오브젝트들을 무작위로 재시작하기
        -=======
        -// Restart all the Mover objects randomly
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function reset() {
           for (let i = 0; i < 9; i++) {
             movers[i] = new Mover(random(0.5, 3), 40 + i * 70, 0);
        @@ -111,18 +69,13 @@ let Liquid = function(x, y, w, h, c) {
           this.c = c;
         };
         
        -<<<<<<< HEAD
         // Mover가 액체인가요?
        -=======
        -// Is the Mover in the Liquid?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Liquid.prototype.contains = function(m) {
           let l = m.position;
           return l.x > this.x && l.x < this.x + this.w &&
                  l.y > this.y && l.y < this.y + this.h;
         };
         
        -<<<<<<< HEAD
         // 항력 계산하기
         Liquid.prototype.calculateDrag = function(m) {
           // Magnitue(크기) = 계수 * speed(속도)의 제곱
        @@ -134,19 +87,6 @@ Liquid.prototype.calculateDrag = function(m) {
           dragForce.mult(-1);
         
           // 힘의 크기에 따라 조정하기
        -=======
        -// Calculate drag force
        -Liquid.prototype.calculateDrag = function(m) {
        -  // Magnitude is coefficient * speed squared
        -  let speed = m.velocity.mag();
        -  let dragMagnitude = this.c * speed * speed;
        -
        -  // Direction is inverse of velocity
        -  let dragForce = m.velocity.copy();
        -  dragForce.mult(-1);
        -
        -  // Scale according to magnitude
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           // dragForce.setMag(dragMagnitude);
           dragForce.normalize();
           dragForce.mult(dragMagnitude);
        @@ -166,32 +106,19 @@ function Mover(m, x, y) {
           this.acceleration = createVector(0, 0);
         }
         
        -<<<<<<< HEAD
         // 뉴턴(Newton)의 두번째 법칙: F = M * A
         // 또는 A = F / M
        -=======
        -// Newton's 2nd law: F = M * A
        -// or A = F / M
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Mover.prototype.applyForce = function(force) {
           let f = p5.Vector.div(force, this.mass);
           this.acceleration.add(f);
         };
         
         Mover.prototype.update = function() {
        -<<<<<<< HEAD
           // 가속도에 따라 변하는 속도
           this.velocity.add(this.acceleration);
           // 속도에 따라 변하는 위치
           this.position.add(this.velocity);
           // 매 프레임마다 가속도 초기화
        -=======
        -  // Velocity changes according to acceleration
        -  this.velocity.add(this.acceleration);
        -  // position changes by velocity
        -  this.position.add(this.velocity);
        -  // We must clear acceleration each frame
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           this.acceleration.mult(0);
         };
         
        @@ -202,17 +129,10 @@ Mover.prototype.display = function() {
           ellipse(this.position.x, this.position.y, this.mass * 16, this.mass * 16);
         };
         
        -<<<<<<< HEAD
         // 바닥면에서 튀어오르기
         Mover.prototype.checkEdges = function() {
           if (this.position.y > (height - this.mass * 8)) {
             // 바닥면에 닿을 때 약간의 완충 현상 발생
        -=======
        -// Bounce off bottom of window
        -Mover.prototype.checkEdges = function() {
        -  if (this.position.y > (height - this.mass * 8)) {
        -    // A little dampening when hitting the bottom
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             this.velocity.y *= -0.9;
             this.position.y = (height - this.mass * 8);
           }
        diff --git a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        index cf71118089..81ea5dd585 100644
        --- a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 파티클 시스템
          * @description 이 예제는 기초적인 파티클 시스템을 다룹니다.
        -=======
        - * @name Particle System
        - * @description This is a basic Particle System
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         let system;
        @@ -21,7 +16,7 @@ function draw() {
           system.run();
         }
         
        -// A simple Particle class
        +// 간단한 파티클 클래스
         let Particle = function(position) {
           this.acceleration = createVector(0, 0.05);
           this.velocity = createVector(random(-1, 1), random(-1, 0));
        @@ -34,14 +29,14 @@ Particle.prototype.run = function() {
           this.display();
         };
         
        -// Method to update position
        +// 위치 업데이트를 위한 메소드
         Particle.prototype.update = function(){
           this.velocity.add(this.acceleration);
           this.position.add(this.velocity);
           this.lifespan -= 2;
         };
         
        -// Method to display
        +// 화면에 보이기 위한 메소드
         Particle.prototype.display = function() {
           stroke(200, this.lifespan);
           strokeWeight(2);
        @@ -49,7 +44,7 @@ Particle.prototype.display = function() {
           ellipse(this.position.x, this.position.y, 12, 12);
         };
         
        -// Is the particle still useful?
        +// 파티클이 여전히 쓸만한가요?
         Particle.prototype.isDead = function(){
           return this.lifespan < 0;
         };
        diff --git a/src/data/examples/ko/09_Simulate/02_Flocking.js b/src/data/examples/ko/09_Simulate/02_Flocking.js
        index d0d86898bf..55fa0b262b 100644
        --- a/src/data/examples/ko/09_Simulate/02_Flocking.js
        +++ b/src/data/examples/ko/09_Simulate/02_Flocking.js
        @@ -1,19 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 플로킹
          * @description 크레이그 레이놀즈(Craig Reynolds)의 "군집(Flocking)" 행위를 묘사합니다.
          * 참고: http://www.red3d.com/cwr/
          * 규칙: 응집, 분리, 정렬
          * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
          * 마우스를 드래그하여 시스템에 개체(boid)를 더해보세요.
        -=======
        - * @name Flocking
        - * @description Demonstration of Craig Reynolds' "Flocking" behavior.
        - * See: http://www.red3d.com/cwr/
        - * Rules: Cohesion, Separation, Alignment
        - * (from <a href="http://natureofcode.com">natureofcode.com</a>).
        - *  Drag mouse to add boids into the system.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         
        @@ -24,11 +15,7 @@ function setup() {
           createP("Drag the mouse to generate new boids.");
         
           flock = new Flock();
        -<<<<<<< HEAD
           // 시스템에 초기 개체(boid) 더하기
        -=======
        -  // Add an initial set of boids into the system
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < 100; i++) {
             let b = new Boid(width / 2,height / 2);
             flock.addBoid(b);
        @@ -40,17 +27,12 @@ function draw() {
           flock.run();
         }
         
        -<<<<<<< HEAD
         // 시스템에 새로운 개체 더하기
        -=======
        -// Add a new boid into the System
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function mouseDragged() {
           flock.addBoid(new Boid(mouseX, mouseY));
         }
         
         // The Nature of Code
        -<<<<<<< HEAD
         // 다니엘 쉬프만(Daniel Shiffman)
         // http://natureofcode.com
         
        @@ -60,26 +42,11 @@ function mouseDragged() {
         function Flock() {
           // 모든 개체의 배열
           this.boids = []; // 배열 초기화
        -=======
        -// Daniel Shiffman
        -// http://natureofcode.com
        -
        -// Flock object
        -// Does very little, simply manages the array of all the boids
        -
        -function Flock() {
        -  // An array for all the boids
        -  this.boids = []; // Initialize the array
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         Flock.prototype.run = function() {
           for (let i = 0; i < this.boids.length; i++) {
        -<<<<<<< HEAD
             this.boids[i].run(this.boids);  // 전체 보이즈 개체 목록을 각 개체에 보내기
        -=======
        -    this.boids[i].run(this.boids);  // Passing the entire list of boids to each boid individually
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         }
         
        @@ -88,32 +55,19 @@ Flock.prototype.addBoid = function(b) {
         }
         
         // The Nature of Code
        -<<<<<<< HEAD
         // 다니엘 쉬프만(Daniel Shiffman)
         // http://natureofcode.com
         
         // Boid(개체) 클래스
         // 응집(cohesion), 분리(seperation), 정렬(alignment)을 위한 메소드 추가
        -=======
        -// Daniel Shiffman
        -// http://natureofcode.com
        -
        -// Boid class
        -// Methods for Separation, Cohesion, Alignment added
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function Boid(x, y) {
           this.acceleration = createVector(0, 0);
           this.velocity = createVector(random(-1, 1), random(-1, 1));
           this.position = createVector(x, y);
           this.r = 3.0;
        -<<<<<<< HEAD
           this.maxspeed = 3;    // 최대 속도
           this.maxforce = 0.05; // 최대 조타력
        -=======
        -  this.maxspeed = 3;    // Maximum speed
        -  this.maxforce = 0.05; // Maximum steering force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         Boid.prototype.run = function(boids) {
        @@ -124,7 +78,6 @@ Boid.prototype.run = function(boids) {
         }
         
         Boid.prototype.applyForce = function(force) {
        -<<<<<<< HEAD
           // A = F / M 으로 계산하고 싶다면, 여기에 질량을 더하면 됩니다. 
           this.acceleration.add(force);
         }
        @@ -139,28 +92,11 @@ Boid.prototype.flock = function(boids) {
           ali.mult(1.0);
           coh.mult(1.0);
           // 가속도에 force 벡터 더하기
        -=======
        -  // We could add mass here if we want A = F / M
        -  this.acceleration.add(force);
        -}
        -
        -// We accumulate a new acceleration each time based on three rules
        -Boid.prototype.flock = function(boids) {
        -  let sep = this.separate(boids);   // Separation
        -  let ali = this.align(boids);      // Alignment
        -  let coh = this.cohesion(boids);   // Cohesion
        -  // Arbitrarily weight these forces
        -  sep.mult(1.5);
        -  ali.mult(1.0);
        -  coh.mult(1.0);
        -  // Add the force vectors to acceleration
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           this.applyForce(sep);
           this.applyForce(ali);
           this.applyForce(coh);
         }
         
        -<<<<<<< HEAD
         // 위치 업데이트를 위한 메소드
         Boid.prototype.update = function() {
           // 속도 업데이트
        @@ -177,42 +113,16 @@ Boid.prototype.update = function() {
         Boid.prototype.seek = function(target) {
           let desired = p5.Vector.sub(target,this.position);  // 현위치에서 목표점을 가리키는 벡터
           // desired를 표준화하고 최대 속도로 조정
        -=======
        -// Method to update location
        -Boid.prototype.update = function() {
        -  // Update velocity
        -  this.velocity.add(this.acceleration);
        -  // Limit speed
        -  this.velocity.limit(this.maxspeed);
        -  this.position.add(this.velocity);
        -  // Reset accelertion to 0 each cycle
        -  this.acceleration.mult(0);
        -}
        -
        -// A method that calculates and applies a steering force towards a target
        -// STEER = DESIRED MINUS VELOCITY
        -Boid.prototype.seek = function(target) {
        -  let desired = p5.Vector.sub(target,this.position);  // A vector pointing from the location to the target
        -  // Normalize desired and scale to maximum speed
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           desired.normalize();
           desired.mult(this.maxspeed);
           // Steering = Desired minus Velocity
           let steer = p5.Vector.sub(desired,this.velocity);
        -<<<<<<< HEAD
           steer.limit(this.maxforce);  // 최대 조타력으로 제한
        -=======
        -  steer.limit(this.maxforce);  // Limit to maximum steering force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           return steer;
         }
         
         Boid.prototype.render = function() {
        -<<<<<<< HEAD
           // 속도의 방향에 따라 회전하는 삼각형 그리기
        -=======
        -  // Draw a triangle rotated in the direction of velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let theta = this.velocity.heading() + radians(90);
           fill(127);
           stroke(200);
        @@ -235,18 +145,12 @@ Boid.prototype.borders = function() {
           if (this.position.y > height + this.r) this.position.y = -this.r;
         }
         
        -<<<<<<< HEAD
         // 분리 Seperation
         // 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
        -=======
        -// Separation
        -// Method checks for nearby boids and steers away
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Boid.prototype.separate = function(boids) {
           let desiredseparation = 25.0;
           let steer = createVector(0, 0);
           let count = 0;
        -<<<<<<< HEAD
           // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
           for (let i = 0; i < boids.length; i++) {
             let d = p5.Vector.dist(this.position,boids[i].position);
        @@ -261,35 +165,13 @@ Boid.prototype.separate = function(boids) {
             }
           }
           // 평균 -- 얼마로 나눌 것인가
        -=======
        -  // For every boid in the system, check if it's too close
        -  for (let i = 0; i < boids.length; i++) {
        -    let d = p5.Vector.dist(this.position,boids[i].position);
        -    // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
        -    if ((d > 0) && (d < desiredseparation)) {
        -      // Calculate vector pointing away from neighbor
        -      let diff = p5.Vector.sub(this.position, boids[i].position);
        -      diff.normalize();
        -      diff.div(d);        // Weight by distance
        -      steer.add(diff);
        -      count++;            // Keep track of how many
        -    }
        -  }
        -  // Average -- divide by how many
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (count > 0) {
             steer.div(count);
           }
         
        -<<<<<<< HEAD
           // 벡터가 0보다 크다면,
           if (steer.mag() > 0) {
             // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
        -=======
        -  // As long as the vector is greater than 0
        -  if (steer.mag() > 0) {
        -    // Implement Reynolds: Steering = Desired - Velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             steer.normalize();
             steer.mult(this.maxspeed);
             steer.sub(this.velocity);
        @@ -298,13 +180,8 @@ Boid.prototype.separate = function(boids) {
           return steer;
         }
         
        -<<<<<<< HEAD
         // 배열 Alignment
         // 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
        -=======
        -// Alignment
        -// For every nearby boid in the system, calculate the average velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Boid.prototype.align = function(boids) {
           let neighbordist = 50;
           let sum = createVector(0,0);
        @@ -328,38 +205,22 @@ Boid.prototype.align = function(boids) {
           }
         }
         
        -<<<<<<< HEAD
         // 응집 Cohesion
         // 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
         Boid.prototype.cohesion = function(boids) {
           let neighbordist = 50;
           let sum = createVector(0, 0);   // 빈 벡터값으로 시작하여 모든 위치들을 축적
        -=======
        -// Cohesion
        -// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
        -Boid.prototype.cohesion = function(boids) {
        -  let neighbordist = 50;
        -  let sum = createVector(0, 0);   // Start with empty vector to accumulate all locations
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let count = 0;
           for (let i = 0; i < boids.length; i++) {
             let d = p5.Vector.dist(this.position,boids[i].position);
             if ((d > 0) && (d < neighbordist)) {
        -<<<<<<< HEAD
               sum.add(boids[i].position); // 위치 추가
        -=======
        -      sum.add(boids[i].position); // Add location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               count++;
             }
           }
           if (count > 0) {
             sum.div(count);
        -<<<<<<< HEAD
             return this.seek(sum);  // 해당 위치를 향해 조타
        -=======
        -    return this.seek(sum);  // Steer towards the location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           } else {
             return createVector(0, 0);
           }
        diff --git a/src/data/examples/ko/09_Simulate/03_WolframCA.js b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        index 675a2148db..6472f7d97f 100644
        --- a/src/data/examples/ko/09_Simulate/03_WolframCA.js
        +++ b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        @@ -1,16 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 울프램 셀룰러 오토마타
          * @description 1차원 셀룰러 오토마타(cellular automata) 간단하게 구현하기.
        -=======
        - * @name Wolfram CA
        - * @description Simple demonstration of a Wolfram 1-dimensional cellular automata
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         
         let w = 10;
        -<<<<<<< HEAD
         // 0과 1들의 배열
         let cells;
         
        @@ -18,15 +12,6 @@ let cells;
         let generation = 0;
         
         // {0,1,1,0,1,1,0,1}과 같은 규칙 묶음(ruleset)을 저장하는 배열
        -=======
        -// An array of 0s and 1s
        -let cells;
        -
        - // We arbitrarily start with just the middle cell having a state of "1"
        -let generation = 0;
        -
        -// An array to store the ruleset, for example {0,1,1,0,1,1,0,1}
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let ruleset = [0, 1, 0, 1, 1, 0, 1, 0];
         
         function setup() {
        @@ -54,7 +39,6 @@ function draw() {
           }
         }
         
        -<<<<<<< HEAD
         // 새로운 세대(generation) 생성 과정
         function generate() {
           // 먼저, 새로운 값을 위한 빈 배열을 만듭니다.
        @@ -68,33 +52,13 @@ function generate() {
             nextgen[i] = rules(left, me, right); // 다음 세대 상태를 규칙 묶음(ruleset)에 의거하여 계산
           }
           // 현재 상태가 새로운 세대가 됩니다.
        -=======
        -// The process of creating the new generation
        -function generate() {
        -  // First we create an empty array for the new values
        -  let nextgen = Array(cells.length);
        -  // For every spot, determine new state by examing current state, and neighbor states
        -  // Ignore edges that only have one neighor
        -  for (let i = 1; i < cells.length-1; i++) {
        -    let left   = cells[i-1];   // Left neighbor state
        -    let me     = cells[i];     // Current state
        -    let right  = cells[i+1];   // Right neighbor state
        -    nextgen[i] = rules(left, me, right); // Compute next generation state based on ruleset
        -  }
        -  // The current generation is the new generation
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           cells = nextgen;
           generation++;
         }
         
         
        -<<<<<<< HEAD
         // 울프램 규칙 구현하기
         // 더 향상되거나 간결해질 수도 있지만, 여기서 각 사례별로 어떤 일이 일어나는지 명확히 볼 수 있습니다.
        -=======
        -// Implementing the Wolfram rules
        -// Could be improved and made more concise, but here we can explicitly see what is going on for each case
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function rules(a, b, c) {
           if (a == 1 && b == 1 && c == 1) return ruleset[0];
           if (a == 1 && b == 1 && c == 0) return ruleset[1];
        diff --git a/src/data/examples/ko/09_Simulate/04_GameOfLife.js b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        index abfd5c2ec6..d203b1a791 100644
        --- a/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        +++ b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        @@ -1,12 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 라이프 게임
          * @description 존 콘웨이(John Conway)의 라이프 게임 셀룰러 오토마타
          * (Game of Life Cellular Automata)의 기초적 구현
        -=======
        - * @name Game of Life
        - * @description A basic implementation of John Conway's Game of Life CA
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         
        @@ -19,26 +14,15 @@ let next;
         function setup() {
           createCanvas(720, 400);
           w = 20;
        -<<<<<<< HEAD
           // 행렬 계산하기
           columns = floor(width / w);
           rows = floor(height / w);
           // JS를 사용하여 요상한 2D 배열 만들기
        -=======
        -  // Calculate columns and rows
        -  columns = floor(width / w);
        -  rows = floor(height / w);
        -  // Wacky way to make a 2D array is JS
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           board = new Array(columns);
           for (let i = 0; i < columns; i++) {
             board[i] = new Array(rows);
           }
        -<<<<<<< HEAD
           // 복수의 2D 배열을 만들고 바꾸기
        -=======
        -  // Going to use multiple 2D arrays and swap them
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           next = new Array(columns);
           for (i = 0; i < columns; i++) {
             next[i] = new Array(rows);
        @@ -60,16 +44,11 @@ function draw() {
         
         }
         
        -<<<<<<< HEAD
         // 마우스 버튼 클릭시 보드 리셋하기
        -=======
        -// reset board when mouse is pressed
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function mousePressed() {
           init();
         }
         
        -<<<<<<< HEAD
         // 무작위로 보드 채우기
         function init() {
           for (let i = 0; i < columns; i++) {
        @@ -77,22 +56,12 @@ function init() {
               // 0으로 모서리 테두리 그리기
               if (i == 0 || j == 0 || i == columns-1 || j == rows-1) board[i][j] = 0;
               // 나머지는 무작위로 채우기
        -=======
        -// Fill board randomly
        -function init() {
        -  for (let i = 0; i < columns; i++) {
        -    for (let j = 0; j < rows; j++) {
        -      // Lining the edges with 0s
        -      if (i == 0 || j == 0 || i == columns-1 || j == rows-1) board[i][j] = 0;
        -      // Filling the rest randomly
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               else board[i][j] = floor(random(2));
               next[i][j] = 0;
             }
           }
         }
         
        -<<<<<<< HEAD
         // 새로운 세대 생성하는 과정
         function generate() {
         
        @@ -100,15 +69,6 @@ function generate() {
           for (let x = 1; x < columns - 1; x++) {
             for (let y = 1; y < rows - 1; y++) {
               // 3x3의 주변 그리드에 모든 상태들을 더하여 넣기
        -=======
        -// The process of creating the new generation
        -function generate() {
        -
        -  // Loop through every spot in our 2D array and check spots neighbors
        -  for (let x = 1; x < columns - 1; x++) {
        -    for (let y = 1; y < rows - 1; y++) {
        -      // Add up all the states in a 3x3 surrounding grid
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               let neighbors = 0;
               for (let i = -1; i <= 1; i++) {
                 for (let j = -1; j <= 1; j++) {
        @@ -116,7 +76,6 @@ function generate() {
                 }
               }
         
        -<<<<<<< HEAD
               // 위의 반복을 통해 모든 셀들의 현재 상태를 계산해 넣었으므로,
               // 이 계산을 빼주는 요령
               neighbors -= board[x][y];
        @@ -129,20 +88,6 @@ function generate() {
           }
         
           // 바꾸기!
        -=======
        -      // A little trick to subtract the current cell's state since
        -      // we added it in the above loop
        -      neighbors -= board[x][y];
        -      // Rules of Life
        -      if      ((board[x][y] == 1) && (neighbors <  2)) next[x][y] = 0;           // Loneliness
        -      else if ((board[x][y] == 1) && (neighbors >  3)) next[x][y] = 0;           // Overpopulation
        -      else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1;           // Reproduction
        -      else                                             next[x][y] = board[x][y]; // Stasis
        -    }
        -  }
        -
        -  // Swap!
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let temp = board;
           board = next;
           next = temp;
        diff --git a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        index 92df0b23a4..90e91091c0 100644
        --- a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        +++ b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        @@ -1,14 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 멀티플 파티클 시스템
          * @description 마우스를 클릭한 위치에서 파티클이 폭발적으로 생성되도록 만들어보세요. <br> 매 폭발은 Particle 클래스의 하위 클래스인 Particles와 CrazyParticles
          * 의 한 인스턴스에 해당합니다. <br> 클래스 상속과 다형 사용에 대한 방법을 확인해보세요. <br>
          * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
        -=======
        - * @name Multiple Particle Systems
        - * @description Click the mouse to generate a burst of particles at mouse location.<br>Each burst is one instance of a particle system with Particles and CrazyParticles (a subclass of Particle).<br>Note use of Inheritance and Polymorphism here.<br>
        - * Original by Daniel Shiffman.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let systems;
         
        @@ -37,11 +31,7 @@ function mousePressed() {
           systems.push(p);
         }
         
        -<<<<<<< HEAD
        -// 간단한 Particle 클래스
        -=======
        -// A simple Particle class
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +// 간단한 파티클 클래스
         let Particle = function(position) {
           this.acceleration = createVector(0, 0.05);
           this.velocity = createVector(random(-1, 1), random(-1, 0));
        @@ -54,22 +44,14 @@ Particle.prototype.run = function() {
           this.display();
         };
         
        -<<<<<<< HEAD
         // 위치 업데이트를 위한 메소드
        -=======
        -// Method to update position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Particle.prototype.update = function(){
           this.velocity.add(this.acceleration);
           this.position.add(this.velocity);
           this.lifespan -= 2;
         };
         
        -<<<<<<< HEAD
        -// 화면에 보이게 하기 위한 메소드
        -=======
        -// Method to display
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +// 화면에 보이기 위한 메소드
         Particle.prototype.display = function () {
           stroke(200, this.lifespan);
           strokeWeight(2);
        @@ -77,10 +59,7 @@ Particle.prototype.display = function () {
           ellipse(this.position.x, this.position.y, 12, 12);
         };
         
        -<<<<<<< HEAD
        -// 파티클이 여전히 유용한가요?
        -=======
        -// Is the particle still useful?
        +// 파티클이 여전히 쓸만한가요?
         >>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Particle.prototype.isDead = function () {
           if (this.lifespan < 0) {
        @@ -96,11 +75,7 @@ let ParticleSystem = function (position) {
         };
         
         ParticleSystem.prototype.addParticle = function () {
        -<<<<<<< HEAD
           // Particle 또는 CrazyParticle을 시스템에 더하기
        -=======
        -  // Add either a Particle or CrazyParticle to the system
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (int(random(0, 2)) == 0) {
             p = new Particle(this.origin);
           }
        @@ -120,7 +95,6 @@ ParticleSystem.prototype.run = function () {
           }
         };
         
        -<<<<<<< HEAD
         // Particle의 하위 클래스
         
         function CrazyParticle(origin) {
        @@ -155,44 +129,6 @@ CrazyParticle.prototype.display=function() {
           // 타원형을 일반적인 파티클처럼 렌더링하기
           Particle.prototype.display.call(this);
           // 그 다음, 회전하는 선들 더하기
        -=======
        -// A subclass of Particle
        -
        -function CrazyParticle(origin) {
        -  // Call the parent constructor, making sure (using Function#call)
        -  // that "this" is set correctly during the call
        -  Particle.call(this, origin);
        -
        -  // Initialize our added properties
        -  this.theta = 0.0;
        -};
        -
        -// Create a Crazy.prototype object that inherits from Particle.prototype.
        -// Note: A common error here is to use "new Particle()" to create the
        -// Crazy.prototype. That's incorrect for several reasons, not least
        -// that we don't have anything to give Particle for the "origin"
        -// argument. The correct place to call Particle is above, where we call
        -// it from Crazy.
        -CrazyParticle.prototype = Object.create(Particle.prototype); // See note below
        -
        -// Set the "constructor" property to refer to CrazyParticle
        -CrazyParticle.prototype.constructor = CrazyParticle;
        -
        -// Notice we don't have the method run() here; it is inherited from Particle
        -
        -// This update() method overrides the parent class update() method
        -CrazyParticle.prototype.update=function() {
        -  Particle.prototype.update.call(this);
        -  // Increment rotation based on horizontal velocity
        -  this.theta += (this.velocity.x * this.velocity.mag()) / 10.0;
        -}
        -
        -// This display() method overrides the parent class display() method
        -CrazyParticle.prototype.display=function() {
        -  // Render the ellipse just like in a regular particle
        -  Particle.prototype.display.call(this);
        -  // Then add a rotating line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           push();
           translate(this.position.x, this.position.y);
           rotate(this.theta);
        diff --git a/src/data/examples/ko/09_Simulate/06_Spirograph.js b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        index b5d1d48b96..bdbb38b12e 100644
        --- a/src/data/examples/ko/09_Simulate/06_Spirograph.js
        +++ b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        @@ -1,6 +1,5 @@
         
         /*
        -<<<<<<< HEAD
          * @name 스피로그래프
          * @description 일명 싸인이라 불리는 서로 맞물린 원형들을 이용하여,
          * 스피로그래프와 같은 효과를 만드는 간단한 변형 예제를 소개합니다.
        @@ -18,50 +17,21 @@ let fund = 0.005; // 중심 싸인의 속도
         let ratio = 1; // 더해진 각 싸인은 속도에 몇을 곱하나요?
         let alpha = 50; // 궤도 추적 시스템의 투명도
         
        -let trace = false; // 추적을 하나요?
        -=======
        - * @name Spirograph
        - * @description This sketch uses simple transformations to create a
        - * Spirograph-like effect with interlocking circles (called sines).
        - * Press the spacebar to switch between tracing and showing the underlying geometry.<br>
        - * Example created by <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>.<br>
        - * <a href='http://en.wikipedia.org/wiki/Spirograph'>http://en.wikipedia.org/wiki/Spirograph</a>
        - */
        -let NUMSINES = 20; // how many of these things can we do at once?
        -let sines = new Array(NUMSINES); // an array to hold all the current angles
        -let rad; // an initial radius value for the central sine
        -let i; // a counter variable
        -
        -// play with these to get a sense of what's going on:
        -let fund = 0.005; // the speed of the central sine
        -let ratio = 1; // what multiplier for speed is each additional sine?
        -let alpha = 50; // how opaque is the tracing system
        -
        -let trace = false; // are we tracing?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +let trace = false; // 추적 중인가요?
         
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           rad = height / 4; // 중심 원의 반지름 계산
           background(204); // 화면 비우기
         
           for (let i = 0; i<sines.length; i++) {
             sines[i] = PI; // 모든 원들이 북쪽을 향해 시작하도록 설정
        -=======
        -  rad = height / 4; // compute radius for central circle
        -  background(204); // clear the screen
        -
        -  for (let i = 0; i<sines.length; i++) {
        -    sines[i] = PI; // start EVERYBODY facing NORTH
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         }
         
         function draw() {
           if (!trace) {
        -<<<<<<< HEAD
             background(204); // 기하 형상이 보일 경우 스크린 비우기
             stroke(0, 255); // 검정색 펜
             noFill(); // 면채우기 없음
        @@ -92,38 +62,6 @@ function draw() {
           }
         
           pop(); // 마지막 변형에 다다르면 레벨 1 다운
        -=======
        -    background(204); // clear screen if showing geometry
        -    stroke(0, 255); // black pen
        -    noFill(); // don't fill
        -  }
        -
        -  // MAIN ACTION
        -  push(); // start a transformation matrix
        -  translate(width / 2, height / 2); // move to middle of screen
        -
        -  for (let i = 0; i < sines.length; i++) {
        -    let erad = 0; // radius for small "point" within circle... this is the 'pen' when tracing
        -    // setup for tracing
        -    if (trace) {
        -      stroke(0, 0, 255 * (float(i) / sines.length), alpha); // blue
        -      fill(0, 0, 255, alpha / 2); // also, um, blue
        -      erad = 5.0 * (1.0 - float(i) / sines.length); // pen width will be related to which sine
        -    }
        -    let radius = rad / (i + 1); // radius for circle itself
        -    rotate(sines[i]); // rotate circle
        -    if (!trace) ellipse(0, 0, radius * 2, radius * 2); // if we're simulating, draw the sine
        -    push(); // go up one level
        -    translate(0, radius); // move to sine edge
        -    if (!trace) ellipse(0, 0, 5, 5); // draw a little circle
        -    if (trace) ellipse(0, 0, erad, erad); // draw with erad if tracing
        -    pop(); // go down one level
        -    translate(0, radius); // move into position for next sine
        -    sines[i] = (sines[i] + (fund + (fund * i * ratio))) % TWO_PI; // update angle based on fundamental
        -  }
        -
        -  pop(); // pop down final transformation
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         }
         
        diff --git a/src/data/examples/ko/09_Simulate/07_LSystems.js b/src/data/examples/ko/09_Simulate/07_LSystems.js
        index 31087b55fc..6fcd73cc69 100644
        --- a/src/data/examples/ko/09_Simulate/07_LSystems.js
        +++ b/src/data/examples/ko/09_Simulate/07_LSystems.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name L-시스템
          * @description 이 스케치는 린덴마이어(Lindenmayer) 또는 (L-) 시스템을 기반으로 한 자동 드로잉을 보여줍니다.
          * L-시스템은 자연적, 기하학적, 또는 재밌는 "프랙탈형" 패턴을 만드는 제너레이티브 그래픽에 쓰입니다.<br>
        @@ -20,48 +19,17 @@ therules[0] = ['A', '-BF+AFA+FB-']; // 첫 번째 규칙
         therules[1] = ['B', '+AF-BFB-FA+']; // 두 번째 규칙
         
         let whereinstring = 0; // L-시스템 상 현재 위치?
        -=======
        - * @name L-Systems
        - * @description This sketch creates an automated drawing based on a Lindenmayer
        - * or (L-) system. L-systems are often used in procedural graphics to make
        - * natural, geometric, or interesting "fractal-style" patterns.<br>
        - * Example created by <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>.<br>
        - * <a href='https://en.wikipedia.org/wiki/L-system'>https://en.wikipedia.org/wiki/L-system</a>
        - */
        -// TURTLE STUFF:
        -let x, y; // the current position of the turtle
        -let currentangle = 0; // which way the turtle is pointing
        -let step = 20; // how much the turtle moves with each 'F'
        -let angle = 90; // how much the turtle turns with a '-' or '+'
        -
        -// LINDENMAYER STUFF (L-SYSTEMS)
        -let thestring = 'A'; // "axiom" or start of the string
        -let numloops = 5; // how many iterations to pre-compute
        -let therules = []; // array for rules
        -therules[0] = ['A', '-BF+AFA+FB-']; // first rule
        -therules[1] = ['B', '+AF-BFB-FA+']; // second rule
        -
        -let whereinstring = 0; // where in the L-system are we?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(710, 400);
           background(255);
           stroke(0, 0, 0, 255);
         
        -<<<<<<< HEAD
           // 좌측 하단 코너에서 x와 y 위치 시작
           x = 0;
           y = height-1;
         
           // L-시스템 처리하기
        -=======
        -  // start the x and y position at lower-left corner
        -  x = 0;
        -  y = height-1;
        -
        -  // COMPUTE THE L-SYSTEM
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < numloops; i++) {
             thestring = lindenmayer(thestring);
           }
        @@ -69,25 +37,16 @@ function setup() {
         
         function draw() {
         
        -<<<<<<< HEAD
           // 현재의 문자를 문자열로 그리기:
           drawIt(thestring[whereinstring]);
         
           // 문자열을 읽는 지점 증가하기
           // 마지막에 wrap around
        -=======
        -  // draw the current character in the string:
        -  drawIt(thestring[whereinstring]);
        -
        -  // increment the point for where we're reading the string.
        -  // wrap around at the end.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           whereinstring++;
           if (whereinstring > thestring.length-1) whereinstring = 0;
         
         }
         
        -<<<<<<< HEAD
         // L-시스템 해석하기
         function lindenmayer(s) {
           let outputstring = ''; // 빈 출력 문자열 시작하기
        @@ -128,69 +87,19 @@ function drawIt(k) {
           }
         
           // 무작위의 색상값을 주세요:
        -=======
        -// interpret an L-system
        -function lindenmayer(s) {
        -  let outputstring = ''; // start a blank output string
        -
        -  // iterate through 'therules' looking for symbol matches:
        -  for (let i = 0; i < s.length; i++) {
        -    let ismatch = 0; // by default, no match
        -    for (let j = 0; j < therules.length; j++) {
        -      if (s[i] == therules[j][0])  {
        -        outputstring += therules[j][1]; // write substitution
        -        ismatch = 1; // we have a match, so don't copy over symbol
        -        break; // get outta this for() loop
        -      }
        -    }
        -    // if nothing matches, just copy the symbol over.
        -    if (ismatch == 0) outputstring+= s[i];
        -  }
        -
        -  return outputstring; // send out the modified string
        -}
        -
        -// this is a custom function that draws turtle commands
        -function drawIt(k) {
        -
        -  if (k=='F') { // draw forward
        -    // polar to cartesian based on step and currentangle:
        -    let x1 = x + step*cos(radians(currentangle));
        -    let y1 = y + step*sin(radians(currentangle));
        -    line(x, y, x1, y1); // connect the old and the new
        -
        -    // update the turtle's position:
        -    x = x1;
        -    y = y1;
        -  } else if (k == '+') {
        -    currentangle += angle; // turn left
        -  } else if (k == '-') {
        -    currentangle -= angle; // turn right
        -  }
        -
        -  // give me some random color values:
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let r = random(128, 255);
           let g = random(0, 192);
           let b = random(0, 50);
           let a = random(50, 100);
         
        -<<<<<<< HEAD
           // 반지름에 대한 가우스 분포(D&D) 선택하기:
        -=======
        -  // pick a gaussian (D&D) distribution for the radius:
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let radius = 0;
           radius += random(0, 15);
           radius += random(0, 15);
           radius += random(0, 15);
           radius = radius / 3;
         
        -<<<<<<< HEAD
           // 그리기:
        -=======
        -  // draw the stuff:
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(r, g, b, a);
           ellipse(x, y, radius, radius);
         }
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/08_Spring.js b/src/data/examples/ko/09_Simulate/08_Spring.js
        index 87b933235e..03feae7e50 100644
        --- a/src/data/examples/ko/09_Simulate/08_Spring.js
        +++ b/src/data/examples/ko/09_Simulate/08_Spring.js
        @@ -1,17 +1,10 @@
         /*
         <<<<<<< HEAD
        - * @name 스프링
        + * @name 용수철
          * @frame 710, 400
        - * @description 스프링 효과를 보려면 수평 막대를 클릭하고 드래그한 뒤 놓아보세요.
        + * @description 수평 막대를 클릭하고 드래그한 뒤 놓으면 용수철 효과를 볼 수 있습니다.
          */
        -// 상단의 막대를 위한 Spring drawing constants for top bar
        -=======
        - * @name Spring
        - * @frame 710, 400
        - * @description Click, drag, and release the horizontal bar to start the spring.
        - */
        -// Spring drawing constants for top bar
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +// 상단의 막대기를 위한 용수철(spring) 그리기
         let springHeight = 32,
             left,
             right,
        @@ -20,31 +13,17 @@ let springHeight = 32,
             over = false,
             move = false;
         
        -<<<<<<< HEAD
        -// 스프링 시뮬레이션 상수들
        +// 용수철 시뮬레이션 상수들
         let M = 0.8,  // Mass(질량)
        -    K = 0.2,  // 스프링 상수
        +    K = 0.2,  // 용수철(spring) 상수
             D = 0.92, // Damping(감쇠)
             R = 150;  // Rest Position(놓인 위치)
         
        -// 스프링 시뮬레이션 변수들
        +// 용수철 시뮬레이션 변수들
         let ps = R,   // 위치
             vs = 0.0, // 속도
             as = 0,   // 가속도
             f = 0;    // 힘
        -=======
        -// Spring simulation constants
        -let M = 0.8,  // Mass
        -    K = 0.2,  // Spring constant
        -    D = 0.92, // Damping
        -    R = 150;  // Rest position
        -
        -// Spring simulation variables
        -let ps = R,   // Position
        -    vs = 0.0, // Velocity
        -    as = 0,   // Acceleration
        -    f = 0;    // Force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(710, 400);
        @@ -61,16 +40,12 @@ function draw() {
         }
         
         function drawSpring() {
        -  // Draw base
        +  // 바탕 그리기
           fill(0.2);
           let baseWidth = 0.5 * ps + -8;
           rect(width / 2 - baseWidth, ps + springHeight, width / 2 + baseWidth, height);
         
        -<<<<<<< HEAD
           // 상단 막대기의 색상 설정하고 그리기
        -=======
        -  // Set color and draw top bar
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (over || move) {
             fill(255);
           } else {
        @@ -81,43 +56,26 @@ function drawSpring() {
         }
         
         function updateSpring() {
        -<<<<<<< HEAD
        -  // 스프링 위치 업데이트
        +  // 용수철(spring) 위치 업데이트
           if ( !move ) {
             f = -K * ( ps - R ); // f=-ky
             as = f / M;          // 가속도 설정, f=ma == a=f/m
             vs = D * (vs + as);  // 속도 설정
             ps = ps + vs;        // 업데이트된 위치
        -=======
        -  // Update the spring position
        -  if ( !move ) {
        -    f = -K * ( ps - R ); // f=-ky
        -    as = f / M;          // Set the acceleration, f=ma == a=f/m
        -    vs = D * (vs + as);  // Set the velocity
        -    ps = ps + vs;        // Updated position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         
           if (abs(vs) < 0.1) {
             vs = 0.0;
           }
         
        -<<<<<<< HEAD
           // 마우스가 상단 막대기 위에 있는지 여부 테스트
        -=======
        -  // Test if mouse if over the top bar
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + springHeight) {
             over = true;
           } else {
             over = false;
           }
         
        -<<<<<<< HEAD
           // 상단 막대기의 위치 설정 및 제한
        -=======
        -  // Set and constrain the position of top bar
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (move) {
             ps = mouseY - springHeight / 2;
             ps = constrain(ps, minHeight, maxHeight);
        diff --git a/src/data/examples/ko/09_Simulate/09_Springs.js b/src/data/examples/ko/09_Simulate/09_Springs.js
        index 090bb5128d..bca9c5c5c5 100644
        --- a/src/data/examples/ko/09_Simulate/09_Springs.js
        +++ b/src/data/examples/ko/09_Simulate/09_Springs.js
        @@ -1,18 +1,10 @@
         /*
        -<<<<<<< HEAD
        - * @name 스프링들
        + * @name 용수철들
          * @frame 710,400
          * @description 마우스로 원형 하나를 클릭해 재배치해보세요.
          * 마우스 클릭을 놓으면 원위치로 되돌아갑니다.
          * 각 원형은 조금씩 다른 행동을 보입니다.
        -=======
        - * @name Springs
        - * @frame 710,400
        - * @description Move the mouse over one of the circles and click to re-position.
        - * When you release the mouse, it will snap back into position.
        - * Each circle has a slightly different behavior.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        - * (ported from https://processing.org/examples/springs.html)
        + * (https://processing.org/examples/springs.html에서 옮김)
          */
         let num = 3;
         let springs = [];
        @@ -47,15 +39,9 @@ function mouseReleased() {
           }
         }
         
        -<<<<<<< HEAD
        -// Spring 클래스
        +// 용수철(Spring) 클래스
         function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
           // 화면상 위치값들
        -=======
        -// Spring class
        -function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
        -  // Screen values
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           // this.xpos = _x;
           // this.ypos = _y;
         
        @@ -68,8 +54,7 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
           this.over = false;
           this.move = false;
         
        -<<<<<<< HEAD
        -	// 스프링 시뮬레이션 상수들
        +  // 용수철 시뮬레이션 상수들
           this.mass = _m;       // Mass(질량)
           this.k = 0.2;    // Spring constant
           this.k = _k_in;
        @@ -77,28 +62,12 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
           this.rest_posx = _x;  // 놓인 위치 X
           this.rest_posy = _y;  // 놓인 위치 Y
         
        -  // 스프링 시뮬레이션 변수들
        +  // 용수철 시뮬레이션 변수들
           //float pos = 20.0; // 위치
           this.velx = 0.0;   // X 속도
           this.vely = 0.0;   // Y 속도
           this.accel = 0;    // 가속도
           this.force = 0;    // 힘
        -=======
        -	// Spring simulation constants
        -  this.mass = _m;       // Mass
        -  this.k = 0.2;    // Spring constant
        -  this.k = _k_in;
        -  this.damp = _d;       // Damping
        -  this.rest_posx = _x;  // Rest position X
        -  this.rest_posy = _y;  // Rest position Y
        -
        -  // Spring simulation variables
        -  //float pos = 20.0; // Position
        -  this.velx = 0.0;   // X Velocity
        -  this.vely = 0.0;   // Y Velocity
        -  this.accel = 0;    // Acceleration
        -  this.force = 0;    // Force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
           this.friends = _others;
           this.id = _id;
        @@ -111,27 +80,16 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	}
         
         	this.force = -this.k * (this.y_pos - this.rest_posy);  // f=-ky
        -<<<<<<< HEAD
        -	this.accel = this.force / this.mass;                 // 가속도 설정하기, f=ma == a=f/m
        -	this.vely = this.damp * (this.vely + this.accel);         // 속도 설정하기
        -	this.y_pos = this.y_pos + this.vely;           // 업데이트된 위치
        +	this.accel = this.force / this.mass; // 가속도 설정하기, f=ma == a=f/m
        +	this.vely = this.damp * (this.vely + this.accel); // 속도 설정하기
        +	this.y_pos = this.y_pos + this.vely; // 업데이트된 위치
         
         
         	this.force = -this.k * (this.x_pos - this.rest_posx);  // f=-ky
        -	this.accel = this.force / this.mass;                 // 가속도 설정하기, f=ma == a=f/m
        -	this.velx = this.damp * (this.velx + this.accel);         // 속도 설정하기
        -	this.x_pos = this.x_pos + this.velx;           // 업데이트된 위치
        -=======
        -	this.accel = this.force / this.mass;                 // Set the acceleration, f=ma == a=f/m
        -	this.vely = this.damp * (this.vely + this.accel);         // Set the velocity
        -	this.y_pos = this.y_pos + this.vely;           // Updated position
        -
        +	this.accel = this.force / this.mass; // 가속도 설정하기, f=ma == a=f/m
        +	this.velx = this.damp * (this.velx + this.accel); // 속도 설정하기
        +	this.x_pos = this.x_pos + this.velx; // 업데이트된 위치
         
        -	this.force = -this.k * (this.x_pos - this.rest_posx);  // f=-ky
        -	this.accel = this.force / this.mass;                 // Set the acceleration, f=ma == a=f/m
        -	this.velx = this.damp * (this.velx + this.accel);         // Set the velocity
        -	this.x_pos = this.x_pos + this.velx;           // Updated position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         
         	if ((this.overEvent() || this.move) && !(this.otherOver()) ) {
        @@ -141,11 +99,7 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	  }
           }
         
        -<<<<<<< HEAD
        -  // 마우스가 이 스프링 위에 있는지의 여부르 테스트
        -=======
        -  // Test to see if mouse is over this spring
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 마우스가 이 용수철 위에 있는지의 여부 테스트
           this.overEvent = function() {
         	let disX = this.x_pos - mouseX;
         	let disY = this.y_pos - mouseY;
        @@ -157,11 +111,7 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	  }
           }
         
        -<<<<<<< HEAD
        -  // 다른 스프링이 움직이지 않도록 처리
        -=======
        -  // Make sure no other springs are active
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 다른 용수철이 움직이지 않도록 처리
           this.otherOver = function() {
         	for (let i = 0; i < num; i++) {
         	  if (i != this.id) {
        diff --git a/src/data/examples/ko/09_Simulate/10_SoftBody.js b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        index 1b29058fcc..a34f32ec5a 100644
        --- a/src/data/examples/ko/09_Simulate/10_SoftBody.js
        +++ b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 소프트 바디
          * @description 이라 그린버그(Ira Greenberg) 원본 제작.
          * <br><br>curveVertex() 와 curveTightness()를 사용한 소프트 바디 역학 시뮬레이션.
          */
         // 중심점
        -=======
        - * @name Soft Body
        - * @description Original example by Ira Greenberg.
        - * <br><br>Softbody dynamics simulation using curveVertex() and curveTightness().
        - */
        -// center point
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let centerX = 0.0, centerY = 0.0;
         
         let radius = 45, rotAngle = -90;
        @@ -19,17 +11,10 @@ let accelX = 0.0, accelY = 0.0;
         let deltaX = 0.0, deltaY = 0.0;
         let springing = 0.0009, damping = 0.98;
         
        -<<<<<<< HEAD
        -// 코너 노드들
        +// 모서리의 노드들
         let nodes = 5;
         
         // 빈 배열
        -=======
        -//corner nodes
        -let nodes = 5;
        -
        -//zero fill arrays
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let nodeStartX = [];
         let nodeStartY = [];
         let nodeX = [];
        @@ -37,29 +22,17 @@ let nodeY = [];
         let angle = [];
         let frequency = [];
         
        -<<<<<<< HEAD
         // 소프트 바디 역학
        -=======
        -// soft-body dynamics
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let organicConstant = 1.0;
         
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 화면상의 중심 도형
           centerX = width / 2;
           centerY = height / 2;
         
           // 배열을 0으로 초기화
        -=======
        -  //center shape in window
        -  centerX = width / 2;
        -  centerY = height / 2;
        -
        -  //initialize arrays to 0
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < nodes; i++){
             nodeStartX[i] = 0;
             nodeStartY[i] = 0;
        @@ -68,11 +41,7 @@ function setup() {
             angle[i] = 0;
           }
         
        -<<<<<<< HEAD
        -  // 코너 노드의 빈도수 초기화
        -=======
        -  // iniitalize frequencies for corner nodes
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 모서리 노드들의 빈도수 초기화
           for (let i = 0; i < nodes; i++){
             frequency[i] = random(5, 12);
           }
        @@ -82,11 +51,7 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 배경 사라지게하기
        -=======
        -  //fade background
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(0, 100);
           rect(0, 0, width, height);
           drawShape();
        @@ -94,22 +59,14 @@ function draw() {
         }
         
         function drawShape() {
        -<<<<<<< HEAD
           // 노드 시작 위치 계산
        -=======
        -  //  calculate node  starting locations
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < nodes; i++){
             nodeStartX[i] = centerX + cos(radians(rotAngle)) * radius;
             nodeStartY[i] = centerY + sin(radians(rotAngle)) * radius;
             rotAngle += 360.0 / nodes;
           }
         
        -<<<<<<< HEAD
           // 다각형 그리기
        -=======
        -  // draw polygon
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           curveTightness(organicConstant);
           fill(255);
           beginShape();
        @@ -123,25 +80,16 @@ function drawShape() {
         }
         
         function moveShape() {
        -<<<<<<< HEAD
           // 중심점 옮기기
           deltaX = mouseX - centerX;
           deltaY = mouseY - centerY;
         
           // 스프링같은 효과 만들기
        -=======
        -  //move center point
        -  deltaX = mouseX - centerX;
        -  deltaY = mouseY - centerY;
        -
        -  // create springing effect
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           deltaX *= springing;
           deltaY *= springing;
           accelX += deltaX;
           accelY += deltaY;
         
        -<<<<<<< HEAD
           // 프레데터(predator)의 중심 옮기기
           centerX += accelX;
           centerY += accelY;
        @@ -154,20 +102,6 @@ function moveShape() {
           organicConstant = 1 - ((abs(accelX) + abs(accelY)) * 0.1);
         
           // 노드 옮기기
        -=======
        -  // move predator's center
        -  centerX += accelX;
        -  centerY += accelY;
        -
        -  // slow down springing
        -  accelX *= damping;
        -  accelY *= damping;
        -
        -  // change curve tightness
        -  organicConstant = 1 - ((abs(accelX) + abs(accelY)) * 0.1);
        -
        -  //move nodes
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < nodes; i++){
             nodeX[i] = nodeStartX[i] + sin(radians(angle[i])) * (accelX * 2);
             nodeY[i] = nodeStartY[i] + sin(radians(angle[i])) * (accelY * 2);
        diff --git a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        index 4bf03f220a..8f11abfee3 100644
        --- a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        @@ -1,8 +1,8 @@
         /*
         <<<<<<< HEAD
        - * @name 스모크 파티클
        + * @name 연기 파티클
          * @description 다니엘 쉬프만(Dan Shiffman)이 프로세싱(Processing)을 위해 제작한
        - * 스모크 파티클 시스템(SmokeParticleSystem) 예제를 옮겨왔습니다.
        + * 연기 파티클 시스템(SmokeParticleSystem) 예제를 옮겨왔습니다.
          * 마치 연기와 같은 파티클을 만들어볼까요 :p
          */
         
        @@ -10,17 +10,6 @@
         let particle_texture = null;
         
         // 파티클 시스템을 담는 변수
        -=======
        - * @name SmokeParticles
        - * @description a port of Dan Shiffman's SmokeParticleSystem example originally
        - * for Processing. Creates smokey particles :p
        - */
        -
        -// texture for the particle
        -let particle_texture = null;
        -
        -// variable holding our particle system
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let ps = null;
         
         function preload() {
        @@ -29,17 +18,10 @@ function preload() {
         
         function setup() {
         
        -<<<<<<< HEAD
           // 캔버스 사이즈 설정
           createCanvas(640, 360);
         
           // 파티클 시스템 초기화
        -=======
        -  //set the canvas size
        -  createCanvas(640, 360);
        -
        -  //initialize our particle system
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           ps = new ParticleSystem(0, createVector(width / 2, height - 60), particle_texture);
         }
         
        @@ -55,20 +37,12 @@ function draw() {
             ps.addParticle();
           }
         
        -<<<<<<< HEAD
           // 바람의 힘을 뜻하는 화살표 그리기
        -=======
        -  // Draw an arrow representing the wind force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           drawVector(wind, createVector(width / 2, 50, 0), 500);
         }
         
         /**
        -<<<<<<< HEAD
          *  이 함수는 "wind(바람)"이 부는 방향을 나타낸 화살표를 그립니다.
        -=======
        - *  This function draws an arrow showing the direction our "wind" is blowing.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function drawVector(v, loc, scale){
           push();
        @@ -83,7 +57,6 @@ function drawVector(v, loc, scale){
           line(len, 0, len-arrowsize, -arrowsize / 2);
           pop();
         }
        -<<<<<<< HEAD
         //========= 파티클 시스템 ===========
         
         /**
        @@ -92,25 +65,11 @@ function drawVector(v, loc, scale){
          * @param v 파티클 시스템의 원점을 나타내는 매개 변수
          * @param img_ 시스템 상 각 파티클의 텍스쳐를 나타내는 매개 변수
          * @constructor 생성자
        -=======
        -//========= PARTICLE SYSTEM ===========
        -
        -/**
        - * A basic particle system class
        - * @param num the number of particles
        - * @param v the origin of the particle system
        - * @param img_ a texture for each particle in the system
        - * @constructor
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let ParticleSystem = function(num, v, img_) {
         
           this.particles = [];
        -<<<<<<< HEAD
           this.origin = v.copy(); // 실수로 원래 벡터값(origin)을 바꾼 경우를 대비하여, 벡터값을 복사합니다.
        -=======
        -  this.origin = v.copy(); // we make sure to copy the vector value in case we accidentally mutate the original by accident
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           this.img = img_
           for(let i = 0; i < num; ++i){
             this.particles.push(new Particle(this.origin, this.img));
        @@ -118,7 +77,6 @@ let ParticleSystem = function(num, v, img_) {
         };
         
         /**
        -<<<<<<< HEAD
          * 이 함수는 전체 파티클 시스템을 실행합니다.
          */
         ParticleSystem.prototype.run = function() {
        @@ -129,32 +87,14 @@ ParticleSystem.prototype.run = function() {
           let len = this.particles.length;
         
           //파티클 반복 및 실행
        -=======
        - * This function runs the entire particle system.
        - */
        -ParticleSystem.prototype.run = function() {
        -
        -  // cache length of the array we're going to loop into a variable
        -  // You may see <variable>.length in a for loop, from time to time but
        -  // we cache it here because otherwise the length is re-calculated for each iteration of a loop
        -  let len = this.particles.length;
        -
        -  //loop through and run particles
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = len - 1; i >= 0; i--) {
             let particle = this.particles[i];
             particle.run();
         
        -<<<<<<< HEAD
             // 파티클이 죽을 경우, 제거(remove)합니다.
             // 자바스크립트의 배열에는 "remove" 기능이 없지만,
             // 대신 동일한 기능을 수행하는 "splice"를 사용할 수 있습니다.
             // 제거를 시작할 지점에 인덱스를 넣고, 해당 지점부터 몇 개를 제거할 지 넣을 수 있습니다.
        -=======
        -    // if the particle is dead, we remove it.
        -    // javascript arrays don't have a "remove" function but "splice" works just as well.
        -    // we feed it an index to start at, then how many numbers from that point to remove.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (particle.isDead()) {
               this.particles.splice(i, 1);
             }
        @@ -162,13 +102,8 @@ ParticleSystem.prototype.run = function() {
         }
         
         /**
        -<<<<<<< HEAD
          * 현재 시스템의 존재하는 모든 파티클에 힘 벡터를 추가하는 메소드
          * @param dir 힘의 방향을 묘사하는 p5.Vector 매개 변수
        -=======
        - * Method to add a force vector to all particles currently in the system
        - * @param dir a p5.Vector describing the direction of the force.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         ParticleSystem.prototype.applyForce = function(dir) {
           let len = this.particles.length;
        @@ -178,26 +113,16 @@ ParticleSystem.prototype.applyForce = function(dir) {
         }
         
         /**
        -<<<<<<< HEAD
          * 본래 지정된 텍스쳐와 동일한 텍스쳐의 파티클을 시스템 원점에 추가
        -=======
        - * Adds a new particle to the system at the origin of the system and with
        - * the originally set texture.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         ParticleSystem.prototype.addParticle = function() {
             this.particles.push(new Particle(this.origin, this.img));
         }
         
        -<<<<<<< HEAD
        +
         //========= 파티클 ===========
         /**
          * 파티클을 이미지로 렌더링하는 간단한 파티클 클래스
        -=======
        -//========= PARTICLE  ===========
        -/**
        - *  A simple Particle class, renders the particle as an image
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let Particle = function (pos, img_) {
           this.loc = pos.copy();
        @@ -212,11 +137,7 @@ let Particle = function (pos, img_) {
         }
         
         /**
        -<<<<<<< HEAD
        - *  파티클을 동시에 업데이트하고 보이게 하기
        -=======
        - *  Simulataneously updates and displays a particle.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        + *  파티클을 업데이트하는 동시에 보이게 하기
          */
         Particle.prototype.run = function() {
           this.update();
        @@ -224,7 +145,7 @@ Particle.prototype.run = function() {
         }
         
         /**
        - *  A function to display a particle
        + *  파티클을 화면에 보이게하는 메소드
          */
         Particle.prototype.render = function() {
           imageMode(CENTER);
        @@ -233,24 +154,15 @@ Particle.prototype.render = function() {
         }
         
         /**
        -<<<<<<< HEAD
          *  파티클에 힘 벡터를 적용하는 메소드
        -=======
        - *  A method to apply a force vector to a particle.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         Particle.prototype.applyForce = function(f) {
           this.acc.add(f);
         }
         
         /**
        -<<<<<<< HEAD
          *  파티클의 lifespan(수명)이 끝나가는지 여부를 확인하는 메소드
          *  만약 끝나간다면 true(참)을, 그렇지 않다면 false(거짓)을 반환
        -=======
        - *  This method checks to see if the particle has reached the end of it's lifespan,
        - *  if it has, return true, otherwise return false.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         Particle.prototype.isDead = function () {
           if (this.lifespan <= 0.0) {
        @@ -261,11 +173,7 @@ Particle.prototype.isDead = function () {
         }
         
         /**
        -<<<<<<< HEAD
          *  파티클의 위치를 업데이트하는 메소드
        -=======
        - *  This method updates the position of the particle.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         Particle.prototype.update = function() {
           this.vel.add(this.acc);
        diff --git a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        index 6fb73163fc..3299544550 100644
        --- a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        +++ b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 브라운 운동
          * @description 무작위의 움직임을 연속된 선으로서 기록합니다.
          * 프로세싱(Processing) 홈페이지의 예제 페이지에 있는 원본 예제를 옮겨왔습니다.
        -=======
        - * @name Brownian Motion
        - * @description Recording random movement as a continuous line.
        - * Port of original example from the Processing examples page.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let num = 2000;
        @@ -29,17 +23,12 @@ function setup() {
         function draw() {
           background(51);
         
        -<<<<<<< HEAD
           // 모든 요소들을 좌측으로 1자리 이동
        -=======
        -  // Shift all elements 1 place to the left
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for ( let i = 1; i < num; i++ ) {
             ax[i - 1] = ax[i];
             ay[i - 1] = ay[i];
           }
         
        -<<<<<<< HEAD
           // 배열의 끝에 새로운 값 넣기
           ax[num - 1] += random(-range, range);
           ay[num - 1] += random(-range, range);
        @@ -49,17 +38,6 @@ function draw() {
           ay[num - 1] = constrain(ay[num - 1], 0, height);
         
           // 점들을 잇는 선 그리기
        -=======
        -  // Put a new value at the end of the array
        -  ax[num - 1] += random(-range, range);
        -  ay[num - 1] += random(-range, range);
        -
        -  // Constrain all points to the screen
        -  ax[num - 1] = constrain(ax[num - 1], 0, width);
        -  ay[num - 1] = constrain(ay[num - 1], 0, height);
        -
        -  // Draw a line connecting the points
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for ( let j = 1; j < num; j++ ) {
             let val = j / num * 204.0 + 51;
             stroke(val);
        diff --git a/src/data/examples/ko/09_Simulate/13_Chain.js b/src/data/examples/ko/09_Simulate/13_Chain.js
        index a7fc4d5979..48dd33d3fa 100644
        --- a/src/data/examples/ko/09_Simulate/13_Chain.js
        +++ b/src/data/examples/ko/09_Simulate/13_Chain.js
        @@ -1,14 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 사슬
          * @description 한 도형은 마우스 커서 위치에, 다른 하나는 이 도형의 위치에 붙어 따라옵니다.
          * 화면에는 중력이 작용하여 두 도형을 아래 방향으로 끌어당깁니다.
          * 프로세싱(Processing) 홈페이지의 예제 페이지에서 옮겨왔습니다.
        -=======
        - * @name Chain
        - * @description One mass is attached to the mouse position and the other is attached the position of the other mass. The gravity in the environment pulls down on both.
        - * Ported from the Processing Examples page.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let s1, s2;
         let gravity = 9.0;
        @@ -17,11 +11,7 @@ let mass = 2.0;
         function setup() {
           createCanvas(720, 400);
           fill(255, 126);
        -<<<<<<< HEAD
           // 입력: x, y, mass(질량), gravity(중력)
        -=======
        -  // Inputs: x, y, mass, gravity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           s1 = new Spring2D(0.0, width / 2, mass, gravity);
           s2 = new Spring2D(0.0, width / 2, mass, gravity);
         }
        @@ -35,15 +25,9 @@ function draw() {
         }
         
         function Spring2D(xpos, ypos, m, g) {
        -<<<<<<< HEAD
           this.x = xpos;// x 와 y 좌표
           this.y = ypos;
           this.vx = 0; // x축과 y축 속도
        -=======
        -  this.x = xpos;// The x- and y-coordinates
        -  this.y = ypos;
        -  this.vx = 0; // The x- and y-axis velocities
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           this.vy = 0;
           this.mass = m;
           this.gravity = g;
        diff --git a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        index 260dc3ee06..ad9e572770 100644
        --- a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        @@ -1,21 +1,11 @@
         /*
        -<<<<<<< HEAD
        - * @name 눈송이
        + * @name 눈송이 파티클
          * @description 이 파티클 시스템은 마치 떨어지는 눈송이같은 모션을 시뮬레이션합니다.
          * 눈송이 파티클을 담는 객체 배열을 사용합니다.
          * 애티쉬 바티아(Aatish Bhatia) 기여.
          */
         
         let snowflakes = []; // 눈송이 객체를 담는 배열
        -=======
        - * @name Snowflakes
        - * @description Particle system simulating the motion of falling snowflakes.
        - * Uses an array of objects to hold the snowflake particles.
        - * Contributed by Aatish Bhatia.
        - */
        -
        -let snowflakes = []; // array to hold snowflake objects
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(400, 600);
        @@ -25,7 +15,6 @@ function setup() {
         
         function draw() {
           background('brown');
        -<<<<<<< HEAD
           let t = frameCount / 60; // 시간 업데이트
         
           // 매 프라임마다 무작위 개수의 눈송이 생성
        @@ -43,31 +32,11 @@ function draw() {
         // snowflake 클래스
         function snowflake() {
           // 좌표값 초기화
        -=======
        -  let t = frameCount / 60; // update time
        -
        -  // create a random number of snowflakes each frame
        -  for (let i = 0; i < random(5); i++) {
        -    snowflakes.push(new snowflake()); // append snowflake object
        -  }
        -
        -  // loop through snowflakes with a for..of loop
        -  for (let flake of snowflakes) {
        -    flake.update(t); // update snowflake position
        -    flake.display(); // draw snowflake
        -  }
        -}
        -
        -// snowflake class
        -function snowflake() {
        -  // initialize coordinates
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           this.posX = 0;
           this.posY = random(-50, 0);
           this.initialangle = random(0, 2 * PI);
           this.size = random(2, 5);
         
        -<<<<<<< HEAD
           // 방사형 눈송이의 반지름
           // 눈송이를 화면에 고루 퍼뜨리기 위해 선택
           this.radius = sqrt(random(pow(width / 2, 2)));
        @@ -82,22 +51,6 @@ function snowflake() {
             this.posY += pow(this.size, 0.5);
         
             // 화면 하단을 지나친 눈송이는 삭제
        -=======
        -  // radius of snowflake spiral
        -  // chosen so the snowflakes are uniformly spread out in area
        -  this.radius = sqrt(random(pow(width / 2, 2)));
        -
        -  this.update = function(time) {
        -    // x position follows a circle
        -    let w = 0.6; // angular speed
        -    let angle = w * time + this.initialangle;
        -    this.posX = width / 2 + this.radius * sin(angle);
        -
        -    // different size snowflakes fall at slightly different y speeds
        -    this.posY += pow(this.size, 0.5);
        -
        -    // delete snowflake if past end of screen
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (this.posY > height) {
               let index = snowflakes.indexOf(this);
               snowflakes.splice(index, 1);
        diff --git a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        index 09a6a97f9f..40e17ca292 100644
        --- a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        +++ b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 펜로즈 타일
          * @frame 710,400
          * @description 이 예제는 데이비드 블리츠(David Blitz)가 processing.org/examples의 "펜로즈 타일(Penrose Tile)" 예제에서 옮겨왔습니다.
        -=======
        - * @name Penrose Tiles
        - * @frame 710,400
        - * @description This is a port by David Blitz of the "Penrose Tile" example from processing.org/examples
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let ds;
        @@ -15,11 +9,7 @@ let ds;
         function setup() {
           createCanvas(710, 400);
           ds = new PenroseLSystem();
        -<<<<<<< HEAD
           //다음의 줄과 함께 놀아보세요!
        -=======
        -  //please, play around with the following line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           ds.simulate(5);
         }
         
        @@ -31,28 +21,17 @@ function draw() {
         function PenroseLSystem() {
             this.steps = 0;
         
        -<<<<<<< HEAD
            //아래는 펜로즈 마름모 L-시스템의 공리와 규칙들입니다.
            //레퍼런스가 있다면 좋겠지만, 좋은 사례를 찾지 못했습니다.
        -=======
        -   //these are axiom and rules for the penrose rhombus l-system
        -   //a reference would be cool, but I couldn't find a good one
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             this.axiom = "[X]++[X]++[X]++[X]++[X]";
             this.ruleW = "YF++ZF----XF[-YF----WF]++";
             this.ruleX = "+YF--ZF[---WF--XF]+";
             this.ruleY = "-WF++XF[+++YF++ZF]-";
             this.ruleZ = "--YF++++WF[+ZF++++XF]--XF";
         
        -<<<<<<< HEAD
             //아래의 두 줄과 함께 놀아보세요!
             this.startLength = 460.0;
             this.theta = TWO_PI / 10.0; //36도, TWO_PI / 6.0도을 넣어보세요, ...
        -=======
        -    //please play around with the following two lines
        -    this.startLength = 460.0;
        -    this.theta = TWO_PI / 10.0; //36 degrees, try TWO_PI / 6.0, ...
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             this.reset();
         }
         
        @@ -72,23 +51,14 @@ PenroseLSystem.prototype.getAge = function () {
             return this.generations;
           }
         
        -<<<<<<< HEAD
         //대체 규칙을 적용하여, 문자열의 새로운 반복 생성
        -=======
        -//apply substitution rules to create new iteration of production string
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         PenroseLSystem.prototype.iterate = function() {
             let newProduction = "";
         
             for(let i=0; i < this.production.length; ++i) {
               let step = this.production.charAt(i);
        -<<<<<<< HEAD
               // 현재 문자가 'W'이면,
               // 이 현재 문자를 규칙에 맞게 대체합니다.
        -=======
        -      //if current character is 'W', replace current character
        -      //by corresponding rule
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               if (step == 'W') {
                 newProduction = newProduction + this.ruleW;
               }
        @@ -102,13 +72,8 @@ PenroseLSystem.prototype.iterate = function() {
                 newProduction = newProduction + this.ruleZ;
               }
               else {
        -<<<<<<< HEAD
                 // 모든 'F'를 drop 삭제하되, 
                 // 여타 문자들(예. '+', '-', '[', ']')은 건들지 않는다.
        -=======
        -        //drop all 'F' characters, don't touch other
        -        //characters (i.e. '+', '-', '[', ']'
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
                 if (step != 'F') {
                   newProduction = newProduction + step;
                 }
        @@ -120,11 +85,7 @@ PenroseLSystem.prototype.iterate = function() {
             this.production = newProduction;
         }
         
        -<<<<<<< HEAD
         //문자열을 거북이 그래픽으로 변환
        -=======
        -//convert production string to a turtle graphic
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         PenroseLSystem.prototype.render = function () {
             translate(width / 2, height / 2);
         
        @@ -136,11 +97,7 @@ PenroseLSystem.prototype.render = function () {
             for(let i=0; i<this.steps; ++i) {
               let step = this.production.charAt(i);
         
        -<<<<<<< HEAD
               //'W', 'X', 'Y', 'Z' 기호들은 거북이 동작에 상응하지 않습니다.
        -=======
        -      //'W', 'X', 'Y', 'Z' symbols don't actually correspond to a turtle action
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               if( step == 'F') {
                 stroke(255, 60);
                 for(let j=0; j < this.repeats; j++) {
        diff --git a/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        index 711b2c6007..c0c1ff2057 100644
        --- a/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        +++ b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 재귀 나무
          * @description 재귀를 통해 나무와 같은 구조를 간단히 렌더링합니다.
          * 나뭇가지의 분기 각도는 마우스 수평 위치에 대한 함수로써 계산됩니다.
          * 마우스를 좌우로 움직혀 각도를 바꿔보세요.
          * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/tree.html">재귀 나무 예제</a> 에서 옮겨왔습니다.
        -=======
        - * @name Recursive Tree
        - * @description Renders a simple tree-like structure via recursion.
        - * The branching angle is calculated as a function of the horizontal mouse
        - * location. Move the mouse left and right to change the angle.
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/tree.html">Recursive Tree Example</a> for Processing.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let theta;
         
        @@ -23,7 +15,6 @@ function draw() {
           background(0);
           frameRate(30);
           stroke(255);
        -<<<<<<< HEAD
           // 마우스 위치에 따라 0부터 90도 중 각도 한 개를 골라볼까요!
           let a = (mouseX / width) * 90;
           // 이를 라디안 값으로 전환합니다.
        @@ -35,26 +26,11 @@ function draw() {
           // 위의 선의 끝 지점으로 이동하기
           translate(0,-120);
           // 나뭇가지의 재귀적 분기 시작하기!
        -  branchㅌ(120);
        -=======
        -  // Let's pick an angle 0 to 90 degrees based on the mouse position
        -  let a = (mouseX / width) * 90;
        -  // Convert it to radians
        -  theta = radians(a);
        -  // Start the tree from the bottom of the screen
        -  translate(width/2,height);
        -  // Draw a line 120 pixels
        -  line(0,0,0,-120);
        -  // Move to the end of that line
        -  translate(0,-120);
        -  // Start the recursive branching!
           branch(120);
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         }
         
         function branch(h) {
        -<<<<<<< HEAD
           // 각각의 나뭇가지 크기는 이전 가지의 2/3에 해당합니다.
           h *= 0.66;
         
        @@ -69,22 +45,6 @@ function branch(h) {
             pop();     // 이 지점에 도달할 때 마다, 이전 매트릭스 상태를 복원하기 위해 "pop(팝)"합니다.
         
             // 같은 내용을 반복하되, 이번에는 "왼쪽"으로만 가지가 분기하도록 만듭니다!
        -=======
        -  // Each branch will be 2/3rds the size of the previous one
        -  h *= 0.66;
        -
        -  // All recursive functions must have an exit condition!!!!
        -  // Here, ours is when the length of the branch is 2 pixels or less
        -  if (h > 2) {
        -    push();    // Save the current state of transformation (i.e. where are we now)
        -    rotate(theta);   // Rotate by theta
        -    line(0, 0, 0, -h);  // Draw the branch
        -    translate(0, -h); // Move to the end of the branch
        -    branch(h);       // Ok, now call myself to draw two new branches!!
        -    pop();     // Whenever we get back here, we "pop" in order to restore the previous matrix state
        -
        -    // Repeat the same thing, only branch off to the "left" this time!
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             push();
             rotate(-theta);
             line(0, 0, 0, -h);
        diff --git a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        index 332db1a00d..6b41ae6ab4 100644
        --- a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        +++ b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 망델브로 집합
          * @description 망델브로(Mandelbrot) 집합을 간단히 렌더링합니다.
          * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/mandelbrot.html">망델브로 예제</a>에서 옮겨왔습니다.
        -=======
        - * @name The Mandelbrot Set
        - * @description Simple rendering of the Mandelbrot set.
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/mandelbrot.html">Mandelbrot Example</a> for Processing.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         function setup() {
        @@ -19,7 +13,6 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           // 복잡한 평면 위에서 값의 범위를 설정
           // 설정된 범위에 따라 프랙탈을 줌인 또는 줌아웃할 수 있습니다.
         
        @@ -55,43 +48,6 @@ function draw() {
             for (let i = 0; i < width; i++) {
         
               // 이제, 우리가 z = z^2 + cm 를 반복 할 때 z가 무한대로 향하나요?
        -=======
        -  // Establish a range of values on the complex plane
        -  // A different range will allow us to "zoom" in or out on the fractal
        -
        -  // It all starts with the width, try higher or lower values
        -  const w = 4;
        -  const h = (w * height) / width;
        -
        -  // Start at negative half the width and height
        -  const xmin = -w/2;
        -  const ymin = -h/2;
        -
        -  // Make sure we can write to the pixels[] array.
        -  // Only need to do this once since we don't do any other drawing.
        -  loadPixels();
        -
        -  // Maximum number of iterations for each point on the complex plane
        -  const maxiterations = 100;
        -
        -  // x goes from xmin to xmax
        -  const xmax = xmin + w;
        -  // y goes from ymin to ymax
        -  const ymax = ymin + h;
        -
        -  // Calculate amount we increment x,y for each pixel
        -  const dx = (xmax - xmin) / (width);
        -  const dy = (ymax - ymin) / (height);
        -
        -  // Start y
        -  let y = ymin;
        -  for (let j = 0; j < height; j++) {
        -    // Start x
        -    let x = xmin;
        -    for (let i = 0; i < width; i++) {
        -
        -      // Now we test, as we iterate z = z^2 + cm does z tend towards infinity?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               let a = x;
               let b = y;
               let n = 0;
        @@ -101,37 +57,22 @@ function draw() {
                 const twoab = 2.0 * a * b;
                 a = aa - bb + x;
                 b = twoab + y;
        -<<<<<<< HEAD
                 // 이 유한한 세상에서의 무한대 개념은 간단합니다. 여기서는 그냥 16이라 설정하지요.
                 if (dist(aa, bb, 0, 0) > 16) {
                   break; 
        -=======
        -        // Infinty in our finite world is simple, let's just consider it 16
        -        if (dist(aa, bb, 0, 0) > 16) {
        -          break;  // Bail
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
                 }
                 n++;
               }
         
        -<<<<<<< HEAD
               // 무한대에 도달하기까지 걸리는 시간을 기준으로 각 픽셀에 색상을 지정합니다.
               // 도달하지 못할 경우, 검정색으로 지정합니다.
        -=======
        -      // We color each pixel based on how long it takes to get to infinity
        -      // If we never got there, let's pick the color black
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               const pix = (i+j*width)*4;
               const norm = map(n, 0, maxiterations, 0, 1);
               let bright = map(sqrt(norm), 0, 1, 0, 255);
               if (n == maxiterations) {
                 bright = 0;
               } else {
        -<<<<<<< HEAD
                 // 원한다면 여기서 좀 더 화려한 색상을 만들 수 있습니다.
        -=======
        -        // Gosh, we could make fancy colors here if we wanted
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
                 pixels[pix + 0] = bright;
                 pixels[pix + 1] = bright;
                 pixels[pix + 2] = bright;
        diff --git a/src/data/examples/ko/09_Simulate/18_Koch.js b/src/data/examples/ko/09_Simulate/18_Koch.js
        new file mode 100644
        index 0000000000..cdac9067e5
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/18_Koch.js
        @@ -0,0 +1,141 @@
        +/*
        + * @name 코흐 곡선
        + * @description 간단한 코흐 곡선 즉, 눈송이형 프랙탈을 만듭니다.
        + * 각각의 재귀 단계는 순차적으로 그려집니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 제작
        + */
        +
        +let k;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  frameRate(1);  // 천천히 움직이기
        +  k = new KochFractal();
        +}
        +
        +function draw() {
        +  background(0);
        +  // 눈송이 그리기!
        +  k.render();
        +  // 반복하기
        +  k.nextLevel();
        +  // 5회를 초과하진 않습니다...
        +  if (k.getCount() > 5) {
        +    k.restart();
        +  }
        +}
        +
        +// 선 하나를 프랙탈로 표현해주는 클래스
        +// midp5.Vectors가 코크 알고리즘에 의거하여 선을 계산하는 메소드를 포함합니다.
        +
        +class KochLine {
        +  constructor(a,b) {
        +    // 두개의 p5.Vectors,
        +    // 시작은 "왼쪽" p5.Vector이고
        +    // 끝은 "오른쪽" p5.Vector입니다.
        +    this.start = a.copy();
        +    this.end = b.copy();
        +  }
        +
        +  display() {
        +    stroke(255);
        +    line(this.start.x, this.start.y, this.end.x, this.end.y);
        +  }
        +
        +  kochA() {
        +    return this.start.copy();
        +  }
        +
        +  // 쉽지요? 여기까지 전체 내용의 1/3을 진행했어요.
        +  kochB() {
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.div(3);
        +    v.add(this.start);
        +    return v;
        +  }
        +
        +  // 약간 복잡한데요, 이 p5의 위치를 알아내기 위해 약간의 삼각법을 사용합니다!
        +  kochC() {
        +    let a = this.start.copy(); // Start at the beginning
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.div(3);
        +    a.add(v);  // 점 B로 이동하기
        +    v.rotate(-PI/3); // 60도 회전하기
        +    a.add(v);  // 점 C로 이동하기
        +    return a;
        +  }
        +
        +  // 쉽지요? 여기까지 전체 내용의 2/3을 진행했어요.
        +  kochD() {
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.mult(2/3.0);
        +    v.add(this.start);
        +    return v;
        +  }
        +
        +  kochE() {
        +    return this.end.copy();
        +  }
        +}
        +
        +//눈송이 패턴을 갖는 선분들을 배열로 관리하는 클래스입니다.
        +class KochFractal {
        +  constructor() {
        +    this.start = createVector(0,height-20);   // 시작점 p5.Vector
        +    this.end = createVector(width,height-20); // 끝점 p5.Vector
        +    this.lines = [];                         // 모든 선분을 추적하는 배열
        +    this.count = 0;
        +    this.restart();
        +  }
        +
        +  nextLevel() {
        +    // 배열에 담긴 각각의 선분들에 대해
        +    // 4개의 선분들을 추가한, 새로운 배열을 만듭니다.
        +    this.lines = this.iterate(this.lines);
        +    this.count++;
        +  }
        +
        +  restart() {
        +    this.count = 0;      // 카운트 리셋하기
        +    this.lines = [];  // 배열 비우기
        +    this.lines.push(new KochLine(this.start,this.end));  // 초기 선분 더하기(하나의 끝점 p5.Vector에서 다른 p5.Vector로)
        +  }
        +
        +  getCount() {
        +    return this.count;
        +  }
        +
        +  // 이 부분도 쉽습니다. 모든 선들을 그리는 함수이지요.
        +  render() {
        +    for(let i = 0; i < this.lines.length; i++) {
        +      this.lines[i].display();
        +    }
        +  }
        +
        +  // This is where the **MAGIC** happens
        +  // Step 1: Create an empty arraylist
        +  // Step 2: For every line currently in the arraylist
        +  //   - calculate 4 line segments based on Koch algorithm
        +  //   - add all 4 line segments into the new arraylist
        +  // Step 3: Return the new arraylist and it becomes the list of line segments for the structure
        +
        +  // As we do this over and over again, each line gets broken into 4 lines, which gets broken into 4 lines, and so on. . .
        +  iterate(before) {
        +    let now = [];    // Create emtpy list
        +    for(let i = 0; i < this.lines.length; i++) {
        +      let l = this.lines[i];
        +      // Calculate 5 koch p5.Vectors (done for us by the line object)
        +      let a = l.kochA();
        +      let b = l.kochB();
        +      let c = l.kochC();
        +      let d = l.kochD();
        +      let e = l.kochE();
        +      // Make line segments between all the p5.Vectors and add them
        +      now.push(new KochLine(a,b));
        +      now.push(new KochLine(b,c));
        +      now.push(new KochLine(c,d));
        +      now.push(new KochLine(d,e));
        +    }
        +    return now;
        +  }
        +}
        diff --git a/src/data/examples/ko/09_Simulate/19_Bubblesort.js b/src/data/examples/ko/09_Simulate/19_Bubblesort.js
        new file mode 100644
        index 0000000000..bff2f5a7bf
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/19_Bubblesort.js
        @@ -0,0 +1,66 @@
        +/*
        + * @name 버블 정렬
        + * @description 전체 정렬 과정을 시뮬레이션하면서,
        + * 무작위로 분포된 막대들을 그 높이에 따라 오름차순으로 정렬합니다.
        + * 코딩 트레인(Coding Train)의 코딩 챌린지(Coding Challenge)를 참조하였습니다.
        + */
        +
        +let values = [];
        +let i = 0;
        +let j = 0;
        +
        +// setup() 함수 속 명령문들은
        +// 프로그램 시작시 한 번 실행됩니다.
        +// 배열은 setup()함수를 통해 임의의 값들로 채워집니다.
        +function setup() {
        +  createCanvas(720, 400);
        +  for(let i = 0;i<width/8;i++){
        +    values.push(random(height));
        +  }
        +}
        +
        +// draw() 함수 속 명령문들은 
        +// 프로그램이 멈출 때까지 실행됩니다.
        +// 각 명령문은 순차적으로 실행되며,
        +// 마지막 명령문 실행한 후에는 첫 명령문으로 돌아가 실행합니다.
        +function draw() {
        +  background(220);
        +  bubbleSort();
        +  simulateSorting();
        +}
        +
        +// bubbleSort() 함수는 매 프레임마다
        +// 8개의 배열 요소를 가져옵니다.
        +// 이 함수가 사용하는 알고리즘은 버블 정렬입니다.
        +function bubbleSort() {
        +  for(let k = 0;k<8;k++){
        +    if(i<values.length){
        +      let temp = values[j];
        +      if(values[j] > values[j+1]){
        +        values[j] = values[j+1];
        +        values[j+1] = temp;
        +      }
        +      j++;
        +      
        +      if(j>=values.length-i-1){
        +        j = 0;
        +        i++;
        +      }
        +    }
        +    else{
        +      noLoop();
        +    }
        +  }
        +}
        +
        +// simulateSorting() 함수는 버블 정렬 알고리즘에
        +// 애니메이션을 적용합니다.
        +// 이 함수는 배열의 값을 사각형 길이로 치환해
        +// 사각형을 그립니다.
        +function simulateSorting(){
        +  for(let i = 0;i<values.length;i++){
        +    stroke(100, 143, 143);
        +     fill(50);
        +     rect(i*8 , height, 8, -values[i],20);
        +   }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/20_SteepingFeet.js b/src/data/examples/ko/09_Simulate/20_SteepingFeet.js
        new file mode 100644
        index 0000000000..a2c017f424
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/20_SteepingFeet.js
        @@ -0,0 +1,81 @@
        +/*
        + * @name 스테핑 피트 일루전
        + * @description 스테핑 피트 이루전(Stepping feet illusion)은 저명한
        + * 심리학 실험입니다.
        + * 두 사각형은 동일한 속도로 움직이나,
        + * 마치 다른 속도로 움직이는 것처럼 보입니다.
        + * 캔버스를 마우스로 클릭해 두 사각형이 동일한 속도로
        + * 이동하는지 확인해보세요.
        + * 사가 아로라(Sagar Arora) 기여.
        + */
        +
        +// 이 클래스는 전체 구조와 사각형의 움직임을
        +// 표현합니다.
        +class Brick{
        +  constructor(bc, y){
        +    this.brickColor = bc;
        +    this.yPos = y;
        +    this.xPos = 0;
        +  }
        +
        +  // 이 함수는 사각형을 생성합니다.
        +  createBrick(){
        +    fill(this.brickColor);
        +    rect(this.xPos, this.yPos, 100, 50);
        +  }
        +
        +  // 이 함수는 사각형의 움직임을 1로
        +  // 설정합니다. 
        +  setSpeed(){
        +    this.xSpeed = 1;
        +  }
        +
        +  // 이 함수는 사각형을 움직입니다.
        +  moveBrick(){
        +    this.xPos+=this.xSpeed;
        +    if(this.xPos+100 >= width || this.xPos <= 0){
        +      this.xSpeed*=-1;
        +    }
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  createP("Keep the mouse clicked").style('color','#ffffff');
        +  createP("to check whether the bricks").style('color','#ffffff');
        +  createP("are moving at same speed or not").style('color','#ffffff');
        +}
        +
        +// 두 개의 사각형을 각각
        +// 흰색과 검정색으로 지정합니다.
        +let brick1 = new Brick("white",100);
        +let brick2 = new Brick("black",250);
        +
        +//
        +brick1.setSpeed();
        +brick2.setSpeed();
        +
        +function draw () {
        +  background(0);
        +  if(mouseIsPressed){
        +    background(50);
        +  }
        +  brick1.createBrick();
        +  brick1.moveBrick();
        +  if(!mouseIsPressed){
        +    createBars();
        +  }
        +  brick2.createBrick();
        +  brick2.moveBrick();
        +}
        +
        +// 이 함수는 화면에
        +// 검정색 및 흰색 막대기들을 생성합니다.
        +function createBars() {
        +  let len = 12;
        +  for(let i = 0;i<width/len;i++){
        +    fill("white");
        +    if(i%2 == 0)
        +    rect(i*len,height,len,-height);
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/21_Particle.js b/src/data/examples/ko/09_Simulate/21_Particle.js
        new file mode 100644
        index 0000000000..8b953d7235
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/21_Particle.js
        @@ -0,0 +1,68 @@
        +/*
        + * @name 파티클
        + * @description particle.js는 가벼운 자바스크립트 라이브러리로,
        + * 매우 아름다운 파티클 시스템을 만듭니다.
        + * 이 예제는 p5.js를 사용하여 particle.js의 파티클 시스템을 재현합니다.
        + * 사가 아로라(Sagar Arora)가 기여하고, Particle.js로부터 영감을 얻었습니다.
        + */
        +
        +
        +// 이 클래스는 각 파티클의 속성들을 표현합니다.
        +class Particle {
        +// 파티클의 좌표값, 반경, 그리고 속도를
        +// 두 좌표축에 의거하여 설정합니다.
        +  constructor(){
        +    this.x = random(0,width);
        +    this.y = random(0,height);
        +    this.r = random(1,8);
        +    this.xSpeed = random(-2,2);
        +    this.ySpeed = random(-1,1.5);
        +  }
        +
        +// 파티클 생성하기
        +  createParticle() {
        +    noStroke();
        +    fill('rgba(200,169,169,0.5)');
        +    circle(this.x,this.y,this.r);
        +  }
        +
        +// 파티클이 움직이도록 설정하기
        +  moveParticle() {
        +    if(this.x < 0 || this.x > width)
        +      this.xSpeed*=-1;
        +    if(this.y < 0 || this.y > height)
        +      this.ySpeed*=-1;
        +    this.x+=this.xSpeed;
        +    this.y+=this.ySpeed;
        +  }
        +
        +// 이 함수는 특정 거리 안쪽에 위치한 파티클들 사이에 연결선을 만듭니다.
        +  joinParticles(paraticles) {
        +    particles.forEach(element =>{
        +      let dis = dist(this.x,this.y,element.x,element.y);
        +      if(dis<85) {
        +        stroke('rgba(255,255,255,0.04)');
        +        line(this.x,this.y,element.x,element.y);
        +      }
        +    });
        +  }
        +}
        +
        +// 복수의 파티클들을 추가하기 위한 배열
        +let particles = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  for(let i = 0;i<width/10;i++){
        +    particles.push(new Particle());
        +  }
        +}
        +
        +function draw() {
        +  background('#0f0f0f');
        +  for(let i = 0;i<particles.length;i++) {
        +    particles[i].createParticle();
        +    particles[i].moveParticle();
        +    particles[i].joinParticles(particles.slice(i));
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/10_Interaction/10_Tickle.js b/src/data/examples/ko/10_Interaction/10_Tickle.js
        index c4e027688a..1a013d41a9 100644
        --- a/src/data/examples/ko/10_Interaction/10_Tickle.js
        +++ b/src/data/examples/ko/10_Interaction/10_Tickle.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 간질간질
          * @description 마우스 커서를 갖다대면 "tickle"이라는 단어가 간지럼을 타듯 떨립니다.
          * 너무 간지럽히면 화면 밖으로 튀어나갈 수도 있습니다 XD
        @@ -10,18 +9,6 @@ let message = 'tickle',
           fontsize = 60,
           x,
           y; // 텍스트의 x 와 y 좌표
        -=======
        - * @name Tickle
        - * @description The word "tickle" jitters when the cursor hovers over.
        - * Sometimes, it can be tickled off the screen.
        - */
        -let message = 'tickle',
        -  font,
        -  bounds, // holds x, y, w, h of the text's bounding box
        -  fontsize = 60,
        -  x,
        -  y; // x and y coordinates of the text
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function preload() {
           font = loadFont('assets/SourceSansPro-Regular.otf');
        @@ -30,19 +17,11 @@ function preload() {
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 폰트 설정
           textFont(font);
           textSize(fontsize);
         
           // 초기화시 중앙 정렬을 하기 위해 텍스트의 너비 및 높이값을 받아옴
        -=======
        -  // set up the font
        -  textFont(font);
        -  textSize(fontsize);
        -
        -  // get the width and height of the text so we can center it initially
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           bounds = font.textBounds(message, 0, 0, fontsize);
           x = width / 2 - bounds.w / 2;
           y = height / 2 - bounds.h / 2;
        @@ -51,20 +30,12 @@ function setup() {
         function draw() {
           background(204, 120);
         
        -<<<<<<< HEAD
           // 텍스트를 검정색으로 쓰고 그 바운딩 박스를 받아옴
        -=======
        -  // write the text in black and get its bounding box
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(0);
           text(message, x, y);
           bounds = font.textBounds(message, x, y, fontsize);
         
        -<<<<<<< HEAD
           // 마우스가 바운딩 박스 안에 있는지를 확인하고, 안에 있다면 간질간질!
        -=======
        -  // check if the mouse is inside the bounding box and tickle if so
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (
             mouseX >= bounds.x &&
             mouseX <= bounds.x + bounds.w &&
        diff --git a/src/data/examples/ko/10_Interaction/20_Follow1.js b/src/data/examples/ko/10_Interaction/20_Follow1.js
        index 2aae9e66c9..c5b35b3a13 100644
        --- a/src/data/examples/ko/10_Interaction/20_Follow1.js
        +++ b/src/data/examples/ko/10_Interaction/20_Follow1.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
        - * @name 따라가기 1
        + * @name 따라다니기 1
          * @frame 710,400
          * @description 마우스 커서로 선분을 밀고 당깁니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Follow 1
        - * @frame 710,400
        - * @description A line segment is pushed and pulled by the cursor.
        - * Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let x = 100,
           y = 100,
        diff --git a/src/data/examples/ko/10_Interaction/21_Follow2.js b/src/data/examples/ko/10_Interaction/21_Follow2.js
        index 005bb2f6e6..276ebaa52b 100644
        --- a/src/data/examples/ko/10_Interaction/21_Follow2.js
        +++ b/src/data/examples/ko/10_Interaction/21_Follow2.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 따라다니기 2
          * @frame 710,400
          * @description 팔 형상의 두 선분이 마우스 커서의 위치를 따라다닙니다.
          * 선분들 사이의 상대 각도는 atan2()로, 그 위치는 sin()과 cos()로 계산됩니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Follow 2
        - * @frame 710,400
        - * @description A two-segmented arm follows the cursor position. The relative
        - * angle between the segments is calculated with atan2() and the position
        - * calculated with sin() and cos(). Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let x = [0, 0],
           y = [0, 0],
        diff --git a/src/data/examples/ko/10_Interaction/22_Follow3.js b/src/data/examples/ko/10_Interaction/22_Follow3.js
        index fe18d039b3..7f585e572b 100644
        --- a/src/data/examples/ko/10_Interaction/22_Follow3.js
        +++ b/src/data/examples/ko/10_Interaction/22_Follow3.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 따라다니기 3
          * @frame 710,400
          * @description 선분이 마우스를 따라다닙니다. 한 선분의 다음 선분에 대한 상대 각도는 atan2()로,
          * 다음 선분의 위치는 sin()과 cos()로 계산됩니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Follow 3
        - * @frame 710,400
        - * @description A segmented line follows the mouse. The relative angle from
        - * each segment to the next is calculated with atan2() and the position of
        - * the next is calculated with sin() and cos(). Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let x = [],
           y = [],
        diff --git a/src/data/examples/ko/10_Interaction/23_snake.js b/src/data/examples/ko/10_Interaction/23_snake.js
        index f31a1f9525..10422434f6 100644
        --- a/src/data/examples/ko/10_Interaction/23_snake.js
        +++ b/src/data/examples/ko/10_Interaction/23_snake.js
        @@ -1,25 +1,18 @@
         /*
        -<<<<<<< HEAD
          * @name 스네이크 게임
          * @description 그 유명한 스네이크 게임입니다! 실행(run)을 누르고, 
          * 검은 화면 위 아무 지점을 클릭한 뒤, i,j,k,l 키로 뱀을 조종할 수 있습니다.
        - * 뱀이 벽이나 자신의 몸통에 닿지 않도록 하세요!<br>
        - * 예제 제작: <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta
        -=======
        - * @name Snake game
        - * @description The famous snake game! Once you click run, click anywhere
        - * inside the black area, and control the snake using i j k and l. Don't let
        - * the snake hit itself or the wall!<br>
        - * Example created by <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        + * 뱀이 벽이나 자신의 몸에 닿지 않도록 하세요!<br>
        + * 예제 제작: <a href='https://github.com/prashantgupta24' target='_blank'>프라샨트 굽타(Prashant Gupta)
          */
         
        -// the snake is divided into small segments, which are drawn and edited on each 'draw' call
        +// 뱀의 형상은 작은 조각(segment)들로 구성되는데,
        +// 이는 매 'draw' 호출에서 그려지고 수정됩니다.
         let numSegments = 10;
         let direction = 'right';
         
        -const xStart = 0; //starting x coordinate for snake
        -const yStart = 250; //starting y coordinate for snake
        +const xStart = 0; // 뱀의 시작 x좌표
        +const yStart = 250; // 뱀의 시작 y좌표
         const diff = 10;
         
         let xCor = [];
        @@ -58,15 +51,12 @@ function draw() {
         }
         
         /*
        - The segments are updated based on the direction of the snake.
        - All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0
        - gets the value of segment 1, segment 1 gets the value of segment 2, and so on,
        - and this results in the movement of the snake.
        -
        - The last segment is added based on the direction in which the snake is going,
        - if it's going left or right, the last segment's x coordinate is increased by a
        - predefined value 'diff' than its second to last segment. And if it's going up
        - or down, the segment's y coordinate is affected.
        + 뱀의 방향에 따라, 뱀의 형상을 구성하는 작은 조각(segment)들의 위치가 업데이트됩니다.
        + 0에서 n-1까지의 모든 조각들은 n에 도달할 때까지 그 다음 조각의 위치를 복사합니다.
        + 예를 들어, segment 0은 segment 1의 값을 받고, segment 1은 segment 2의 값을 받습니다. 뱀은 이러한 과정을 통해 움직이는 것입니다.
        + 이 때, 마지막 조각(segment)은 뱀이 가는 방향에 따라 추가됩니다. 
        + 뱀이 좌우로 움직일 때 가장 마지막 조각의 x값은, 마지막에서 두번째 조각의 x값보다 'diff'값만큼 증가합니다.
        + 뱀이 상하로 움직일 때는 가장 마지막 조각의 y값이 증가하는 식입니다.
         */
         function updateSnakeCoordinates() {
           for (let i = 0; i < numSegments - 1; i++) {
        @@ -94,9 +84,8 @@ function updateSnakeCoordinates() {
         }
         
         /*
        - I always check the snake's head position xCor[xCor.length - 1] and
        - yCor[yCor.length - 1] to see if it touches the game's boundaries
        - or if the snake hits itself.
        + 전 항상 뱀의 머리 위치인 xCor[xCor.length - 1]와
        + yCor[yCor.length - 1]를 확인하여 뱀이 화면 경계나 자신의 몸에 닿는지를 본답니다.
         */
         function checkGameStatus() {
           if (
        @@ -113,8 +102,8 @@ function checkGameStatus() {
         }
         
         /*
        - If the snake hits itself, that means the snake head's (x,y) coordinate
        - has to be the same as one of its own segment's (x,y) coordinate.
        + 뱀이 자신의 몸에 닿았다는건 다시말해, 뱀의 머리의 (x,y)좌표가
        + 조각(segment)들 중 한 (x,y)좌표와 일치한다는 것입니다.
         */
         function checkSnakeCollision() {
           const snakeHeadX = xCor[xCor.length - 1];
        @@ -127,9 +116,7 @@ function checkSnakeCollision() {
         }
         
         /*
        - Whenever the snake consumes a fruit, I increment the number of segments,
        - and just insert the tail segment again at the start of the array (basically
        - I add the last segment again at the tail, thereby extending the tail)
        + 뱀이 과일을 먹을 때마다 조각의 수가 증가하고, 배열의 시작에 꼬리 조각이 다시 삽입되도록 설정했습니다.(기본적으로, 마지막 조각을 꼬리 부분에 추가하여 꼬리를 늘리는 식이지요.)
         */
         function checkForFruit() {
           point(xFruit, yFruit);
        @@ -145,9 +132,10 @@ function checkForFruit() {
         
         function updateFruitCoordinates() {
           /*
        -    The complex math logic is because I wanted the point to lie
        -    in between 100 and width-100, and be rounded off to the nearest
        -    number divisible by 10, since I move the snake in multiples of 10.
        +    여기서 복잡한 연산 논리가 추가된 이유는
        +    뱀이 10의 배수 단위로 움직이도록 설정했기 때문입니다.
        +    점을 너비 100과 -100 사이에 있도록 하고,
        +    그 위치값이 가장 가까운 10의 배수 숫자로 반올림되도록 처리하였습니다.
           */
         
           xFruit = floor(random(10, (width - 100) / 10)) * 10;
        diff --git a/src/data/examples/ko/10_Interaction/24_Wavemaker.js b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        index 275ddf8d45..85d0a0e979 100644
        --- a/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        +++ b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        @@ -1,22 +1,12 @@
         /*
        -<<<<<<< HEAD
          * @name 파도 만들기
          * @description 이 예제는 특정 위치에서 진동하는 파티클로 파도를 만드는 법을 설명합니다.
          * 마우스를 움직여 파도의 방향을 바꿔보세요.
        - * 애티쉬 바티아(Aatish Bhatia) 기여, Dan Whyte 제작 <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a>
        + * 애티쉬 바티아(Aatish Bhatia) 기여, 댄 와이트(Dan Whyte) 제작 <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a>
          * 로부터 영감을 받았습니다.
          */
         
         let t = 0; // 시간 변수
        -=======
        - * @name Wavemaker
        - * @description This illustrates how waves (like water waves) emerge
        - * from particles oscillating in place. Move your mouse to direct the wave.
        - * Contributed by Aatish Bhatia, inspired by <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a> by Dave Whyte.
        - */
        -
        -let t = 0; // time variable
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(600, 600);
        @@ -25,7 +15,6 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           background(10, 10); // 불투명한 배경화면(파티클의 꼬리 만들기)
         
           // 타원형으로 구성된 x와 y 그리드 만들기
        @@ -46,26 +35,4 @@ function draw() {
           }
         
           t = t + 0.01; // 시간 업데이트
        -=======
        -  background(10, 10); // translucent background (creates trails)
        -
        -  // make a x and y grid of ellipses
        -  for (let x = 0; x <= width; x = x + 30) {
        -    for (let y = 0; y <= height; y = y + 30) {
        -      // starting point of each circle depends on mouse position
        -      const xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true);
        -      const yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true);
        -      // and also varies based on the particle's location
        -      const angle = xAngle * (x / width) + yAngle * (y / height);
        -
        -      // each particle moves in a circle
        -      const myX = x + 20 * cos(2 * PI * t + angle);
        -      const myY = y + 20 * sin(2 * PI * t + angle);
        -
        -      ellipse(myX, myY, 10); // draw particle
        -    }
        -  }
        -
        -  t = t + 0.01; // update time
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
        diff --git a/src/data/examples/ko/10_Interaction/25_reach1.js b/src/data/examples/ko/10_Interaction/25_reach1.js
        index 04d1303d29..483283d3da 100644
        --- a/src/data/examples/ko/10_Interaction/25_reach1.js
        +++ b/src/data/examples/ko/10_Interaction/25_reach1.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 팔닿기 1
          * @frame 710,400
          * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Reach 1
        - * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let segLength = 80,
           x,
        diff --git a/src/data/examples/ko/10_Interaction/26_reach2.js b/src/data/examples/ko/10_Interaction/26_reach2.js
        index e9e33fc874..d6b1ae8272 100644
        --- a/src/data/examples/ko/10_Interaction/26_reach2.js
        +++ b/src/data/examples/ko/10_Interaction/26_reach2.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 팔닿기 2
          * @frame 710,400
          * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Reach 2
        - * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let numSegments = 10,
           x = [],
        @@ -30,13 +23,8 @@ function setup() {
           strokeWeight(20);
           stroke(255, 100);
         
        -<<<<<<< HEAD
           x[x.length - 1] = width / 2; // 기본 x좌표 설정
           y[x.length - 1] = height; // 기본 y좌표 설정
        -=======
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/10_Interaction/27_reach3.js b/src/data/examples/ko/10_Interaction/27_reach3.js
        index a8b5c0450d..fdf58bc952 100644
        --- a/src/data/examples/ko/10_Interaction/27_reach3.js
        +++ b/src/data/examples/ko/10_Interaction/27_reach3.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 팔닿기 3
          * @frame 710,400
          * @description 팔모양이 공의 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
          * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
        -=======
        - * @name Reach 3
        - * @frame 710,400
        - * @description The arm follows the position of the ball by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let numSegments = 8,
           x = [],
        @@ -35,13 +28,8 @@ function setup() {
           stroke(255, 100);
           noFill();
         
        -<<<<<<< HEAD
           x[x.length - 1] = width / 2; // 기본 x좌표 설정
           y[x.length - 1] = height; // 기본 y좌표 설정
        -=======
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js b/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
        new file mode 100644
        index 0000000000..e801838d69
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
        @@ -0,0 +1,38 @@
        +/*
        + * @name WebJack과 아두이노 센서 데이터
        + * @description 웹잭(WebJack)은 오디오를 사용하여 아두이노와
        + * 다른 소스들로부터 데이터를 읽어오는 한 방식입니다.
        + * 기본적으로, 아두이노를 오디오 모뎀으로 변환합니다.
        + * 
        + * https://github.com/publiclab/webjack
        + * 
        + * 주의: 이 예제를 로컬 프로젝트에서 실행하려면, index.html 파일에 WebJack과 p5-webjack 라이브러리를 다음과같이 추가해야 합니다:
        + * <pre><code class="language-markup">&lt;script src="https://webjack.io/dist/webjack.js">&lt;/script></code></pre>
        + * <pre><code class="language-markup">&lt;script src="https://jywarren.github.io/p5-webjack/lib.js">&lt;/script></code></pre>
        + * 
        + * 작동 예시: https://editor.p5js.org/jywarren/sketches/rkztwSt8M
        + * 
        + * 오디오 테스팅: https://www.youtube.com/watch?v=GtJW1Dlt3cg
        + * 이 스케치를 아두이노로 불러오세요: 
        + * https://create.arduino.cc/editor/jywarren/023158d8-be51-4c78-99ff-36c63126b554/preview
        + * 아두이노가 pin 3 + ground로부터 오디오를 출력할 것입니다. 마이크나 오디오 케이블을 사용하세요.
        + */
        +
        +function setup() { 
        +  createCanvas(400, 400);
        +  noStroke();
        +  fill('#ff00aa22');
        +  receiveSensorData(handleData);
        +}
        +
        +function handleData(data, connection) {
        +
        +  console.log(data); // 값을 로그에 출력
        +  // data[0] = 첫번째 값, data[1] = 두번째 값 ...
        +
        +  // 그려보세요! 참고: http://p5js.org/reference/
        +  background('#ddd');
        +  ellipse(100, 200, data[0]+10, data[0]+10);
        +
        +  // connection.send('아두이노가 오디오리스닝 중이라면 아두이노로 데이터를 다시 전송하기');
        +}
        diff --git a/src/data/examples/ko/10_Interaction/29_kaleidoscope.js b/src/data/examples/ko/10_Interaction/29_kaleidoscope.js
        new file mode 100644
        index 0000000000..56b1b24cb7
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/29_kaleidoscope.js
        @@ -0,0 +1,76 @@
        +/*
        + * @name 만화경
        + * @description
        +436/5000
        +만화경은 두 개 이상의 반사면이 서로를 향해 비스듬히 기울어진 광학 기기를 말합니다.
        +이 예제는 만화경의 작동 원리를 복제하고 재현합니다. "대칭(symmetry)" 변수를 통해 반사 횟수를 조정하고 화면 위에 그림을 그려보세요.
        +슬라이더를 사용하여 브러시 크기를 조정할 수 있습니다. "clearButton"은 화면을 지웁니다. "saveButton" 버튼은 사용자가 만든 작품을 .jpg 파일로 다운로드합니다.
        +*/
        +// 반사 횟수에 따른 대칭을 설정합니다. 반사 횟수를 조정해보세요.
        +let symmetry = 6;   
        +
        +let angle = 360 / symmetry;
        +let saveButton, clearButton, mouseButton, keyboardButton;
        +let slider;
        +
        +function setup() { 
        +  createCanvas(710, 710);
        +  angleMode(DEGREES);
        +  background(127);
        +
        +  // 파일 저장을 위한 saveButton 생성하기
        +  saveButton = createButton('save');
        +  saveButton.mousePressed(saveFile);
        +
        +  // 화면 지우기를 위한 claerButton 생성하기
        +  clearButton = createButton('clear');
        +  clearButton.mousePressed(clearScreen);
        +
        +  // 전체 화면 보기를 위한 fullscreenButton 생성하기
        +  fullscreenButton = createButton('Full Screen');
        +  fullscreenButton.mousePressed(screenFull);
        +
        +  // 브러시 두께 조정을 위한 슬라이더 설정하기
        +  brushSizeSlider = createButton('Brush Size Slider');
        +  sizeSlider = createSlider(1, 32, 4, 0.1);
        +}
        +
        +// 파일 저장 함수
        +function saveFile() {
        +  save('design.jpg');
        +}
        +
        +// 화면 지우기 함수
        +function clearScreen() {
        +  background(127);
        +}
        +
        +// 전체 화면 보기 함수
        +function screenFull() {
        +  let fs = fullscreen();
        +  fullscreen(!fs);
        +}
        +
        +function draw() {
        +  translate(width / 2, height / 2);
        +
        +  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
        +    let mx = mouseX - width / 2;
        +    let my = mouseY - height / 2;
        +    let pmx = pmouseX - width / 2;
        +    let pmy = pmouseY - height / 2;
        +    
        +    if (mouseIsPressed) {
        +      for (let i = 0; i < symmetry; i++) {
        +        rotate(angle);
        +        let sw = sizeSlider.value();
        +        strokeWeight(sw);
        +        line(mx, my, pmx, pmy);
        +        push();
        +        scale(1, -1);
        +        line(mx, my, pmx, pmy);
        +        pop();
        +      }
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/01_Objects.js b/src/data/examples/ko/11_Objects/01_Objects.js
        index 53dd9c6f4e..cffbe8d85c 100644
        --- a/src/data/examples/ko/11_Objects/01_Objects.js
        +++ b/src/data/examples/ko/11_Objects/01_Objects.js
        @@ -1,29 +1,15 @@
         /*
        -<<<<<<< HEAD
        - * @name 객체(object)
        + * @name 객체
          * @description Jitter 클래스를 만들고, 객체를 인스턴스화하여
        - * 화면 안에서 움직여보세요. 캐시 리아즈(Casey Reas) & 벤 프라이(Ben Fry) 저 Getting Started with
        + * 화면 안에서 움직여보세요. 캐시 리스(Casey Reas) & 벤 프라이(Ben Fry) 저 Getting Started with
          * Processing에서 옮김.
          */
         
        -let bug; // 객체 선언
        +let bug; // 객체 선언하기
         
         function setup() {
           createCanvas(710, 400);
        -  // 객체 생성
        -=======
        - * @name Objects
        - * @description Create a Jitter class, instantiate an object,
        - * and move it around the screen. Adapted from Getting Started with
        - * Processing by Casey Reas and Ben Fry.
        - */
        -
        -let bug; // Declare object
        -
        -function setup() {
        -  createCanvas(710, 400);
        -  // Create object
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 객체 생성하기
           bug = new Jitter();
         }
         
        @@ -33,11 +19,7 @@ function draw() {
           bug.display();
         }
         
        -<<<<<<< HEAD
         // Jitter 클래스
        -=======
        -// Jitter class
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        index a24e69f203..8a0a96a3f4 100644
        --- a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        +++ b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        @@ -1,30 +1,17 @@
         /*
        -<<<<<<< HEAD
          * @name 복수 객체
          * @description Jitter 클래스를 만들고, 복수의 객체를 인스턴스화하여
          * 화면 안에서 움직여보세요.
          */
         
        -let bug1; // 객체들 선언
        -=======
        - * @name Multiple Objects
        - * @description Create a Jitter class, instantiate multiple objects,
        - * and move it around the screen.
        - */
        -
        -let bug1; // Declare objects
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +let bug1; // 객체들 선언하기
         let bug2;
         let bug3;
         let bug4;
         
         function setup() {
           createCanvas(710, 400);
        -<<<<<<< HEAD
        -  // 객체 생성
        -=======
        -  // Create object
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 객체 생성하기
           bug1 = new Jitter();
           bug2 = new Jitter();
           bug3 = new Jitter();
        @@ -43,11 +30,7 @@ function draw() {
           bug4.display();
         }
         
        -<<<<<<< HEAD
         // Jitter 클래스
        -=======
        -// Jitter class
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Array.js b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        index e9a17765ab..2fac9f60b8 100644
        --- a/src/data/examples/ko/11_Objects/03_Objects_Array.js
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        @@ -1,20 +1,14 @@
         /*
        -<<<<<<< HEAD
          * @name 객체 배열
          * @description Jitter 클래스를 만들고, 객체 배열을 인스턴스화하여
          * 화면 안에서 움직여보세요.
        -=======
        - * @name Array of Objects
        - * @description Create a Jitter class, instantiate an array of objects
        - * and move them around the screen.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
        -let bugs = []; // array of Jitter objects
        +let bugs = []; // Jitter 객체들의 배열
         
         function setup() {
           createCanvas(710, 400);
        -  // Create objects
        +  // 객체들 생성하기
           for (let i = 0; i < 50; i++) {
             bugs.push(new Jitter());
           }
        @@ -28,7 +22,7 @@ function draw() {
           }
         }
         
        -// Jitter class
        +// Jitter 클래스
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        index 1036a1a779..25ffa5e70a 100644
        --- a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 객체 2
          * @description hbarragan 제작 예제에서 옮김. 이미지 위로 마우스를 움직여
          * 기하의 속도와 위치를 바꿔보세요. MRect 클래스가 선들의 군상을 정의합니다.
        -=======
        - * @name Objects 2
        - * @description Ported from example by hbarragan. Move the cursor across the
        - * image to change the speed and positions of the geometry. The class MRect
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          * defines a group of lines.
          */
         
        @@ -39,21 +33,12 @@ function draw() {
         
         class MRect {
           constructor(iw, ixp, ih, iyp, id, it) {
        -<<<<<<< HEAD
             this.w = iw; // 막대기 한 개 너비
             this.xpos = ixp; // rect의 x위치
             this.h = ih; // rect의 높이
             this.ypos = iyp; // rect의 y위치
             this.d = id; // 막대기 간 거리
             this.t = it; // 막대기 개수
        -=======
        -    this.w = iw; // single bar width
        -    this.xpos = ixp; // rect xposition
        -    this.h = ih; // rect height
        -    this.ypos = iyp; // rect yposition
        -    this.d = id; // single bar distance
        -    this.t = it; // number of bars
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         
           move(posX, posY, damping) {
        diff --git a/src/data/examples/ko/11_Objects/04_Inheritance.js b/src/data/examples/ko/11_Objects/04_Inheritance.js
        index 19ba122faf..12b3737c05 100644
        --- a/src/data/examples/ko/11_Objects/04_Inheritance.js
        +++ b/src/data/examples/ko/11_Objects/04_Inheritance.js
        @@ -1,18 +1,9 @@
        -<<<<<<< HEAD
         /* @name 상속
          * @description 다른 클래스에 기초하여 클래스를 정의할 수 있습니다. 
          * 객체 지향 프로그래밍 언어에서, 한 클래스는 다른 클래스의 필드와 메소드를 상속할 수 있습니다.
          * 이처럼 다른 객체로부터 상속받는 객체를 하위 클래스라 하고,
          * 상속하는 객체를 상위 클래스라고 합니다.
          * 하위 클래스는 상위 클래스를 확장합니다.
        -=======
        -/* @name Inheritance
        - * @description A class can be defined using another class as a
        - * foundation. In object-oriented programming terminology, one class can
        - * inherit fields and methods from another. An object that inherits from
        - * another is called a subclass, and the object it inherits from is called
        - * a superclass. A subclass extends the superclass.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let spots, arm;
         
        diff --git a/src/data/examples/ko/11_Objects/05_Composite_Objects.js b/src/data/examples/ko/11_Objects/05_Composite_Objects.js
        new file mode 100644
        index 0000000000..af575305a8
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/05_Composite_Objects.js
        @@ -0,0 +1,98 @@
        +/* @name 합성 객체
        + * @description 한 객체는 여러 개의 다른 객체들을 포함할 수 있습니다.
        + * 합성 객체를 생성하면 모듈화 원칙들을 활용하거나, 또 높은 수준의 추상을 구축하기에 좋습니다.
        + */
        +let er1, er2;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  er1 = new EggRing(width*0.45, height*0.5, 0.1, 120);
        +  er2 = new EggRing(width*0.65, height*0.8, 0.05, 180);
        +}
        +
        +function draw() {
        +  background(0);
        +  er1.transmit();
        +  er2.transmit();
        +}
        +
        +class Egg {
        +  constructor(xpos, ypos, t, s) {
        +    this.x = xpos;
        +    this.y = ypos;
        +    this.tilt = t;
        +    this.scalar = s / 100.0;
        +    this.angle = 0.0;
        +  }
        +
        +  wobble() {
        +    this.tilt = cos(this.angle) / 8;
        +    this.angle += 0.1;
        +  }
        +
        +  display() {
        +    noStroke();
        +    fill(255);
        +    push();
        +    translate(this.x, this.y);
        +    rotate(this.tilt);
        +    scale(this.scalar);
        +    beginShape();
        +    vertex(0, -100);
        +    bezierVertex(25, -100, 40, -65, 40, -40);
        +    bezierVertex(40, -15, 25, 0, 0, 0);
        +    bezierVertex(-25, 0, -40, -15, -40, -40);
        +    bezierVertex(-40, -65, -25, -100, 0, -100);
        +    endShape();
        +    pop();
        +  }
        +}
        +
        +class Ring {
        +  start(xpos, ypos) {
        +    this.x = xpos;
        +    this.y = ypos;
        +    this.on = true;
        +    this.diameter = 1;
        +  }
        +
        +  grow() {
        +    if (this.on == true) {
        +      this.diameter += 0.5;
        +      if (this.diameter > width*2) {
        +        this.diameter = 0.0;
        +      }
        +    }
        +  }
        +
        +  display() {
        +    if (this.on == true) {
        +      noFill();
        +      strokeWeight(4);
        +      stroke(155, 153);
        +      ellipse(this.x, this.y, this.diameter, this.diameter);
        +    }
        +  }
        +}
        +
        +class EggRing {
        +  constructor(x, y, t, sp) {
        +    this.x = x;
        +    this.y = y;
        +    this.t = t;
        +    this.sp = sp;
        +    this.circle = new Ring();
        +    this.ovoid = new Egg(this.x, this.y, this.t, this.sp);
        +    this.circle.start(this.x, this.y - this.sp/2);
        +  }
        +
        +  transmit() {
        +    this.ovoid.wobble();
        +    this.ovoid.display();
        +    this.circle.grow();
        +    this.circle.display();
        +    if (circle.on == false) {
        +      circle.on = true;
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/12_Lights/02_Directional.js b/src/data/examples/ko/12_Lights/02_Directional.js
        index 445cdb67a1..2e09a2c792 100644
        --- a/src/data/examples/ko/12_Lights/02_Directional.js
        +++ b/src/data/examples/ko/12_Lights/02_Directional.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 디렉셔널 라이트
          * @frame 710,400
          * @description 마우스를 움직여 조명의 방향을 바꿔보세요.
        @@ -7,14 +6,6 @@
          * 표면에 직각으로 닿을 때 강한 빛을,
          * 부드러운 각도로 닿았을 때 약한 빛을 보입니다. 
          * 디렉셔널 라이트는 표면에 닿으면 그 빛이 모든 방향으로 흩어집니다.
        -=======
        - * @name Directional
        - * @frame 710,400
        - * @description Move the mouse to change the direction of the light.
        - * Directional light comes from one direction and is stronger when hitting a
        - * surface squarely and weaker if it hits at a a gentle angle. After hitting a
        - * surface, a directional light scatters in all directions.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         const radius = 200;
         
        diff --git a/src/data/examples/ko/12_Lights/05_Mixture.js b/src/data/examples/ko/12_Lights/05_Mixture.js
        index ac176365d6..d01c872f70 100644
        --- a/src/data/examples/ko/12_Lights/05_Mixture.js
        +++ b/src/data/examples/ko/12_Lights/05_Mixture.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 혼합 라이트
          * @frame 710,400 (optional)
          * @description 세 개의 다른 조명과 함께 박스를 보여줍니다.
        -=======
        - * @name Mixture
        - * @frame 710,400 (optional)
        - * @description Display a box with three different kinds of lights.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        @@ -17,7 +11,6 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           // 우측에서 비추는 오렌지색 포인트 라이트
           pointLight(150, 100, 0, 500, 0, 200);
         
        @@ -25,15 +18,6 @@ function draw() {
           directionalLight(0, 102, 255, -1, 0, 0);
         
           // 정면에서 비추는 노랑색 스포트라이트
        -=======
        -  // Orange point light on the right
        -  pointLight(150, 100, 0, 500, 0, 200);
        -
        -  // Blue directional light from the left
        -  directionalLight(0, 102, 255, -1, 0, 0);
        -
        -  // Yellow spotlight from the front
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           pointLight(255, 255, 109, 0, 0, 300);
         
           rotateY(map(mouseX, 0, width, 0, PI));
        diff --git a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        index 4538c6abd8..028d28ef51 100644
        --- a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        +++ b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 비직각 반사
          * @frame 710,400 (optional)
          * @description 이 예제는 processing.org/examples의 "Reflection 1" 예제를 데이비드 블리츠(David Blitz)가 옮긴 것입니다.
        @@ -14,22 +13,6 @@ let base2;
         //let baseLength;
         
         // 움직이는 공에 대한 변수들
        -=======
        - * @name Non Orthogonal Reflection
        - * @frame 710,400 (optional)
        - * @description This is a port by David Blitz of the "Reflection 1" example from processing.org/examples
        - */
        -
        -//Position of left hand side of floor
        -let base1;
        -
        -//Position of right hand side of floor
        -let base2;
        -//Length of floor
        -//let baseLength;
        -
        -// Variables related to moving ball
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let position;
         let velocity;
         let r = 6;
        @@ -43,59 +26,35 @@ function setup() {
           base2 = createVector(width, height);
           //createGround();
         
        -<<<<<<< HEAD
           // 화면 중앙의 상단에서 타원형 시작
           position = createVector(width / 2, 0);
         
           // 초기 임의 속도 계산
        -=======
        -  //start ellipse at middle top of screen
        -  position = createVector(width / 2, 0);
        -
        -  //calculate initial random velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           velocity = p5.Vector.random2D();
           velocity.mult(speed);
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 배경 그리기
        -=======
        -  //draw background
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(0, 12);
           noStroke();
           rect(0, 0, width, height);
         
        -<<<<<<< HEAD
           // base(밑바닥) 그리기
           fill(200);
           quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
         
           // base(밑바닥) 상단의 normal(표준) 계산하기
        -=======
        -  //draw base
        -  fill(200);
        -  quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
        -
        -  //calculate base top normal
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let baseDelta = p5.Vector.sub(base2, base1);
           baseDelta.normalize();
           let normal = createVector(-baseDelta.y, baseDelta.x);
           let intercept = p5.Vector.dot(base1, normal);
         
        -<<<<<<< HEAD
           // ellipse(타원) 그리기
        -=======
        -  //draw ellipse
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noStroke();
           fill(255);
           ellipse(position.x, position.y, r * 2, r * 2);
         
        -<<<<<<< HEAD
           // 타원 움직이기
           position.add(velocity);
         
        @@ -110,22 +69,6 @@ function draw() {
         
             // 반사 벡터 계산
             // 반사 벡터를 방향 벡터에 지정
        -=======
        -  //move ellipse
        -  position.add(velocity);
        -
        -  //normalized incidence vector
        -  incidence = p5.Vector.mult(velocity, -1);
        -  incidence.normalize();
        -
        -  // detect and handle collision with base
        -  if (p5.Vector.dot(normal, position) > intercept) {
        -    //calculate dot product of incident vector and base top
        -    let dot = incidence.dot(normal);
        -
        -    //calculate reflection vector
        -    //assign reflection vector to direction vector
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             velocity.set(
               2 * normal.x * dot - incidence.x,
               2 * normal.y * dot - incidence.y,
        @@ -133,11 +76,7 @@ function draw() {
             );
             velocity.mult(speed);
         
        -<<<<<<< HEAD
        -    // 충돌 지점에서 밑바닥 상단 표준 그리기
        -=======
        -    // draw base top normal at collision point
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +      // 충돌 지점에서 밑바닥 상단 표준 그리기
             stroke(255, 128, 0);
             line(
               position.x,
        @@ -148,40 +87,23 @@ function draw() {
           }
           //}
         
        -<<<<<<< HEAD
           // 경계면 충돌 감지
           // 우측
        -=======
        -  // detect boundary collision
        -  // right
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (position.x > width - r) {
             position.x = width - r;
             velocity.x *= -1;
           }
        -<<<<<<< HEAD
           // 좌측
        -=======
        -  // left
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (position.x < r) {
             position.x = r;
             velocity.x *= -1;
           }
        -<<<<<<< HEAD
           // 상단
        -=======
        -  // top
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (position.y < r) {
             position.y = r;
             velocity.y *= -1;
         
        -<<<<<<< HEAD
             // 밑바닥의 상단 임의화하기
        -=======
        -    //randomize base top
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             base1.y = random(height - 100, height);
             base2.y = random(height - 100, height);
           }
        diff --git a/src/data/examples/ko/13_Motion/02_Linear_Motion.js b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        index 0a2b57a56d..454e13377a 100644
        --- a/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        +++ b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 선형
          * @frame 720,400
          * @description 변수를 바꿔 움직이는 선을 만들어보세요.
          * 선이 화면 상단 밖으로 나가면 변수는 0이 되어
          * 선의 위치를 화면의 하단으로 되돌립니다.
        -=======
        - * @name Linear
        - * @frame 720,400
        - * @description Changing a variable to create a moving line.
        - * When the line moves off the edge of the window,
        - * the variable is set to 0, which places the line back at the bottom of the screen.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let a;
        diff --git a/src/data/examples/ko/13_Motion/03_Bounce.js b/src/data/examples/ko/13_Motion/03_Bounce.js
        index 8e95f8394e..c1a6b9ae7f 100644
        --- a/src/data/examples/ko/13_Motion/03_Bounce.js
        +++ b/src/data/examples/ko/13_Motion/03_Bounce.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 바운스
          * @frame 720,400
          * @description 도형이 화면의 모서리에 닿으면 반대 방향으로 움직입니다.
        @@ -13,32 +12,13 @@ let yspeed = 2.2; // 도형의 속도
         
         let xdirection = 1; // 왼쪽 또는 오른쪽
         let ydirection = 1; // 위 또는 아래
        -=======
        - * @name Bounce
        - * @frame 720,400
        - * @description When the shape hits the edge of the window, it reverses its direction.
        - */
        -
        -let rad = 60; // Width of the shape
        -let xpos, ypos; // Starting position of shape
        -
        -let xspeed = 2.8; // Speed of the shape
        -let yspeed = 2.2; // Speed of the shape
        -
        -let xdirection = 1; // Left or Right
        -let ydirection = 1; // Top to Bottom
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(720, 400);
           noStroke();
           frameRate(30);
           ellipseMode(RADIUS);
        -<<<<<<< HEAD
           // 도형의 시작점 설정
        -=======
        -  // Set the starting position of the shape
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           xpos = width / 2;
           ypos = height / 2;
         }
        @@ -46,21 +26,12 @@ function setup() {
         function draw() {
           background(102);
         
        -<<<<<<< HEAD
           // 도형의 위치 업데이트
           xpos = xpos + xspeed * xdirection;
           ypos = ypos + yspeed * ydirection;
         
           // 도형이 화면 경계를 넘어가는 지 테스트
           // 넘어갈 경우, -1을 곱하여 방향을 반대로 돌린다.
        -=======
        -  // Update the position of the shape
        -  xpos = xpos + xspeed * xdirection;
        -  ypos = ypos + yspeed * ydirection;
        -
        -  // Test to see if the shape exceeds the boundaries of the screen
        -  // If it does, reverse its direction by multiplying by -1
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (xpos > width - rad || xpos < rad) {
             xdirection *= -1;
           }
        @@ -68,10 +39,6 @@ function draw() {
             ydirection *= -1;
           }
         
        -<<<<<<< HEAD
           // 도형 그리기
        -=======
        -  // Draw the shape
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           ellipse(xpos, ypos, rad, rad);
         }
        diff --git a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        index 810801a7e7..108b83b8ba 100644
        --- a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        +++ b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
        - * @name 바운싱 버블
        + * @name 버블 바운스
          * @frame 720,400
          * @description 이 예제는 키스 피터스(Keith Peters)가 제작한 복수-객체 충돌(Multiple-object collision) 예제 코드를 기반으로 합니다.
        -=======
        - * @name Bouncy Bubbles
        - * @frame 720,400
        - * @description  based on code from Keith Peters. Multiple-object collision..
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let numBalls = 13;
        diff --git a/src/data/examples/ko/13_Motion/05_Morph.js b/src/data/examples/ko/13_Motion/05_Morph.js
        index c7d92ed409..6a950d7d97 100644
        --- a/src/data/examples/ko/13_Motion/05_Morph.js
        +++ b/src/data/examples/ko/13_Motion/05_Morph.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 변형(morph)
          * @frame 720,400
          * @description 버텍스를 보간하여 한 모양에서 다른 모양으로 바꾸기
        @@ -16,31 +15,12 @@ let square = [];
         let morph = [];
         
         // 이 불리언 변수는 원형이나 사각형으로 변형할지 여부를 결정합니다.
        -=======
        - * @name Morph
        - * @frame 720,400
        - * @description Changing one shape into another by interpolating vertices from one to another.
        - */
        -
        -// Two ArrayLists to store the vertices for two shapes
        -// This example assumes that each shape will have the same
        -// number of vertices, i.e. the size of each ArrayList will be the same
        -let circle = [];
        -let square = [];
        -
        -// An ArrayList for a third set of vertices, the ones we will be drawing
        -// in the window
        -let morph = [];
        -
        -// This boolean variable will control if we are morphing to a circle or square
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let state = false;
         
         function setup() {
           createCanvas(720, 400);
         
        -<<<<<<< HEAD
        -  // 중심을 가리키는 벡터를 사용하여 원 그리기
        +    // 중심을 가리키는 벡터를 사용하여 원 그리기
           for (let angle = 0; angle < 360; angle += 9) {
             // 주의: 원의 이동 경로와 상응하기 위해, 0에서 시작하지 않습니다.
             let v = p5.Vector.fromAngle(radians(angle - 135));
        @@ -64,33 +44,6 @@ function setup() {
             square.push(createVector(x, 50));
           }
           // 사각형 좌측
        -=======
        -  // Create a circle using vectors pointing from center
        -  for (let angle = 0; angle < 360; angle += 9) {
        -    // Note we are not starting from 0 in order to match the
        -    // path of a circle.
        -    let v = p5.Vector.fromAngle(radians(angle - 135));
        -    v.mult(100);
        -    circle.push(v);
        -    // Let's fill out morph ArrayList with blank PVectors while we are at it
        -    morph.push(createVector());
        -  }
        -
        -  // A square is a bunch of vertices along straight lines
        -  // Top of square
        -  for (let x = -50; x < 50; x += 10) {
        -    square.push(createVector(x, -50));
        -  }
        -  // Right side
        -  for (let y = -50; y < 50; y += 10) {
        -    square.push(createVector(50, y));
        -  }
        -  // Bottom
        -  for (let x = 50; x > -50; x -= 10) {
        -    square.push(createVector(x, 50));
        -  }
        -  // Left side
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let y = 50; y > -50; y -= 10) {
             square.push(createVector(-50, y));
           }
        @@ -99,7 +52,6 @@ function setup() {
         function draw() {
           background(51);
         
        -<<<<<<< HEAD
           // 이 버텍스들이 목표 대상으로부터 얼마나 멀리 있는지 확인
           let totalDistance = 0;
         
        @@ -107,21 +59,11 @@ function draw() {
           for (let i = 0; i < circle.length; i++) {
             let v1;
             // 원형이나 사각형으로 선형 보간합니까?
        -=======
        -  // We will keep how far the vertices are from their target
        -  let totalDistance = 0;
        -
        -  // Look at each vertex
        -  for (let i = 0; i < circle.length; i++) {
        -    let v1;
        -    // Are we lerping to the circle or square?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (state) {
               v1 = circle[i];
             } else {
               v1 = square[i];
             }
        -<<<<<<< HEAD
             // 그려질 버텍스 가져오기
             let v2 = morph[i];
             // 대상을 향해 선형 보간하기
        @@ -131,32 +73,14 @@ function draw() {
           }
         
           // 모든 버텍스들이 가까워지면, 모양 전환
        -=======
        -    // Get the vertex we will draw
        -    let v2 = morph[i];
        -    // Lerp to the target
        -    v2.lerp(v1, 0.1);
        -    // Check how far we are from target
        -    totalDistance += p5.Vector.dist(v1, v2);
        -  }
        -
        -  // If all the vertices are close, switch shape
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (totalDistance < 0.1) {
             state = !state;
           }
         
        -<<<<<<< HEAD
           // 중심을 기준으로 그리기
           translate(width / 2, height / 2);
           strokeWeight(4);
           // 모든 버텍스를 구성하는 다각형 그리기
        -=======
        -  // Draw relative to center
        -  translate(width / 2, height / 2);
        -  strokeWeight(4);
        -  // Draw a polygon that makes up all the vertices
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           beginShape();
           noFill();
           stroke(255);
        diff --git a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        index 010bb6bdcd..0a65c143f6 100644
        --- a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        +++ b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 곡선 위 움직이기
          * @frame 720,400
          * @description 이 예제에서, 원들은 y = x^4 곡선을 따라 움직입니다.
        @@ -17,25 +16,6 @@ let x = 0.0; // 현재 x 좌표
         let y = 0.0; // 현재 y 좌표
         let step = 0.01; // 경로를 따른 각 단계별 움직임 크기
         let pct = 0.0; // 이동 거리 비율 (0.0과 1.0 사이)
        -=======
        - * @name Moving On Curves
        - * @frame 720,400
        - * @description In this example, the circles moves along the curve y = x^4.
        - * Click the mouse to have it move to a new position.
        - */
        -
        -let beginX = 20.0; // Initial x-coordinate
        -let beginY = 10.0; // Initial y-coordinate
        -let endX = 570.0; // Final x-coordinate
        -let endY = 320.0; // Final y-coordinate
        -let distX; // X-axis distance to move
        -let distY; // Y-axis distance to move
        -let exponent = 4; // Determines the curve
        -let x = 0.0; // Current x-coordinate
        -let y = 0.0; // Current y-coordinate
        -let step = 0.01; // Size of each step along the path
        -let pct = 0.0; // Percentage traveled (0.0 to 1.0)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        index d489491af0..a1854cb62d 100644
        --- a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        +++ b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 인스턴스화
          * @description p5 인스턴스를 만들어, 해당 페이지의 모든 변수들이
          * 전역 범위로서 사용되지 않도록 합니다.
        -=======
        - * @name Instantiation
        - * @description Create a p5 instance, which keeps all variables
        - * out of the global scope of your page.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let sketch = function(p) {
           let x = 100;
        @@ -26,11 +20,7 @@ let sketch = function(p) {
         
         let myp5 = new p5(sketch);
         
        -<<<<<<< HEAD
         // "전역 모드(global mode)"와 비교
        -=======
        -// Compare to "global mode"
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         // let x = 100;
         // let y = 100;
         
        diff --git a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        index 633683e679..b5d6647f6e 100644
        --- a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        +++ b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        @@ -1,6 +1,5 @@
         /*
          * @norender
        -<<<<<<< HEAD
          * @name 인스턴스 컨테이너
          * @description 캔버스에 기본 컨테이너를 지정하거나,
          * 두번째 인수로 추가될 수 있는 모든 요소를 지정할 수 있습니다. 
        @@ -8,17 +7,6 @@
          * 컨테이너 DOM 요소를 지정하는 세 가지 다른 방법이 있습니다.
          * p5로 만들어진 모든 DOM 요소(캔버스, 버튼, div 등)는
          * p5()함수 호출시 두 번째 인수로 지정된 DOM 요소에 담기게 됩니다.
        -=======
        - * @name Instance Container
        - * @description Optionally, you can specify a default container for the canvas
        - * and any other elements to append to with a second argument. You can give the
        - * ID of an element in your html, or an html node itself.
        - *
        - * Here are three different options for selecting a container
        - * DOM element. All DOM elements (canvas, buttons, divs, etc) created by p5
        - * will be attached to the DOM element specified as the second argument to the
        - * p5() call.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         <!-- pass in the ID of the container element -->
         <!DOCTYPE html>
        diff --git a/src/data/examples/ko/16_Dom/03_Input_Button.js b/src/data/examples/ko/16_Dom/03_Input_Button.js
        index 70e6330238..76549e0e51 100644
        --- a/src/data/examples/ko/16_Dom/03_Input_Button.js
        +++ b/src/data/examples/ko/16_Dom/03_Input_Button.js
        @@ -1,22 +1,14 @@
         /*
        -<<<<<<< HEAD
          * @name 입력과 버튼
        - * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * @description 로컬 프로젝트에서 이 예제를 실행하려면, 
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
          * 를 추가하면 됩니다.<br><br>
          * 텍스트를 입력하고 버튼을 클릭하면 어떤 효과가 캔버스에 나타나는지 보세요.
        -=======
        - * @name Input and Button
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Input text and click the button to see it affect the the canvas.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let input, button, greeting;
         
         function setup() {
        -  // create canvas
        +  // 캔버스 생성하기
           createCanvas(710, 400);
         
           input = createInput();
        diff --git a/src/data/examples/ko/16_Dom/04_Slider.js b/src/data/examples/ko/16_Dom/04_Slider.js
        index 692ac40668..551a4687c4 100644
        --- a/src/data/examples/ko/16_Dom/04_Slider.js
        +++ b/src/data/examples/ko/16_Dom/04_Slider.js
        @@ -1,27 +1,19 @@
         /*
        -<<<<<<< HEAD
          * @name 슬라이더
        - * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * @description 로컬 프로젝트에서 이 예제를 실행하려면, 
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
          * 를 추가하면 됩니다.<br><br>
          * 슬라이더를 움직여 배경색의 R,G,B값을 조정해보세요.
        -=======
        - * @name Slider
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Move the sliders to control the R, G, B values of the background.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let rSlider, gSlider, bSlider;
         
         function setup() {
        -  // create canvas
        +  // 캔버스 생성하기
           createCanvas(710, 400);
           textSize(15);
           noStroke();
         
        -  // create sliders
        +  // 슬라이더 생성하기
           rSlider = createSlider(0, 255, 100);
           rSlider.position(20, 20);
           gSlider = createSlider(0, 255, 0);
        diff --git a/src/data/examples/ko/16_Dom/07_Modify_DOM.js b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        index 0c272a6ffe..7366f94e56 100644
        --- a/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        +++ b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        @@ -1,19 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name DOM 변경
          * @frame 710,300
          * @description <p>DOM 요소를 만들고 draw()함수가 매번 호출될 때마다
        - * 그 속성들을 변경해보세요. 여러분의 프로젝트에서 이 예제를 실행하려면, 
        + * 그 속성들을 변경해보세요. 로컬 프로젝트에서 이 예제를 실행하려면, 
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
          * 를 추가하면 됩니다.</p>
        -=======
        - * @name Modifying the DOM
        - * @frame 710,300
        - * @description <p>Create DOM elements and modify their properties every time
        - * draw() is called. You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.</p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let dancingWords = [];
         
        @@ -33,30 +24,17 @@ class DanceSpan {
         }
         
         function setup() {
        -<<<<<<< HEAD
           // 이 단락은 윗 단의 주요 코드 블록의 부록으로 작성되었습니다.
           // 아래의 코드들은 요소의 생성과 지정 기능을 각각 구분하고자 합니다.
           // 지정된 요소들은 p5js로 생성될 필요가 없으며,
           // 일반적인 HTML일 수 있습니다.
        -=======
        -  // This paragraph is created aside of the main block of code.
        -  // It's to differentiate the creation of an element from its
        -  // selection. Selected elements don't need to be created by
        -  // p5js, they can be just plain HTML.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           createP(
             'I learn in this Letter, that Don Peter of Aragon, ' +
               ' comes this night to Messina'
           ).addClass('text').hide();
         
        -<<<<<<< HEAD
           // 이 줄은 금방 생성된 '단락'을 받지만,
           // 동시에 HTML 페이지상 'text' 클래스를 가진 다른 요소들을 받아오기도 합니다.
        -=======
        -  // This line grabs the paragraph just created, but it would
        -  // also grab any other elements with class 'text' in the HTML
        -  // page.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           const texts = selectAll('.text');
         
           for (let i = 0; i < texts.length; i++) {
        diff --git a/src/data/examples/ko/16_Dom/08_Video.js b/src/data/examples/ko/16_Dom/08_Video.js
        index bd23443297..87841c4410 100644
        --- a/src/data/examples/ko/16_Dom/08_Video.js
        +++ b/src/data/examples/ko/16_Dom/08_Video.js
        @@ -1,26 +1,15 @@
         /*
        -<<<<<<< HEAD
          * @name 비디오
          * @frame 710,250
          * @description <p>다양한 형식의 비디오를 불러오고 버튼을 눌러 재생과 일시 정지를 전환합니다.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가하면 됩니다.</span></em></p>
        -=======
        - * @name Video
        - * @frame 710,250
        - * @description <p>Load a video with multiple formats and toggle between playing
        - * and paused with a button press.
        - * <p><em><span class="small"> To run this example locally, you will need at least
        - * one video file, and the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let playing = false;
         let fingers;
         let button;
         
         function setup() {
        -<<<<<<< HEAD
           // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
           button = createButton('play');
        @@ -28,15 +17,6 @@ function setup() {
         }
         
         // 현재 상태에 따라 비디오를 재생 또는 일시 정지
        -=======
        -  // specify multiple formats for different browsers
        -  fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        -  button = createButton('play');
        -  button.mousePressed(toggleVid); // attach button listener
        -}
        -
        -// plays or pauses the video depending on current state
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function toggleVid() {
           if (playing) {
             fingers.pause();
        diff --git a/src/data/examples/ko/16_Dom/09_Video_Canvas.js b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        index bcb75b381a..02b9727715 100644
        --- a/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        +++ b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        @@ -1,53 +1,27 @@
         /*
        -<<<<<<< HEAD
          * @name 비디오 캔버스
          * @description <p>비디오를 다양한 형식으로 불러와 캔버스 위에 그릴 수 있도록 합니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Video Canvas
        - * @description <p>Load a video with multiple formats and draw it to the canvas.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let fingers;
         
         function setup() {
           createCanvas(710, 400);
        -<<<<<<< HEAD
           // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
           fingers.hide(); // 기본값으로, 비디오는 별개의 DOM 요소로 나타납니다.
           // 이를 우선 숨긴 뒤, 캔버스에 그릴 수 있도록 해볼까요
        -=======
        -  // specify multiple formats for different browsers
        -  fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        -  fingers.hide(); // by default video shows up in separate dom
        -  // element. hide it and draw it to the canvas
        -  // instead
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
           background(150);
        -<<<<<<< HEAD
           image(fingers, 10, 10); // 캔버스에 비디오 프레임 그리기
        -  filter('GRAY');
        +  filter(GRAY);
           image(fingers, 150, 150); // 캔버스에 두번째 사본 그리기
         }
         
         function mousePressed() {
           fingers.loop(); // 반복 재생 설정 및 비디오 재생
        -=======
        -  image(fingers, 10, 10); // draw the video frame to canvas
        -  filter('GRAY');
        -  image(fingers, 150, 150); // draw a second copy to canvas
        -}
        -
        -function mousePressed() {
        -  fingers.loop(); // set the video to loop and start playing
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
        diff --git a/src/data/examples/ko/16_Dom/10_Video_Pixels.js b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        index 940725da71..10bd28beef 100644
        --- a/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        +++ b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        @@ -1,29 +1,16 @@
         /*
        -<<<<<<< HEAD
          * @name 비디오 픽셀
          * @frame 320,240
          * @description <p>비디오를 불러와 픽셀을 조정하고 캔버스에 그려보세요.
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Video Pixels
        - * @frame 320,240
        - * @description <p>Load a video, manipulate its pixels and draw to canvas.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let fingers;
         
         function setup() {
           createCanvas(320, 240);
        -<<<<<<< HEAD
           // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
        -=======
        -  // specify multiple formats for different browsers
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
           fingers.loop();
           fingers.hide();
        diff --git a/src/data/examples/ko/16_Dom/11_Capture.js b/src/data/examples/ko/16_Dom/11_Capture.js
        index dbe8653722..4c3457e2a3 100644
        --- a/src/data/examples/ko/16_Dom/11_Capture.js
        +++ b/src/data/examples/ko/16_Dom/11_Capture.js
        @@ -1,6 +1,5 @@
         /*
        -<<<<<<< HEAD
        - * @name 실시간 비디오 화면
        + * @name 실시간 비디오
          * @frame 710,240
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        @@ -9,17 +8,6 @@
          * 반전 효과 필터도 적용할 수 있습니다.
          * 실시간 비디오 화면은 기본값으로 캔버스 위에 나타납니다.
          * 아래의 코드 중 capture.hide()의 주석 처리(//)를 해제하면 이 실시간 비디오 화면을 숨길 수 있습니다. 
        -=======
        - * @name Video Capture
        - * @frame 710,240
        - * @description <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p><br><br>
        - * Capture video from the webcam and display
        - * on the canvas as well with invert filter. Note that by
        - * default the capture feed shows up, too. You can hide the
        - * feed by uncommenting the capture.hide() line.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let capture;
         
        diff --git a/src/data/examples/ko/16_Dom/12_Drop.js b/src/data/examples/ko/16_Dom/12_Drop.js
        index d9c522143f..c3541c6d1f 100644
        --- a/src/data/examples/ko/16_Dom/12_Drop.js
        +++ b/src/data/examples/ko/16_Dom/12_Drop.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 드롭 기능
          * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
          * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        @@ -12,20 +11,6 @@ function setup() {
           const c = createCanvas(710, 400);
           background(100);
           // 캔버스에 이미지 파일이 드롭될 때 이벤트 추가
        -=======
        - * @name Drop
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Drag an image file onto the canvas to see it displayed.
        - */
        -
        -function setup() {
        -  // create canvas
        -  const c = createCanvas(710, 400);
        -  background(100);
        -  // Add an event for when a file is dropped onto the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           c.drop(gotFile);
         }
         
        @@ -39,19 +24,11 @@ function draw() {
         }
         
         function gotFile(file) {
        -<<<<<<< HEAD
           // 드롭된 파일이 이미지 파일이라면,
           if (file.type === 'image') {
             // 이미지 DOM 요소를 생성하되, 화면엔 띄우지 않는다.
             const img = createImg(file.data).hide();
             // 이미지를 캔버스에 그린다.
        -=======
        -  // If it's an image file
        -  if (file.type === 'image') {
        -    // Create an image DOM element but don't show it
        -    const img = createImg(file.data).hide();
        -    // Draw the image onto the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             image(img, 0, 0, width, height);
           } else {
             console.log('Not an image file!');
        diff --git a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        index f4751e66e1..aa89265d1d 100644
        --- a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        +++ b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        @@ -1,19 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 연속된 선
          * @description 마우스를 클릭하고 드래그하여 선을 그려보세요.
          */
         function setup() {
           createCanvas(710, 400);
           background(102);ㅌ
        -=======
        - * @name Continous Lines
        - * @description Click and drag the mouse to draw a line.
        - */
        -function setup() {
        -  createCanvas(710, 400);
        -  background(102);
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/17_Drawing/01_Pattern.js b/src/data/examples/ko/17_Drawing/01_Pattern.js
        index e446cf1305..c1db5a64fd 100644
        --- a/src/data/examples/ko/17_Drawing/01_Pattern.js
        +++ b/src/data/examples/ko/17_Drawing/01_Pattern.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
        - * @name 패턴들
        + * @name 패턴
          * @description 캔버스 위로 마우스를 움직여 드로잉할 수 있는 소프트웨어 툴입니다.
          * 이 때, 드로잉은 마우스의 속도에 반응합니다.
        -=======
        - * @name Patterns
        - * @description Move the cursor over the image to draw with a software tool
        - * which responds to the speed of the mouse.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400);
        @@ -15,7 +9,6 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           // variableEllipse()메소드를 호출하고, 여기에
           // 마우스의 현재 및 이전 위치를 담은 매개 변수를 보냅니다.
           variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
        @@ -25,18 +18,6 @@ function draw() {
         // 작성되었습니다. 메소드는 마우스의 속도를 계산하는데,
         // 마우스가 천천히 움직이면 작은 타원을,
         // 마우스가 빨리 움직이면 큰 타원을 그립니다.
        -=======
        -  // Call the variableEllipse() method and send it the
        -  // parameters for the current mouse position
        -  // and the previous mouse position
        -  variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
        -}
        -
        -// The simple method variableEllipse() was created specifically
        -// for this program. It calculates the speed of the mouse
        -// and draws a small ellipse if the mouse is moving slowly
        -// and draws a large ellipse if the mouse is moving quickly
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function variableEllipse(x, y, px, py) {
           let speed = abs(x - px) + abs(y - py);
        diff --git a/src/data/examples/ko/17_Drawing/02_Pulses.js b/src/data/examples/ko/17_Drawing/02_Pulses.js
        index 0e146eb694..3b2e77f82d 100644
        --- a/src/data/examples/ko/17_Drawing/02_Pulses.js
        +++ b/src/data/examples/ko/17_Drawing/02_Pulses.js
        @@ -1,16 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 율동
          * @description 드로잉 스포트웨어는 특정 리듬이나, 그려진 제스쳐로부터 독립된 규칙을 따를 수 있습니다.
          * 이 예제의 경우, 협업 드로잉으로도 볼 수 있습니다.
          * 사용자가 이미지의 일부를 조정하면 소프트웨어가 다른 일부를 조정하는 식입니다.
        -=======
        - * @name Pulses
        - * @description Software drawing instruments can follow a rhythm or abide by
        - * rules independent of drawn gestures. This is a form of collaborative drawing
        - * in which the draftsperson controls some aspects of the image and the software
        - * controls others.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let angle = 0;
         
        @@ -22,11 +14,7 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
        -  // 마우스 버튼이 눌렸을 때만 그리기
        -=======
        -  // Draw only when mouse is pressed
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 마우스가 클릭될 때만 그리기
           if (mouseIsPressed === true) {
             angle += 5;
             let val = cos(radians(angle)) * 12.0;
        diff --git a/src/data/examples/ko/18_Transform/00_Translate.js b/src/data/examples/ko/18_Transform/00_Translate.js
        index 111356764f..69f5a29aa1 100644
        --- a/src/data/examples/ko/18_Transform/00_Translate.js
        +++ b/src/data/examples/ko/18_Transform/00_Translate.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
        - * @name 치환(Translate)
        + * @name 변환(Translate)
          * @description translate() 함수는 객체를 화면 내 어떤 위치로든 이동하게 합니다.
        - * 그 첫 번째 매개 변수는 x축의 오프셋(offset)을,
        - * 두 번째 매개 변수는 y축의 오프셋을 지정합니다.
        - * 이 예제는 이러한 치환들이 축적되는 것을 보여줍니다.
        -=======
        - * @name Translate
        - * @description The translate() function allows objects to be
        - * moved to any location within the window. The first parameter
        - * sets the x-axis offset and the second parameter sets the
        - * y-axis offset. This example shows how transforms accumulate.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        + * 그 첫 번째 매개변수는 x축의 오프셋(offset)을,
        + * 두 번째 매개변수는 y축의 오프셋을 지정합니다.
        + * 이 예제는 이러한 변환들이 축적되는 것을 보여줍니다.
          */
         
         let x = 0;
        @@ -25,40 +17,22 @@ function setup() {
         
         function draw() {
           background(102);
        -<<<<<<< HEAD
           // x값을 증가시켜 움직이게 만들기
           x = x + 0.8;
           // 도형이 캔버스 밖으로 나가면, 위치를 리셋한다.
        -=======
        -  // Animate by increasing our x value
        -  x = x + 0.8;
        -  // If the shape goes off the canvas, reset the position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (x > width + dim) {
             x = -dim;
           }
         
        -<<<<<<< HEAD
           // rect 명령어는 원점을 중심점으로 삼는 도형을 그리지만,
           // translate은 이를 새로운 x와 y 위치로 옮깁니다.
        -=======
        -  // Even though our rect command draws the shape with its
        -  // center at the origin, translate moves it to the new
        -  // x and y position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           translate(x, height / 2 - dim / 2);
           fill(255);
           rect(-dim / 2, -dim / 2, dim, dim);
         
        -<<<<<<< HEAD
        -  // translate(치환)은 축적됩니다. 이 rect가 다른 rect와
        -  // 동일한 x축값 매개 변수를 가졌음에도
        +  // translate(변환)은 축적됩니다. 이 rect가 다른 rect와
        +  // 동일한 x축값 매개변수를 가졌음에도
           // 두 배로 빠르게 움직이는 걸 볼 수 있습니다.
        -=======
        -  // Transforms accumulate. Notice how this rect moves
        -  // twice as fast as the other, but it has the same
        -  // parameter for the x-axis value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           translate(x, dim);
           fill(0);
           rect(-dim / 2, -dim / 2, dim, dim);
        diff --git a/src/data/examples/ko/18_Transform/01_Scale.js b/src/data/examples/ko/18_Transform/01_Scale.js
        index 5c0cc84ad2..93a4ad67fd 100644
        --- a/src/data/examples/ko/18_Transform/01_Scale.js
        +++ b/src/data/examples/ko/18_Transform/01_Scale.js
        @@ -1,20 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 크기 조정(Scale)
          * @description scale()함수의 매개 변수는 10진수 백분율로 표현됩니다.
          * 예를 들어, scale(2.0) 메소드 호출은 도형의 차원을 200 퍼센트 증가시킵니다.
          * 오브젝트의 크기는 항상 원점을 기준으로 조정됩니다. 
        - * 이 예제는 그러한 변형이 축적되는 양상과, 순서에 따라 scale과 translate이
        + * 이 예제는 그러한 변형이 누적되는 양상과, 순서에 따라 scale과 translate이
          * 상호작용하는 것을 보여줍니다.
        -=======
        - * @name Scale
        - * @description Paramenters for the scale() function are values
        - * specified as decimal percentages. For example, the method
        - * call scale(2.0) will increase the dimension of the shape by
        - * 200 percent. Objects always scale from the origin. This example
        - * shows how transforms accumulate and also how scale and translate
        - * interact depending on their order.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let a = 0.0;
        @@ -23,31 +13,31 @@ let s = 0.0;
         function setup() {
           createCanvas(720, 400);
           noStroke();
        -  //Draw all rectangles from their center as opposed to
        -  // the default upper left corner
        +  // 드로잉 시작 기본 위치인 상단 좌측 코너가 아닌,
        +  // 화면 중앙에서 직사각형이 그려지도록 합니다.
           rectMode(CENTER);
         }
         
         function draw() {
           background(102);
         
        -  //Slowly increase 'a' and then animate 's' with
        -  //a smooth cyclical motion by finding the cosine of 'a'
        +  // 'a'를 천천히 증가시킨 다음 'a'의 코사인을 찾아,
        +  // 's'에 부드럽고 주기적인 애니메이션 효과를 줍니다.
           a = a + 0.04;
           s = cos(a) * 2;
         
        -  //Translate our rectangle from the origin to the middle of
        -  //the canvas, then scale it with 's'
        +  // 사각형을 원점에서 캔버스 중간으로 변환(translate)한 다음,
        +  // 's'로 크기를 조정합니다.
           translate(width / 2, height / 2);
           scale(s);
           fill(51);
           rect(0, 0, 50, 50);
         
        -  //Translate and scale are accumulating, so this translate
        -  //moves the second rectangle further right than the first
        -  //and the scale is getting doubled. Note that cosine is
        -  //making 's' both negative and positive, thus it cycles
        -  //from left to right.
        +  // 변환과 크기 조정은 누적됩니다.
        +  // 따라서 변환된 두 번째 사각형은 첫 번째 사각형보다 
        +  // 조금 더 오른쪽으로 이동하게 되고, 그 크기는 두배가 됩니다.
        +  // 한편, 코사인은 's'가 음수와 양수를 오가도록 하는데,
        +  // 이에 따라 사각형이 왼쪽과 오른쪽을 순환하게 됩니다.
           translate(75, 0);
           fill(255);
           scale(s);
        diff --git a/src/data/examples/ko/18_Transform/02_Rotate.js b/src/data/examples/ko/18_Transform/02_Rotate.js
        index bdf1d211a8..d25d8de8f9 100644
        --- a/src/data/examples/ko/18_Transform/02_Rotate.js
        +++ b/src/data/examples/ko/18_Transform/02_Rotate.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 회전(Rotate)
          * @description Z축을 기준으로 사각형 회전시킵니다.
          * 원하는 결과를 얻기 위해, 0부터 PI*2(즉, TWO_PI, 약 6.28)에 해당하는,
        @@ -9,18 +8,6 @@
          * 이 예제에서, 모든 짝수 초마다 jitter(떨림)가 회전에 더해집니다.
          * 홀수 초에는 마지막 jitter값으로 결정된 속도에 따라
          * 시계 방향 또는 반시계 방향으로 회전합니다.
        -=======
        - * @name Rotate
        - * @description Rotating a square around the Z axis.
        - * To get the results you expect, send the rotate function angle
        - * parameters that are values between 0 and PI*2 (TWO_PI which is
        - * roughly 6.28). If you prefer to think about angles as degrees
        - * (0-360), you can use the radians() method to convert your values.
        - * For example: scale(radians(90)) is identical to the statement
        - * scale(PI/2). In this example, every even numbered second a jitter
        - * is added to the rotation. During odd seconds rotation moves CW and
        - * CCW at the speed determined by the last jitter value.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let angle = 0.0;
        @@ -30,20 +17,14 @@ function setup() {
           createCanvas(720, 400);
           noStroke();
           fill(255);
        -<<<<<<< HEAD
           //중심으로부터 사각형을 그리고,
           //사각형이 중심을 기준으로 회전하도록 만들기
        -=======
        -  //Draw the rectangle from the center and it will also be the
        -  //rotate around that center
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rectMode(CENTER);
         }
         
         function draw() {
           background(51);
         
        -<<<<<<< HEAD
           // 짝수 초(0, 2, 4, 6...)동안 회전에
           // jitter(떨림) 더하기
           if (second() % 2 === 0) {
        @@ -56,20 +37,6 @@ function draw() {
           //도형을 캔버스의 중앙으로 이동시키기
           translate(width / 2, height / 2);
           //최종 회전 적용하기
        -=======
        -  // during even-numbered seconds (0, 2, 4, 6...) add jitter to
        -  // the rotation
        -  if (second() % 2 === 0) {
        -    jitter = random(-0.1, 0.1);
        -  }
        -  //increase the angle value using the most recent jitter value
        -  angle = angle + jitter;
        -  //use cosine to get a smooth CW and CCW motion when not jittering
        -  let c = cos(angle);
        -  //move the shape to the center of the canvas
        -  translate(width / 2, height / 2);
        -  //apply the final rotation
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rotate(c);
           rect(0, 0, 180, 180);
         }
        diff --git a/src/data/examples/ko/18_Transform/03_Arm.js b/src/data/examples/ko/18_Transform/03_Arm.js
        index ecf142616d..b62f1dac02 100644
        --- a/src/data/examples/ko/18_Transform/03_Arm.js
        +++ b/src/data/examples/ko/18_Transform/03_Arm.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 팔모양
        - * @description 이 예제는 변환 행렬을 사용하여 팔모양을 만듭니다.
        + * @description 이 예제는 변형 행렬을 사용하여 팔모양을 만듭니다.
          * 각 선분의 각도는 mouseX 및 mouseY 위치로 조정됩니다.
        - * 첫 번째 선분에 적용된 변환은 두 번째 선분에도 적용됩니다.
        + * 첫 번째 선분에 적용된 변형은 두 번째 선분에도 적용됩니다.
          * 두 선분 모두 동일한 push() 및 pop() 행렬 그룹에 속하기 때문입니다.
        -=======
        - * @name Arm
        - * @description This example uses transform matrices to create
        - * an arm. The angle of each segment is controlled with the
        - * mouseX and mouseY position. The transformations applied to
        - * the first segment are also applied to the second segment
        - * because they are inside the same push() and
        - * pop() matrix group.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let x, y;
        @@ -25,17 +15,10 @@ function setup() {
           createCanvas(720, 400);
           strokeWeight(30);
         
        -<<<<<<< HEAD
        -  //반 투명한 선 그리기
        +  // 반투명한 선 그리기
           stroke(255, 160);
         
        -  //팔의 "어깨" 위치를 캔버스 중앙에 위치시키기
        -=======
        -  //Stroke with a semi-transparent white
        -  stroke(255, 160);
        -
        -  //Position the "shoulder" of the arm in the center of the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 팔의 "어깨" 위치를 캔버스 중앙에 위치시키기
           x = width * 0.5;
           y = height * 0.5;
         }
        @@ -43,34 +26,20 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
        -  //마우스 위치에 따라 선분의 각도 바꾸기
        +  // 마우스 위치에 따라 선분의 각도 바꾸기
           angle1 = (mouseX / float(width) - 0.5) * -TWO_PI;
           angle2 = (mouseY / float(height) - 0.5) * PI;
         
        -  // push와 pop을 사용해 변환을 "contain"하기
        +  // push와 pop을 사용해 변형을 담기
           // 사용자 정의 함수를 사용해 선분을 그려도
        -  // 변환 내용이 축적되는 걸 볼 수 있습니다.
        -=======
        -  //Change the angle of the segments according to the mouse positions
        -  angle1 = (mouseX / float(width) - 0.5) * -TWO_PI;
        -  angle2 = (mouseY / float(height) - 0.5) * PI;
        -
        -  //use push and pop to "contain" the transforms. Note that
        -  // even though we draw the segments using a custom function,
        -  // the transforms still accumulate
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  // 변형 내용이 축적되는 걸 볼 수 있습니다.
           push();
           segment(x, y, angle1);
           segment(segLength, 0, angle2);
           pop();
         }
         
        -<<<<<<< HEAD
         // 선분을 그리기 위한 사용자 정의 함수
        -=======
        -//a custom function for drawing segments
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function segment(x, y, a) {
           translate(x, y);
           rotate(a);
        diff --git a/src/data/examples/ko/19_Typography/00_Letters.js b/src/data/examples/ko/19_Typography/00_Letters.js
        index 8143a21135..f9084ab958 100644
        --- a/src/data/examples/ko/19_Typography/00_Letters.js
        +++ b/src/data/examples/ko/19_Typography/00_Letters.js
        @@ -1,40 +1,23 @@
         /*
        -<<<<<<< HEAD
          * @name 글자
          * @description 폰트를 불러와 글자 속성을 설정하면, 화면에 글자를 그릴 수 있습니다.
          * 이 예제에서는 for 반복문과 유니코드 참조 번호를 사용하여,
          * 그리드 속 글자들로 캔버스를 자동으로 채웁니다.
          * 이 중, 모음들만 선택되어 특정 색상이 부여됩니다.
        -=======
        - * @name Letters
        - * @description Letters can be drawn to the screen by loading a font, setting
        - * its characteristics and then drawing the letters. This example uses a for
        - * loop and unicode reference numbers to automatically fill the canvas with
        - * characters in a grid. Vowels are selected and given a specific fill color.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let font,
           fontsize = 32;
         
         function preload() {
        -<<<<<<< HEAD
           // setup()과 draw()를 호출하기에 앞서,
           // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
        -=======
        -  // Ensure the .ttf or .otf font stored in the assets directory
        -  // is loaded before setup() and draw() are called
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           font = loadFont('assets/SourceSansPro-Regular.otf');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 텍스트 속성 설정
        -=======
        -  // Set text characteristics
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           textFont(font);
           textSize(fontsize);
           textAlign(CENTER, CENTER);
        @@ -43,16 +26,11 @@ function setup() {
         function draw() {
           background(160);
         
        -<<<<<<< HEAD
           // 글자 간, 그리고 글자와 좌측 및 상단 간의 margin(여백) 설정
        -=======
        -  // Set the gap between letters and the left and top margin
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let gap = 52;
           let margin = 10;
           translate(margin * 4, margin * 4);
         
        -<<<<<<< HEAD
           // 원하는 글자에서 시작하도록 카운터 설정
           // 이 예제에서는 유니코드 35, 즉 # 기호입니다.
           let counter = 35;
        @@ -64,19 +42,6 @@ function draw() {
               let letter = char(counter);
         
               // 모음과 기타 글자들에 각각 다른 색상 더하기
        -=======
        -  // Set the counter to start at the character you want
        -  // in this case 35, which is the # symbol
        -  let counter = 35;
        -
        -  // Loop as long as there is space on the canvas
        -  for (let y = 0; y < height - gap; y += gap) {
        -    for (let x = 0; x < width - gap; x += gap) {
        -      // Use the counter to retrieve individual letters by their Unicode number
        -      let letter = char(counter);
        -
        -      // Add different color to the vowels and other characters
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               if (
                 letter === 'A' ||
                 letter === 'E' ||
        @@ -89,17 +54,10 @@ function draw() {
                 fill(255);
               }
         
        -<<<<<<< HEAD
               // 화면에 글자 그리기
               text(letter, x, y);
         
               // 카운터 증가시키기
        -=======
        -      // Draw the letter to the screen
        -      text(letter, x, y);
        -
        -      // Increment the counter
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               counter++;
             }
           }
        diff --git a/src/data/examples/ko/19_Typography/01_Words.js b/src/data/examples/ko/19_Typography/01_Words.js
        index 0625692961..725cb82229 100644
        --- a/src/data/examples/ko/19_Typography/01_Words.js
        +++ b/src/data/examples/ko/19_Typography/01_Words.js
        @@ -1,38 +1,22 @@
         /*
        -<<<<<<< HEAD
          * @name 단어
          * @description text()함수는 화면에 단어를 쓸 때 사용됩니다.
          * textAlign()함수로 단어들을 왼쪽, 가운데, 또는 오른쪽 정렬할 수 있으며, 
          * 도형과 마찬가지로, 단어들 역시 fill()로 그 색을 채울 수 있습니다.
        -=======
        - * @name Words
        - * @description The text() function is used for writing words to the screen.
        - * The words can be aligned left, center, or right with the textAlign()
        - * function, and like with shapes, words can be colored with fill().
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let font,
           fontsize = 40;
         
         function preload() {
        -<<<<<<< HEAD
           // setup()과 draw()를 호출하기에 앞서,
           // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
        -=======
        -  // Ensure the .ttf or .otf font stored in the assets directory
        -  // is loaded before setup() and draw() are called
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           font = loadFont('assets/SourceSansPro-Regular.otf');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 텍스트 속성 설정
        -=======
        -  // Set text characteristics
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           textFont(font);
           textSize(fontsize);
           textAlign(CENTER, CENTER);
        @@ -41,7 +25,6 @@ function setup() {
         function draw() {
           background(160);
         
        -<<<<<<< HEAD
           // 텍스트를 오른쪽 정렬하고
           // 캔버스의 좌측 1/3 영역에서 drawWords() 실행하기
           textAlign(RIGHT);
        @@ -54,33 +37,13 @@ function draw() {
         
           // 텍스트를 왼쪽 정렬하고
           // 캔버스의 우측 1/3 영역에서 drawWords() 실행하기
        -=======
        -  // Align the text to the right
        -  // and run drawWords() in the left third of the canvas
        -  textAlign(RIGHT);
        -  drawWords(width * 0.25);
        -
        -  // Align the text in the center
        -  // and run drawWords() in the middle of the canvas
        -  textAlign(CENTER);
        -  drawWords(width * 0.5);
        -
        -  // Align the text to the left
        -  // and run drawWords() in the right third of the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           textAlign(LEFT);
           drawWords(width * 0.75);
         }
         
         function drawWords(x) {
        -<<<<<<< HEAD
           // text() 함수에는 세 개의 매개 변수가 필요합니다:
           // 그려질 텍스트, 가로 위치, 그리고 세로 위치
        -=======
        -  // The text() function needs three parameters:
        -  // the text to draw, the horizontal position,
        -  // and the vertical position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(0);
           text('ichi', x, 80);
         
        diff --git a/src/data/examples/ko/20_3D/00_geometries.js b/src/data/examples/ko/20_3D/00_geometries.js
        index 4964b40fac..59a9b03459 100644
        --- a/src/data/examples/ko/20_3D/00_geometries.js
        +++ b/src/data/examples/ko/20_3D/00_geometries.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 기하
          * @description 현재 p5에는 여섯 개의 3D 기초 조형이 있습니다.
        -=======
        - * @name Geometries
        - * @description There are six 3D primitives in p5 now.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        index f3209e1736..f92bbc0423 100644
        --- a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        +++ b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 3D속 싸인 코싸인
          * @description 싸인, 코싸인, 그리고 push / pop 함수는 3D에도 적용됩니다.
        -=======
        - * @name Sine Cosine in 3D
        - * @description Sine, cosine and push / pop could be applied in 3D as well.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/20_3D/04_textures.js b/src/data/examples/ko/20_3D/04_textures.js
        index 612cf3eafb..54aafba4a6 100644
        --- a/src/data/examples/ko/20_3D/04_textures.js
        +++ b/src/data/examples/ko/20_3D/04_textures.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
        - * @name 텍스쳐
        - * @description 이미지와 비디오가 텍스쳐를 지원합니다.
        + * @name 텍스처
        + * @description 이미지와 비디오가 텍스처를 지원합니다.
          */
         // 비디오 출처: https://vimeo.com/90312869
        -=======
        - * @name Textures
        - * @description Images and videos are supported for texture.
        - */
        -// video source: https://vimeo.com/90312869
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let img;
         let vid;
         let theta = 0;
        @@ -31,11 +24,7 @@ function draw() {
           rotateZ(theta * mouseX * 0.001);
           rotateX(theta * mouseX * 0.001);
           rotateY(theta * mouseX * 0.001);
        -<<<<<<< HEAD
        -  //이미지를 텍스쳐로 전달하기
        -=======
        -  //pass image as texture
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        +  //이미지를 텍스처로 전달하기
           texture(vid);
           sphere(150);
           pop();
        diff --git a/src/data/examples/ko/20_3D/05_ray_casting.js b/src/data/examples/ko/20_3D/05_ray_casting.js
        new file mode 100644
        index 0000000000..ac4fc40e06
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/05_ray_casting.js
        @@ -0,0 +1,100 @@
        +/*
        + * @name 레이 캐스팅
        + * @description 예제 원본: 조나단 왓슨(Jonathan Watson) 제작
        + * <br><br>광선 투사(ray casting) 기능으로 3D 공간 속 마우스의 위치를 감지합니다.
        + */
        +const objects = [];
        +let eyeZ;
        +
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +
        +  eyeZ = height / 2 / tan((30 * PI) / 180); // 카메라가 원점에서 떨어진 기본 위치
        +
        +  objects.push(new IntersectPlane(1, 0, 0, -100, 0, 0)); // 왼쪽 벽
        +  objects.push(new IntersectPlane(1, 0, 0, 100, 0, 0)); // 오른쪽 벽
        +  objects.push(new IntersectPlane(0, 1, 0, 0, -100, 0)); // 바닥
        +  objects.push(new IntersectPlane(0, 1, 0, 0, 100, 0)); // 천장
        +  objects.push(new IntersectPlane(0, 0, 1, 0, 0, 0)); // 뒷면 벽
        +
        +  noStroke();
        +  ambientMaterial(250);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // 조명들
        +  pointLight(255, 255, 255, 0, 0, 400);
        +  ambientLight(244, 122, 158);
        +
        +  // 왼쪽 벽
        +  push();
        +  translate(-100, 0, 200);
        +  rotateY((90 * PI) / 180);
        +  plane(400, 200);
        +  pop();
        +
        +  // 오른쪽 벽
        +  push();
        +  translate(100, 0, 200);
        +  rotateY((90 * PI) / 180);
        +  plane(400, 200);
        +  pop();
        +
        +  // 바닥
        +  push();
        +  translate(0, 100, 200);
        +  rotateX((90 * PI) / 180);
        +  plane(200, 400);
        +  pop();
        +
        +  // 천장
        +  push();
        +  translate(0, -100, 200);
        +  rotateX((90 * PI) / 180);
        +  plane(200, 400);
        +  pop();
        +
        +  plane(200, 200); // 뒷면 벽
        +
        +  const x = mouseX - width / 2;
        +  const y = mouseY - height / 2;
        +
        +  const Q = createVector(0, 0, eyeZ); // 광선 위의 점과 카메라의 기본 위치
        +  const v = createVector(x, y, -eyeZ); // 광선의 방향 벡터
        +
        +  let intersect; // 광선과 벽면의 교차점
        +  let closestLambda = eyeZ * 10; // 거리 그리기
        +
        +  for (let x = 0; x < objects.length; x += 1) {
        +    let object = objects[x];
        +    let lambda = object.getLambda(Q, v); // 광선과 객체 간 교차점의  람다값
        +
        +    if (lambda < closestLambda && lambda > 0) {
        +      // 광선과 객체의 교차점 위치 찾기
        +      intersect = p5.Vector.add(Q, p5.Vector.mult(v, lambda));
        +      closestLambda = lambda;
        +    }
        +  }
        +
        +  // 커서
        +  push();
        +  translate(intersect);
        +  fill(237, 34, 93);
        +  sphere(10);
        +  pop();
        +}
        +
        +// 무한대로 확장하는 벽면 생성을 위한 클래스
        +class IntersectPlane {
        +  constructor(n1, n2, n3, p1, p2, p3) {
        +    this.normal = createVector(n1, n2, n3); // 면의 기본 벡터
        +    this.point = createVector(p1, p2, p3); // 면 위의 점
        +    this.d = this.point.dot(this.normal);
        +  }
        +
        +  getLambda(Q, v) {
        +    return (-this.d - this.normal.dot(Q)) / this.normal.dot(v);
        +  }
        +}
        diff --git a/src/data/examples/ko/20_3D/07_orbit_control.js b/src/data/examples/ko/20_3D/07_orbit_control.js
        index 0d96e195ed..7c45043100 100644
        --- a/src/data/examples/ko/20_3D/07_orbit_control.js
        +++ b/src/data/examples/ko/20_3D/07_orbit_control.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 궤도 제어
          * @description 궤도 제어(Orbit Control)를 사용해 월드를 드래그하거나 움직일 수 있습니다.
        -=======
        - * @name Orbit Control
        - * @description Orbit control allows you to drag and move around the world.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        @@ -15,11 +10,7 @@ function draw() {
           background(250);
           let radius = width * 1.5;
         
        -<<<<<<< HEAD
           //월드를 움직이도록 드래그
        -=======
        -  //drag to move the world.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           orbitControl();
         
           normalMaterial();
        diff --git a/src/data/examples/ko/20_3D/08_basic_shader.js b/src/data/examples/ko/20_3D/08_basic_shader.js
        new file mode 100644
        index 0000000000..f335a266f8
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/08_basic_shader.js
        @@ -0,0 +1,27 @@
        +/*
        + * @name 셰이더 기초
        + * @description p5.js에 셰이더를 불러오는 방법을 설명하는 기본 예제입니다. 
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        +// 이 변수는 셰이더 객체를 담습니다.
        +let theShader;
        +
        +function preload(){
        +  // 셰이더 불러오기
        +  theShader = loadShader('assets/basic.vert', 'assets/basic.frag');
        +}
        +
        +function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +  createCanvas(710, 400, WEBGL);
        +  noStroke();
        +}
        +
        +function draw() {
        +  // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +  shader(theShader);
        +
        +  // rect()함수로 화면에 기하 추가하기
        +  rect(0,0,width, height);
        +}
        diff --git a/src/data/examples/ko/20_3D/09_shader_as_a_texture.js b/src/data/examples/ko/20_3D/09_shader_as_a_texture.js
        new file mode 100644
        index 0000000000..3e12f552c7
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/09_shader_as_a_texture.js
        @@ -0,0 +1,68 @@
        +/*
        + * @name 셰이더로 텍스처 만들기
        + * @description 셰이더는 2D/3D 도형에 텍스처로서 적용될 수 있습니다.
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        + // 이 변수는 createGraphics 레이어를 담습니다.
        + let shaderTexture;
        +
        + let theta = 0;
        +
        + let x;
        + let y;
        + let outsideRadius = 200;
        + let insideRadius = 100;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/texture.vert','assets/texture.frag');
        + }
        +
        + function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        +
        +   // createGraphics 레이어 초기화하기
        +   shaderTexture = createGraphics(710, 400, WEBGL);
        +
        +   // createGraphics 레이어의 테두리 없애기
        +   shaderTexture.noStroke();
        +
        +    x = -50;
        +    y = 0;
        + }
        +
        + function draw() {
        +
        +   // theShader를 활성화 셰이더로 설정하는 대신, createGraphics 레이어로 보냅니다.
        +   shaderTexture.shader(theShader);
        +
        +   // setUniform()를 사용하여 유니폼을 theShader로 보냅니다.
        +   theShader.setUniform("resolution", [width, height]);
        +   theShader.setUniform("time", millis() / 1000.0);
        +   theShader.setUniform("mouse", [mouseX, map(mouseY, 0, height, height, 0)]);
        +
        +   // shaderTexture 레이어 위 기하 형상의 렌더링을 위한 설정
        +   shaderTexture.rect(0,0,width,height);
        +
        +   background(255);
        +
        +   // 셰이더를 텍스쳐로서 설정하기
        +   texture(shaderTexture);
        +
        +   translate(-150, 0, 0);
        +   push();
        +   rotateZ(theta * mouseX * 0.0001);
        +   rotateX(theta * mouseX * 0.0001);
        +   rotateY(theta * mouseX * 0.0001);
        +   theta += 0.05;
        +   sphere(125);
        +   pop();
        +
        +   // 5번째 매개변수를 3D 상의 부드러운 모서리 처리를 위한 값으로 보내기
        +   ellipse(260,0,200,200,100);
        + }
        diff --git a/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js b/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
        new file mode 100644
        index 0000000000..3b274aef49
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
        @@ -0,0 +1,34 @@
        +/*
        + * @name 셰이더 유니폼
        + * @description 유니폼(Uniform)을 통해 p5에서 셰이더로 정보를 전송합니다.
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/uniforms.vert', 'assets/uniforms.frag');
        + }
        +
        + function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        + }
        +
        + function draw() {
        +   // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +   shader(theShader);
        +
        +   // 마우스 + 데이터 수정 시간을 보내기에 앞서,
        +   // 해상도, 마우스, 시간을 셰이더에 보냅니다.
        +   // 이렇게 하면 셰이더에서 사용하기가 더 쉬워집니다.
        +   theShader.setUniform('resolution', [width, height]);
        +   theShader.setUniform('mouse', map(mouseX, 0, width, 0, 7));
        +   theShader.setUniform('time', frameCount * 0.01);
        +
        +  // rect()함수로 화면에 기하 형상 추가하기
        +   rect(0,0,width, height);
        + }
        diff --git a/src/data/examples/ko/20_3D/11_shader_using_webcam.js b/src/data/examples/ko/20_3D/11_shader_using_webcam.js
        new file mode 100644
        index 0000000000..0763b93fac
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/11_shader_using_webcam.js
        @@ -0,0 +1,37 @@
        +/*
        + * @name 웹캠을 사용한 셰이더
        + * @description 웹캠을 텍스처로서 셰이더에 보낼 수 있습니다. 
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        + // 이 변수는 웹캠 비디오를 담습니다.
        + let cam;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/webcam.vert', 'assets/webcam.frag');
        + }
        +
        + function setup() {
        +  // 셰이더 작동을 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        +
        +   cam = createCapture(VIDEO);
        +   cam.size(710, 400);
        +
        +   cam.hide();
        + }
        +
        + function draw() {
        +   // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +   shader(theShader);
        +
        +   // cam을 텍스처로 보내기
        +   theShader.setUniform('tex0', cam);
        +
        +  // rect()함수로 화면에 기하 추가하기
        +   rect(0,0,width,height);
        + }
        diff --git a/src/data/examples/ko/21_Input/00_Clock.js b/src/data/examples/ko/21_Input/00_Clock.js
        index 3927cd759f..7d9b53c902 100644
        --- a/src/data/examples/ko/21_Input/00_Clock.js
        +++ b/src/data/examples/ko/21_Input/00_Clock.js
        @@ -1,15 +1,8 @@
         /*
        -<<<<<<< HEAD
          * @name 시계
          * @description second(), minute(), 그리고 hour()함수를 사용하여
          * 현재 시간을 읽어올 수 있습니다.
          * 이 예제에서는 sin()과 cos()값이 시침, 분침, 초침의 위치를 정합니다.
        -=======
        - * @name Clock
        - * @description The current time can be read with the second(),
        - * minute(), and hour() functions. In this example, sin() and
        - * cos() values are used to set the position of the hands.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let cx, cy;
         let secondsRadius;
        @@ -34,33 +27,20 @@ function setup() {
         function draw() {
           background(230);
         
        -<<<<<<< HEAD
           // 시계 배경 그리기
        -=======
        -  // Draw the clock background
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noStroke();
           fill(244, 122, 158);
           ellipse(cx, cy, clockDiameter + 25, clockDiameter + 25);
           fill(237, 34, 93);
           ellipse(cx, cy, clockDiameter, clockDiameter);
         
        -<<<<<<< HEAD
           // sin()과 cos()의 각도는 3시 정각에서 시작;
           // HALF_PI를 뺄셈하여 상단에서부터 시작하도록 설정
        -=======
        -  // Angles for sin() and cos() start at 3 o'clock;
        -  // subtract HALF_PI to make them start at the top
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
           let m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI;
           let h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI;
         
        -<<<<<<< HEAD
           // 시계침들 그리기
        -=======
        -  // Draw the hands of the clock
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(255);
           strokeWeight(1);
           line(cx, cy, cx + cos(s) * secondsRadius, cy + sin(s) * secondsRadius);
        @@ -69,11 +49,7 @@ function draw() {
           strokeWeight(4);
           line(cx, cy, cx + cos(h) * hoursRadius, cy + sin(h) * hoursRadius);
         
        -<<<<<<< HEAD
           // 분침 그리기
        -=======
        -  // Draw the minute ticks
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           strokeWeight(2);
           beginShape(POINTS);
           for (let a = 0; a < 360; a += 6) {
        diff --git a/src/data/examples/ko/21_Input/01_Constrain.js b/src/data/examples/ko/21_Input/01_Constrain.js
        index 6180900a2c..5aff15a043 100644
        --- a/src/data/examples/ko/21_Input/01_Constrain.js
        +++ b/src/data/examples/ko/21_Input/01_Constrain.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 제한
          * @description 화면 위로 마우스를 움직이면 동그라미가 움직이지만,
          * 박스 안에서만 움직이도록 제한되어 있습니다.
        -=======
        - * @name Constrain
        - * @description Move the mouse across the screen to move
        - * the circle. The program constrains the circle to its box.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let mx = 1;
         let my = 1;
        diff --git a/src/data/examples/ko/21_Input/02_Easing.js b/src/data/examples/ko/21_Input/02_Easing.js
        index f60051d2e7..d84bae3c2a 100644
        --- a/src/data/examples/ko/21_Input/02_Easing.js
        +++ b/src/data/examples/ko/21_Input/02_Easing.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 이징(Easing)
          * @description 화면 위로 마우스 커서를 움직이면 기호가 따라옵니다.
          * 애니메이션의 매 프레임 사이에, 프로그램은 기호와 마우스 커서 간의 거리를 계산합니다.
          * 만약 그 거리가 1픽셀보다 크다면, 기호는 현재 위치로부터 커서의 위치를 향해 
          * 일정 거리(0.05)를 이동합니다.
        -=======
        - * @name Easing
        - * @description Move the mouse across the screen and the symbol
        - * will follow. Between drawing each frame of the animation, the
        - * program calculates the difference between the position of the
        - * symbol and the cursor. If the distance is larger than 1 pixel,
        - * the symbol moves part of the distance (0.05) from its current
        - * position toward the cursor.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let x = 1;
         let y = 1;
        diff --git a/src/data/examples/ko/21_Input/03_Keyboard.js b/src/data/examples/ko/21_Input/03_Keyboard.js
        index 845452e025..643e11c539 100644
        --- a/src/data/examples/ko/21_Input/03_Keyboard.js
        +++ b/src/data/examples/ko/21_Input/03_Keyboard.js
        @@ -1,17 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 키보드
          * @description 이미지를 클릭하여 포커스를 주고
          * 키보드 입력을 통해 화면에 모양을 만듭니다.
          * 각 자판은 고유의 식별 번호를 갖습니다. 
          * 이 번호들은 도형의 화면 상 위치를 정합니다.
        -=======
        - * @name Keyboard
        - * @description Click on the image to give it focus and
        - * press the letter keys to create forms in time and space.
        - * Each key has a unique identifying number. These numbers
        - * can be used to position shapes in space.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let rectWidth;
         
        @@ -23,11 +15,7 @@ function setup() {
         }
         
         function draw() {
        -<<<<<<< HEAD
           // draw()를 여기에 작성하여 키보드 입력을 기다리는 동안 반복되게 합니다.
        -=======
        -  // keep draw() here to continue looping while waiting for keys
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function keyPressed() {
        @@ -36,17 +24,10 @@ function keyPressed() {
             keyIndex = key.charCodeAt(0) - 'a'.charCodeAt(0);
           }
           if (keyIndex === -1) {
        -<<<<<<< HEAD
             // 글자 자판이 아닐 경우, 화면을 비웁니다.
             background(230);
           } else {
             // 글자 자판일 경우, 사각면을 채웁니다.
        -=======
        -    // If it's not a letter key, clear the screen
        -    background(230);
        -  } else {
        -    // It's a letter key, fill a rectangle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             randFill_r = Math.floor(Math.random() * 255 + 1);
             randFill_g = Math.floor(Math.random() * 255 + 1);
             randFill_b = Math.floor(Math.random() * 255 + 1);
        diff --git a/src/data/examples/ko/21_Input/04_Mouse1D.js b/src/data/examples/ko/21_Input/04_Mouse1D.js
        index df39baab10..0ca0d20e8e 100644
        --- a/src/data/examples/ko/21_Input/04_Mouse1D.js
        +++ b/src/data/examples/ko/21_Input/04_Mouse1D.js
        @@ -1,14 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 1D 마우스
          * @description 마우스를 좌우로 움직여 균형점을 이동해보세요. 
          * mouseX 변수로 사각형의 크기와 색상 모두를 조정할 수 있습니다.
        -=======
        - * @name Mouse 1D
        - * @description Move the mouse left and right to
        - * shift the balance. The "mouseX" variable is used
        - * to control both the size and color of the rectangles.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/05_Mouse2D.js b/src/data/examples/ko/21_Input/05_Mouse2D.js
        index 13cf107ce9..72f1513be4 100644
        --- a/src/data/examples/ko/21_Input/05_Mouse2D.js
        +++ b/src/data/examples/ko/21_Input/05_Mouse2D.js
        @@ -1,12 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 2D 마우스
          * @description 마우스를 움직이면 각 상자의 위치와 크기가 바뀝니다.
        -=======
        - * @name Mouse 2D
        - * @description Moving the mouse changes the position and
        - * size of each box.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/06_MouseIsPressed.js b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        index 404d03e895..b29e306fec 100644
        --- a/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        +++ b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        @@ -1,13 +1,7 @@
         /*
        -<<<<<<< HEAD
          * @name 마우스 버튼
          * @description 마우스를 움직여 도형의 위치를 바꿔보세요.
          * 마우스 버튼을 눌러 색을 반전시킬 수 있습니다.
        -=======
        - * @name Mouse Press
        - * @description Move the mouse to position the shape.
        - * Press the mouse button to invert the color.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/07_Mouse_Functions.js b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        index d90338ee83..659b8e8e27 100644
        --- a/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        +++ b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
        - * @name 마우스 기능
        + * @name 마우스 함수
          * @description 상자를 클릭한 뒤 화면 위에서 드래그 해보세요.
        -=======
        - * @name Mouse Functions
        - * @description Click on the box and drag it across the screen.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let bx;
         let by;
        @@ -26,11 +21,7 @@ function setup() {
         function draw() {
           background(237, 34, 93);
         
        -<<<<<<< HEAD
           // 상자 위에 커서가 있는지를 테스트
        -=======
        -  // Test if the cursor is over the box
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (
             mouseX > bx - boxSize &&
             mouseX < bx + boxSize &&
        @@ -48,11 +39,7 @@ function draw() {
             overBox = false;
           }
         
        -<<<<<<< HEAD
           // 상자 그리기
        -=======
        -  // Draw the box
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rect(bx, by, boxSize, boxSize);
         }
         
        diff --git a/src/data/examples/ko/21_Input/08_Mouse_Signals.js b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        index d2d4cbc313..694d9e8aae 100644
        --- a/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        +++ b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        @@ -1,18 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 마우스 신호
          * @description 마우스를 움직이고 클릭하여 신호를 만들어보세요.
          * 상단의 행은 "mouseX", 가운데 행은 "mouseY",
          * 하단의 행은 "mouseIsPressed"에 대한 신호입니다.
           */
        -=======
        - * @name Mouse Signals
        - * @description Move and click the mouse to generate signals.
        - * The top row is the signal from "mouseX", the middle row is
        - * the signal from "mouseY", and the bottom row is the signal
        - * from "mouseIsPressed".
        - */
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let xvals = [];
         let yvals = [];
         let bvals = [];
        @@ -30,11 +21,7 @@ function draw() {
             yvals[i - 1] = yvals[i];
             bvals[i - 1] = bvals[i];
           }
        -<<<<<<< HEAD
           // 배열의 마지막에 새로운 값들 더하기
        -=======
        -  // Add the new values to the end of the array
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           xvals[width - 1] = mouseX;
           yvals[width - 1] = mouseY;
         
        diff --git a/src/data/examples/ko/21_Input/09_Storing_Input.js b/src/data/examples/ko/21_Input/09_Storing_Input.js
        index b6391e2e4d..ea88476c2f 100644
        --- a/src/data/examples/ko/21_Input/09_Storing_Input.js
        +++ b/src/data/examples/ko/21_Input/09_Storing_Input.js
        @@ -1,19 +1,9 @@
         /*
        -<<<<<<< HEAD
          * @name 입력값 저장
          * @description 화면 위로 마우스를 움직여 원들의 위치를 바꿔보세요.
          * 마우스의 위치값들은 배열에 기록되고 매 프레임마다 재생됩니다.
          * 각 프레임이 재생되는 사이, 가장 새로운 값이 배열의 마지막에 더해지고
          * 가장 오래된 값은 삭제됩니다.
        -=======
        - * @name Storing Input
        - * @description Move the mouse across the screen to
        - * change the position of the circles. The positions
        - * of the mouse are recorded into an array and played
        - * back every frame. Between each frame, the newest
        - * value are added to the end of each array and the
        - * oldest value is deleted.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let num = 60;
         let mx = [];
        @@ -32,23 +22,14 @@ function setup() {
         function draw() {
           background(237, 34, 93);
         
        -<<<<<<< HEAD
           // 각 프레임마다 다른 입력값을 이용해 배열을 순환
           // 이처럼 모듈로(%)를 사용하면 모든 값들을 이동시키는 것보다 빠릅니다.
        -=======
        -  // Cycle through the array, using a different entry on each frame.
        -  // Using modulo (%) like this is faster than moving all the values over.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let which = frameCount % num;
           mx[which] = mouseX;
           my[which] = mouseY;
         
           for (let i = 0; i < num; i++) {
        -<<<<<<< HEAD
             // which+1은 가장 작은 값 (동시에, 배열에서 가장 오래된 값)
        -=======
        -    // which+1 is the smallest (the oldest in the array)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             let index = (which + 1 + i) % num;
             ellipse(mx[index], my[index], i, i);
           }
        diff --git a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        index d533dee8c0..251a3b0c8a 100644
        --- a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        +++ b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 저장된 JSON 불러오기
          * @description Bubble 클래스를 만들고, JSON 파일의 데이터를 사용해 버블 여러 개를 인스턴스화합니다.
          * 그리고, 그 결과물을 화면에 띄웁니다.
        @@ -9,17 +8,6 @@
          */
         
         // Bubble 클래스
        -=======
        - * @name Load Saved JSON
        - * @description Create a Bubble class, instantiate multiple bubbles using data from
        - * a JSON file, and display results on the screen.
        - *  Because the web browsers differ in where they save files, we do not make use of
        - * saveJSON, unlike the Processing example.<br><br>
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON Example</a> for Processing.
        - */
        -
        -// Bubble class
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Bubble {
           constructor(x, y, diameter, name) {
             this.x = x;
        @@ -31,21 +19,13 @@ class Bubble {
             this.over = false;
           }
         
        -<<<<<<< HEAD
           // 마우스가 버블 위에 있는지 확인
        -=======
        -  // Check if mouse is over the bubble
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rollover(px, py) {
             let d = dist(px, py, this.x, this.y);
             this.over = d < this.radius;
           }
         
        -<<<<<<< HEAD
           // 버블을 화면에 보이기
        -=======
        -  // Display the Bubble
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           display() {
             stroke(0);
             strokeWeight(0.8);
        @@ -59,22 +39,14 @@ class Bubble {
           }
         }
         
        -<<<<<<< HEAD
         let data = {}; // loadJSON 호출의 결과물을 담는 전역 객체
         let bubbles = []; // 모든 버블 객체를 담는 전역 배열
         
         // 비동기 데이터 로딩을 preload에 담아 setup이 실행되기 전 완료시킴
        -=======
        -let data = {}; // Global object to hold results from the loadJSON call
        -let bubbles = []; // Global array to hold all bubble objects
        -
        -// Put any asynchronous data loading in preload to complete before "setup" is run
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function preload() {
           data = loadJSON('assets/bubbles.json');
         }
         
        -<<<<<<< HEAD
         // 저장된 Bubble 데이터를 Bubble 객체로 전환
         function loadData() {
           let bubbleData = data['bubbles'];
        @@ -84,17 +56,6 @@ function loadData() {
             // position 객체 받아오기
             let position = bubble['position'];
             // 위치로부터 x,y 받아오기
        -=======
        -// Convert saved Bubble data into Bubble Objects
        -function loadData() {
        -  let bubbleData = data['bubbles'];
        -  for (let i = 0; i < bubbleData.length; i++) {
        -    // Get each object in the array
        -    let bubble = bubbleData[i];
        -    // Get a position object
        -    let position = bubble['position'];
        -    // Get x,y from position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             let x = position['x'];
             let y = position['y'];
         
        @@ -102,16 +63,11 @@ function loadData() {
             let diameter = bubble['diameter'];
             let label = bubble['label'];
         
        -<<<<<<< HEAD
             // 배열에 객체 담기
        -=======
        -    // Put object in array
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             bubbles.push(new Bubble(x, y, diameter, label));
           }
         }
         
        -<<<<<<< HEAD
         // 마우스가 클릭될 때마다 새로운 Bubble 만들기
         function mousePressed() {
           // Bubble에 지름과 레이블 더하기
        @@ -124,20 +80,6 @@ function mousePressed() {
           // 버블이 너무 많을 경우 개수 제거하기
           if (bubbles.length > 10) {
             bubbles.shift(); // 배열의 첫 번째 항목 제거하기
        -=======
        -// Create a new Bubble each time the mouse is clicked.
        -function mousePressed() {
        -  // Add diameter and label to bubble
        -  let diameter = random(40, 80);
        -  let label = 'New Label';
        -
        -  // Append the new JSON bubble object to the array
        -  bubbles.push(new Bubble(mouseX, mouseY, diameter, label));
        -
        -  // Prune Bubble Count if there are too many
        -  if (bubbles.length > 10) {
        -    bubbles.shift(); // remove first item from array
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         }
         
        @@ -149,21 +91,13 @@ function setup() {
         function draw() {
           background(255);
         
        -<<<<<<< HEAD
           // 모든 버블들 화면에 보이기
        -=======
        -  // Display all bubbles
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < bubbles.length; i++) {
             bubbles[i].display();
             bubbles[i].rollover(mouseX, mouseY);
           }
         
        -<<<<<<< HEAD
           // 하단에서의 레이블 방향들
        -=======
        -  // Label directions at bottom
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           textAlign(LEFT);
           fill(0);
           text('Click to add bubbles.', 10, height - 10);
        diff --git a/src/data/examples/ko/33_Sound/01_Preload_Sound.js b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        index efc2ad8790..38120ffaaa 100644
        --- a/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        +++ b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 사운드 파일 미리 불러오기
          * @description preload()에서 loadSound()를 호출하여,
          * setup()이 호출되기 전에 미리 사운드 파일을 불러오도록 합니다.
        @@ -9,17 +8,6 @@
          * <br><br><p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Preload SoundFile
        - * @description Call loadSound() during preload() to ensure that the
        - * sound is completely loaded before setup() is called. It's best to always
        - * call loadSound() in preload(), otherwise sounds won't necessarily be loaded
        - * by the time you want to play them in your sketch.
        - *
        - * <br><br><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let song;
        @@ -30,24 +18,15 @@ function preload() {
         
         function setup() {
           createCanvas(710, 200);
        -<<<<<<< HEAD
           song.loop(); // 이제 노래 파일이 setup()에서 재생될 준비가 되었습니다.
                        //preload에서 이미 한 차례 불러왔기 때문입니다.
        -=======
        -  song.loop(); // song is ready to play during setup() because it was loaded during preload
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           background(0, 255, 0);
         }
         
         function mousePressed() {
           if (song.isPlaying()) {
        -<<<<<<< HEAD
             // .isPlaying()은 불리언 값을 반환합니다.
             song.pause(); // .play()는 .pause() 지점에서 다시 시작합니다.
        -=======
        -    // .isPlaying() returns a boolean
        -    song.pause(); // .play() will resume from .pause() position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             background(255, 0, 0);
           } else {
             song.play();
        diff --git a/src/data/examples/ko/33_Sound/02_soundFormats.js b/src/data/examples/ko/33_Sound/02_soundFormats.js
        index 324520f488..0cf8a92cdc 100644
        --- a/src/data/examples/ko/33_Sound/02_soundFormats.js
        +++ b/src/data/examples/ko/33_Sound/02_soundFormats.js
        @@ -1,6 +1,5 @@
         /**
        -<<<<<<< HEAD
        - *  @name 사운드 확장자
        + *  @name 사운드 파일 형식
          *  @description <p>특허 문제로 인해, 모든 웹 브라우저가 지원하는
          *  단일의 사운드 파일 형식은 존재하지 않습니다. 
          *  예를 들어, 
        @@ -28,70 +27,24 @@ function preload() {
         
           // 만약 mp3를 이 브라우저가 지원하지 않는다면,
           // loadSound는 스케치에 포함된 형식인 ogg 파일을 불러옵니다.
        -=======
        - *  @name soundFormats
        - *  @description <p>Technically, due to patent issues, there is no single
        - *  sound format that is supported by all web browsers. While
        - *  <a href="http://caniuse.com/#feat=mp3">mp3 is supported</a> across the
        - *  latest versions of major browsers on OS X and Windows, for example,
        - *  it may not be available on some less mainstream operating systems and
        - *  browsers.</p>
        - *
        - *  <p>To ensure full compatibility, you can include the same sound file
        - *  in multiple formats, e.g. 'sound.mp3' and 'sound.ogg'. (Ogg is an
        - *  open source alternative to mp3.) You can convert audio files
        - *  into web friendly formats for free online at <a href="
        - *  http://media.io/">media.io</a></p>.
        - *
        - *  <p>The soundFormats() method tells loadSound which formats
        - *  we have included with our sketch. Then, loadSound will
        - *  attempt to load the first format that is supported by the
        - *  client's web browser.</p>
        - *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        -let song;
        -
        -function preload() {
        -  // we have included both an .ogg file and an .mp3 file
        -  soundFormats('ogg', 'mp3');
        -
        -  // if mp3 is not supported by this browser,
        -  // loadSound will load the ogg file
        -  // we have included with our sketch
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
         }
         
         function setup() {
           createCanvas(710, 200);
         
        -<<<<<<< HEAD
           // preload()중에 사운드 파일을 미리 불러와, setup()에서 재생할 수 있도록 준비
        -=======
        -  // song loaded during preload(), ready to play in setup()
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           song.play();
           background(0, 255, 0);
         }
         
         function mousePressed() {
           if (song.isPlaying()) {
        -<<<<<<< HEAD
             // .isPlaying()은 불리언 값을 반환합니다.
             song.pause();
             background(255, 0, 0);
           } else {
             song.play(); // playback은 pause(일시정지) 지점에서 다시 재생합니다.
        -=======
        -    // .isPlaying() returns a boolean
        -    song.pause();
        -    background(255, 0, 0);
        -  } else {
        -    song.play(); // playback will resume from the pause position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             background(0, 255, 0);
           }
         }
        diff --git a/src/data/examples/ko/33_Sound/03_Play_Mode.js b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        index 9293f3b5f0..accdf51bc2 100644
        --- a/src/data/examples/ko/33_Sound/03_Play_Mode.js
        +++ b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 재생 모드
          * @description
          * <p>'sustain' 모드에서는 사운드가 겹쳐서 재생됩니다.
        @@ -9,17 +8,6 @@
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Play Mode
        - * @description
        - * <p>In 'sustain' mode, the sound will overlap with itself.
        - * In 'restart' mode it will stop and then start again.
        - * Click mouse to play a sound file.
        - * Trigger lots of sounds at once! Press any key to change playmode.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let playMode = 'sustain';
         let sample;
        diff --git a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        index c55a428efc..0f07dd1a6a 100644
        --- a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        +++ b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        @@ -1,19 +1,10 @@
         /*
        -<<<<<<< HEAD
          * @name 사운드 패닝
          * @description <p>마우스를 클릭해 사운드를 재생하세요.
          * 공의 위치는 마우스의 위치와 더불어, 사운드의 패닝과도 관련됩니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Pan Sound
        - * @description <p>Click mouse to play the sound.
        - * Ball position follows mouse and correlates to panning of sound.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          *
          */
         let ball = {};
        @@ -35,13 +26,8 @@ function draw() {
         }
         
         function mousePressed() {
        -<<<<<<< HEAD
           // 공의 x 위치를 패닝 각도에 맵핑하기
           // -1.0 (좌) 과 1.0 (우) 사이
        -=======
        -  // map the ball's x location to a panning degree
        -  // between -1.0 (left) and 1.0 (right)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let panning = map(ball.x, 0, width, -1.0, 1.0);
           soundFile.pan(panning);
           soundFile.play();
        diff --git a/src/data/examples/ko/33_Sound/05_Sound_Effect.js b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        index 03816d1c41..7f9b5e65a3 100644
        --- a/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        +++ b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 사운드 효과
          * @description <p>마우스로 원 안쪽을 누르면 사운드 효과가 재생됩니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        @@ -15,41 +14,16 @@
         class Doorbell {
           constructor(x_, y_, r_) {
             // 위치와 크기
        -=======
        - * @name Sound Effect
        - * @description <p>Play a sound effect when the mouse is clicked inside the circle.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        -// Adapted from Learning Processing by Daniel Shiffman
        -// http://www.learningprocessing.com
        -// Doorbell sample by Corsica_S via freesound.org,
        -// Creative Commons BY 3.0
        -
        -// A Class to describe a "doorbell" (really a button)
        -class Doorbell {
        -  constructor(x_, y_, r_) {
        -    // Location and size
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             this.x = x_;
             this.y = y_;
             this.r = r_;
           }
        -<<<<<<< HEAD
           // doorbell 안에 마우스 점이 있나요? (마우스 롤오버 등에 사용)
        -=======
        -  // Is a point inside the doorbell? (used for mouse rollover, etc.)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           contains(mx, my) {
             return dist(mx, my, this.x, this.y) < this.r;
           }
         
        -<<<<<<< HEAD
           // doorbell을 보여주세요. (색상 부분은 하드코딩이네요. 더 나은 방법이 있을거에요.)
        -=======
        -  // Show the doorbell (hardcoded colors, could be improved)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           display(mx, my) {
             if (this.contains(mx, my)) {
               fill(100);
        @@ -62,56 +36,32 @@ class Doorbell {
           }
         }
         
        -<<<<<<< HEAD
         // 사운드 파일 객체
         let dingdong;
         
         // 초인종 객체 (사운드를 트리거)
        -=======
        -// A sound file object
        -let dingdong;
        -
        -// A doorbell object (that will trigger the sound)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let doorbell;
         
         function setup() {
           createCanvas(200, 200);
         
        -<<<<<<< HEAD
           // 사운드 파일 불러오기
           // 스케치에 MP3와 OGG 버전을 포함시킵니다.
           soundFormats('mp3', 'ogg');
           dingdong = loadSound('assets/doorbell.mp3');
         
           // 새로운 초인종 만들기
        -=======
        -  // Load the sound file.
        -  // We have included both an MP3 and an OGG version.
        -  soundFormats('mp3', 'ogg');
        -  dingdong = loadSound('assets/doorbell.mp3');
        -
        -  // Create a new doorbell
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           doorbell = new Doorbell(width / 2, height / 2, 64);
         }
         
         function draw() {
           background(255);
        -<<<<<<< HEAD
           // 초인종 보이기
        -=======
        -  // Show the doorbell
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           doorbell.display(mouseX, mouseY);
         }
         
         function mousePressed() {
        -<<<<<<< HEAD
           // 사용자가 초인종을 클릭하면, 사운드 재생하기!
        -=======
        -  // If the user clicks on the doorbell, play the sound!
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (doorbell.contains(mouseX, mouseY)) {
             dingdong.play();
           }
        diff --git a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        index 891b0b1cea..5edc06eb21 100644
        --- a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        +++ b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 재생 속도
          * @description <p>사운드 파일을 불러와 재생 속도와 볼륨을 mouseY에 맵핑합니다.
          * 여기서 재생 속도란, 웹 오디오가 사운드 파일 정보를 처리하는 속도를 말합니다.
        @@ -14,67 +13,32 @@ let song;
         
         function preload() {
           // 사운드 파일 불러오기
        -=======
        - * @name Playback Rate
        - * @description <p>Load a SoundFile and map its playback rate to
        - * mouseY, volume to mouseX. Playback rate is the speed with
        - * which the web audio context processings the sound file information.
        - * Slower rates not only increase the duration of the sound, but also
        - * decrease the pitch because it is being played back at a slower frequency.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        -// A sound file object
        -let song;
        -
        -function preload() {
        -  // Load a sound file
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           song = loadSound('assets/Damscray_DancingTiger.mp3');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           // 사운드 무한 반복하기
           // (뭐, 적어도 stop()이 호출되기 전까지요)
        -=======
        -  // Loop the sound forever
        -  // (well, at least until stop() is called)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           song.loop();
         }
         
         function draw() {
           background(200);
         
        -<<<<<<< HEAD
           // 볼륨 범위를 0 과 1.0 사이로 설정
        -=======
        -  // Set the volume to a range between 0 and 1.0
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let volume = map(mouseX, 0, width, 0, 1);
           volume = constrain(volume, 0, 1);
           song.amp(volume);
         
        -<<<<<<< HEAD
           // 재생 속도 범위를 0.1 과 4 사이로 설정
           // 재생 속도를 변경하면 음고 또한 달라집니다.
        -=======
        -  // Set the rate to a range between 0.1 and 4
        -  // Changing the rate alters the pitch
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let speed = map(mouseY, 0.1, height, 0, 2);
           speed = constrain(speed, 0.01, 4);
           song.rate(speed);
         
        -<<<<<<< HEAD
           // 원을 그려 어떤 일이 일어나는지 확인하기
        -=======
        -  // Draw some circles to show what is going on
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(0);
           fill(51, 100);
           ellipse(mouseX, 100, 48, 48);
        diff --git a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        index dea6ee64b0..91c2e4e994 100644
        --- a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        +++ b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 진폭 측정
          * @description <p>p5.Amplitude로 사운드의 진폭을 분석합니다.</p>
          *
        @@ -17,28 +16,6 @@
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - * @name Measuring Amplitude
        - * @description <p>Analyze the amplitude of sound with
        - * p5.Amplitude.</p>
        - *
        - *  <p><b>Amplitude</b> is the magnitude of vibration. Sound is vibration,
        - *  so its amplitude is is closely related to volume / loudness.</p>
        - *
        - * <p>The <code>getLevel()</code> method takes an array
        - * of amplitude values collected over a small period of time (1024 samples).
        - * Then it returns the <b>Root Mean Square (RMS)</b> of these values.</p>
        - *
        - * <p>The original amplitude values for digital audio are between -1.0 and 1.0.
        - * But the RMS will always be positive, because it is squared.
        - * And, rather than use instantanous amplitude readings that are sampled at a rate
        - * of 44,100 times per second, the RMS is an average over time (1024 samples, in this case),
        - * which better represents how we hear amplitude.
        - * </p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let song, analyzer;
         
        @@ -50,36 +27,21 @@ function setup() {
           createCanvas(710, 200);
           song.loop();
         
        -<<<<<<< HEAD
           // 새로운 진폭 분석기 생성
           analyzer = new p5.Amplitude();
         
           // 볼륨 분석기에 입력값 패치하기
        -=======
        -  // create a new Amplitude analyzer
        -  analyzer = new p5.Amplitude();
        -
        -  // Patch the input to an volume analyzer
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           analyzer.setInput(song);
         }
         
         function draw() {
           background(255);
         
        -<<<<<<< HEAD
           // 평균 진폭값(RMS) 받아오기
        -=======
        -  // Get the average (root mean square) amplitude
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let rms = analyzer.getLevel();
           fill(127);
           stroke(0);
         
        -<<<<<<< HEAD
           // 볼륨과 비례한 크기의 타원 그리기
        -=======
        -  // Draw an ellipse with size based on volume
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           ellipse(width / 2, height / 2, 10 + rms * 200, 10 + rms * 200);
         }
        diff --git a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        index 164a9edfe3..2132861e7d 100644
        --- a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        +++ b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          *  @name 노이즈 드럼 엔벨로프
          *  @description  <p> 화이트 노이즈는 주파수 영역의 모든 부분에서
          *  동일한 에너지를 갖는, 임의의 오디오 신호입니다</p>
        @@ -11,29 +10,11 @@
          *  작동 중인 엔벨로프를 이 값으로서 초록색 사각형으로 표현합니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        -=======
        - *  @name Noise Drum Envelope
        - *  @description  <p>White Noise is a random audio signal with equal energy
        - *  at every part of the frequency spectrum</p>
        - *
        - *  <p>An Envelope is a series of fades, defined
        - *  as time / value pairs.</p>
        - *
        - *  <p>In this example, the p5.Env
        - *  will be used to "play" the p5.Noise like a drum by controlling its output
        - *  amplitude. A p5.Amplitude will get the level of all sound in the sketch, and
        - *  we'll use this value to draw a green rectangle that shows the envelope
        - *  in action.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let noise, env, analyzer;
         
         function setup() {
           createCanvas(710, 200);
        -<<<<<<< HEAD
           noise = new p5.Noise(); // 그 외 타입들은 '갈색'과 '분홍'을 포함
           noise.start();
         
        @@ -49,40 +30,16 @@ function setup() {
         
           // setInput()메소드로 입력값을 지정하지 않는 이상,
           // p5.Amplitude는 스케치에 포함된 모든 사운드를 분석할 것입니다.
        -=======
        -  noise = new p5.Noise(); // other types include 'brown' and 'pink'
        -  noise.start();
        -
        -  // multiply noise volume by 0
        -  // (keep it quiet until we're ready to make noise!)
        -  noise.amp(0);
        -
        -  env = new p5.Env();
        -  // set attackTime, decayTime, sustainRatio, releaseTime
        -  env.setADSR(0.001, 0.1, 0.2, 0.1);
        -  // set attackLevel, releaseLevel
        -  env.setRange(1, 0);
        -
        -  // p5.Amplitude will analyze all sound in the sketch
        -  // unless the setInput() method is used to specify an input.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           analyzer = new p5.Amplitude();
         }
         
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           // p5.Amplitude analyzer(분석 장치)로부터 볼륨 판독값 받아오기
           let level = analyzer.getLevel();
         
           // 레벨값을 사용하여 초록색 사각형 그리기
        -=======
        -  // get volume reading from the p5.Amplitude analyzer
        -  let level = analyzer.getLevel();
        -
        -  // use level to draw a green rectangle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let levelHeight = map(level, 0, 0.4, 0, height);
           fill(100, 250, 100);
           rect(0, height, width, -levelHeight);
        diff --git a/src/data/examples/ko/33_Sound/09_Note_Envelope.js b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        index 6affbb80c7..853814b982 100644
        --- a/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        +++ b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          *  @name 음계 엔벨로프
          *  @description  <p>엔벨로프(envelope)는 시간/값의 쌍으로 정의되는
          *  일련의 페이드를 말합니다.
        @@ -12,22 +11,6 @@
          *  마치 볼륨을 조정하듯 진폭을 조정할 수 있습니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        -=======
        - *  @name Note Envelope
        - *  @description  <p>An Envelope is a series of fades, defined
        - *  as time / value pairs. In this example, the envelope
        - *  will be used to "play" a note by controlling the output
        - *  amplitude of an oscillator.<br/><br/>
        - *  The p5.Oscillator sends its output through
        - *  an internal Web Audio GainNode (p5.Oscillator.output).
        - *  By default, that node has a constant value of 0.5. It can
        - *  be reset with the osc.amp() method. Or, in this example, an
        - *  Envelope takes control of that node, turning the amplitude
        - *  up and down like a volume knob.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let osc, envelope, fft;
         
        @@ -38,7 +21,6 @@ function setup() {
           createCanvas(710, 200);
           osc = new p5.SinOsc();
         
        -<<<<<<< HEAD
           // 엔벨로프 인스턴스화
           envelope = new p5.Env();
         
        @@ -46,15 +28,6 @@ function setup() {
           envelope.setADSR(0.001, 0.5, 0.1, 0.5);
         
           // 어택 레벨, 릴리즈 레벨 설정
        -=======
        -  // Instantiate the envelope
        -  envelope = new p5.Env();
        -
        -  // set attackTime, decayTime, sustainRatio, releaseTime
        -  envelope.setADSR(0.001, 0.5, 0.1, 0.5);
        -
        -  // set attackLevel, releaseLevel
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           envelope.setRange(1, 0);
         
           osc.start();
        @@ -75,11 +48,7 @@ function draw() {
             note = (note + 1) % scaleArray.length;
           }
         
        -<<<<<<< HEAD
           // 캔버스에 FFT.analyze() 주파수 분석 내용 기입
        -=======
        -  // plot FFT.analyze() frequency analysis on the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let spectrum = fft.analyze();
           for (let i = 0; i < spectrum.length / 20; i++) {
             fill(spectrum[i], spectrum[i] / 10, 0);
        diff --git a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        index c84563096a..434bd0a2b1 100644
        --- a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        +++ b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        @@ -1,29 +1,16 @@
         /*
        -<<<<<<< HEAD
          * @name 오실레이터 주파수
          * @description <p>FFT를 사용하여 오실레이터를 제어하고 그 파형을 봅니다.
          * MouseX는 주파수에, mouseY는 진폭에 매핑됩니다.</p>
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
        -=======
        - * @name Oscillator Frequency
        - * @description <p>Control an Oscillator and view the waveform using FFT.
        - * MouseX is mapped to frequency, mouseY is mapped to amplitude.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let osc, fft;
         
         function setup() {
           createCanvas(720, 256);
         
        -<<<<<<< HEAD
           osc = new p5.TriOsc(); // 주파수와 종류 설정
        -=======
        -  osc = new p5.TriOsc(); // set frequency and type
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           osc.amp(0.5);
         
           fft = new p5.FFT();
        @@ -33,11 +20,7 @@ function setup() {
         function draw() {
           background(255);
         
        -<<<<<<< HEAD
           let waveform = fft.waveform(); // 파형 분석하기
        -=======
        -  let waveform = fft.waveform(); // analyze the waveform
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           beginShape();
           strokeWeight(5);
           for (let i = 0; i < waveform.length; i++) {
        @@ -47,11 +30,7 @@ function draw() {
           }
           endShape();
         
        -<<<<<<< HEAD
           // 오실레이터 주파수를 mouseX에 따라 변경
        -=======
        -  // change oscillator frequency based on mouseX
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let freq = map(mouseX, 0, width, 40, 880);
           osc.freq(freq);
         
        diff --git a/src/data/examples/ko/33_Sound/11_Live_Input.js b/src/data/examples/ko/33_Sound/11_Live_Input.js
        index ddbf5f4db0..dc3fefa8e4 100644
        --- a/src/data/examples/ko/33_Sound/11_Live_Input.js
        +++ b/src/data/examples/ko/33_Sound/11_Live_Input.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 마이크 입력
          * @description <p>컴퓨터의 마이크를 통해 오디오 입력을 받습니다.
          * 마이크에 소리를 내어 타원이 떠오르게 해보세요.</p>
        @@ -7,56 +6,28 @@
          * p5.Amplitude를 생성하지 않고도 p5.AudioIn에서 getLevel을 호출할 수 있습니다.</p>
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
        -=======
        - * @name Mic Input
        - * @description <p>Get audio input from your computer's microphone.
        - * Make noise to float the ellipse.</p>
        - * <p>Note: p5.AudioIn contains its own p5.Amplitude object,
        - * so you can call getLevel on p5.AudioIn without
        - * creating a p5.Amplitude.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let mic;
         
         function setup() {
           createCanvas(710, 200);
         
        -<<<<<<< HEAD
           // 오디오 입력 생성하기
           mic = new p5.AudioIn();
         
           // 오디오 입력 시작하기
           // 그 기본값은 .connect()(즉, 컴퓨터 스피커에 연결)되지 "않은" 상태입니다.
        -=======
        -  // Create an Audio input
        -  mic = new p5.AudioIn();
        -
        -  // start the Audio Input.
        -  // By default, it does not .connect() (to the computer speakers)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           mic.start();
         }
         
         function draw() {
           background(200);
         
        -<<<<<<< HEAD
           // 전체 볼륨(0과 1.0 사이) 받아오기
        -=======
        -  // Get the overall volume (between 0 and 1.0)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let vol = mic.getLevel();
           fill(127);
           stroke(0);
         
        -<<<<<<< HEAD
           // 마이크 소리의 볼륨에 따라 떠있는 높이가 변하는 타원 그리기
        -=======
        -  // Draw an ellipse with height based on volume
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let h = map(vol, 0, 1, height, 0);
           ellipse(width / 2, h - 25, 50, 50);
         }
        diff --git a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        index 0f13045a68..488985b5be 100644
        --- a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        +++ b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        @@ -1,17 +1,9 @@
         /**
        -<<<<<<< HEAD
          * @name 주파수 스펙트럼
          * @description <p>실시간 오디오 입력을 통해 주파수 스펙트럼을 시각화합니다.</p>
          * <p><em><span class="small"> To run this example locally, you will need the
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        - * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
        -=======
        - * @name Frequency Spectrum
        - * @description <p>Visualize the frequency spectrum of live audio input.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let mic, fft;
         
        diff --git a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        index 33a81b8c9b..46e98c93d5 100644
        --- a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        +++ b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 마이크 임계값
          * @description <p>입력된 오디오의 볼륨이 임계값을 초과하면
          * 특정 이벤트(이 경우, 사각형 그리기)가 발생합니다.</p>
        @@ -7,16 +6,6 @@
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         // 다니엘 쉬프만(Daniel Shiffman)저 Learning Processing을 적용
        -=======
        - * @name Mic Threshold
        - * @description <p>Trigger an event (draw a rectangle) when the Audio Input
        - * volume surpasses a threshold.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        -// Adapted from Learning Processing, Daniel Shiffman
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         // learningprocessing.com
         let input;
         let analyzer;
        @@ -25,30 +14,18 @@ function setup() {
           createCanvas(710, 200);
           background(255);
         
        -<<<<<<< HEAD
           // 오디오 입력 생성하기
        -=======
        -  // Create an Audio input
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           input = new p5.AudioIn();
         
           input.start();
         }
         
         function draw() {
        -<<<<<<< HEAD
           // 전체 볼륨(0과 1.0 사이) 받아오기
           let volume = input.getLevel();
         
           // 만약 볼륨 > 0.1 이라면, 임의의 위치에 사각형 한 개가 그려집니다.
           // 볼륨이 커질수록, 사각형도 커집니다.
        -=======
        -  // Get the overall volume (between 0 and 1.0)
        -  let volume = input.getLevel();
        -
        -  // If the volume > 0.1,  a rect is drawn at a random location.
        -  // The louder the volume, the larger the rectangle.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let threshold = 0.1;
           if (volume > threshold) {
             stroke(0);
        @@ -56,22 +33,14 @@ function draw() {
             rect(random(40, width), random(height), volume * 50, volume * 50);
           }
         
        -<<<<<<< HEAD
           // 전체 볼륨 범위를 막대 그래프로 나타내고 임계값의 위치에는 선 하나 긋기
        -=======
        -  // Graph the overall potential volume, w/ a line at the threshold
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let y = map(volume, 0, 1, height, 0);
           let ythreshold = map(threshold, 0, 1, height, 0);
         
           noStroke();
           fill(175);
           rect(0, 0, 20, height);
        -<<<<<<< HEAD
           // 그 다음, 볼륨값을 보여주는 검정 사각형을 그래프 위에 그리기
        -=======
        -  // Then draw a rectangle on the graph, sized according to volume
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fill(0);
           rect(0, y, 20, y);
           stroke(0);
        diff --git a/src/data/examples/ko/33_Sound/16_Delay.js b/src/data/examples/ko/33_Sound/16_Delay.js
        index e870ae66ba..f18120992f 100644
        --- a/src/data/examples/ko/33_Sound/16_Delay.js
        +++ b/src/data/examples/ko/33_Sound/16_Delay.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          *  @name 딜레이 필터
          *  @description
          *  마우스를 클릭하여 p5.Delay로 처리된 사운드 파일을 들어보세요.
        @@ -10,18 +9,6 @@
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - *  @name Delay
        - *  @description
        - *  Click the mouse to hear the p5.Delay process a SoundFile.
        - *  MouseX controls the p5.Delay Filter Frequency.
        - *  MouseY controls both the p5.Delay Time and Resonance.
        - *  Visualize the resulting sound's volume with an Amplitude object.
        - *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let soundFile, analyzer, delay;
        @@ -34,19 +21,11 @@ function preload() {
         function setup() {
           createCanvas(710, 400);
         
        -<<<<<<< HEAD
           soundFile.disconnect(); // 여기선 딜레이만 들을 수 있습니다.
         
           delay = new p5.Delay();
           delay.process(soundFile, 0.12, 0.7, 2300);
           delay.setType('pingPong'); // 스테레오 효과
        -=======
        -  soundFile.disconnect(); // so we'll only hear delay
        -
        -  delay = new p5.Delay();
        -  delay.process(soundFile, 0.12, 0.7, 2300);
        -  delay.setType('pingPong'); // a stereo effect
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
           analyzer = new p5.Amplitude();
         }
        @@ -54,17 +33,10 @@ function setup() {
         function draw() {
           background(0);
         
        -<<<<<<< HEAD
           // p5.Amplitude 분석 장치의 볼륨 판독 내용 받아오기
           let level = analyzer.getLevel();
         
           // 레벨을 사용하여 초록색 사각형 그리기
        -=======
        -  // get volume reading from the p5.Amplitude analyzer
        -  let level = analyzer.getLevel();
        -
        -  // use level to draw a green rectangle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let levelHeight = map(level, 0, 0.1, 0, height);
           fill(100, 250, 100);
           rect(0, height, width, -levelHeight);
        diff --git a/src/data/examples/ko/33_Sound/17_Reverb.js b/src/data/examples/ko/33_Sound/17_Reverb.js
        index 90379eca87..672383782b 100644
        --- a/src/data/examples/ko/33_Sound/17_Reverb.js
        +++ b/src/data/examples/ko/33_Sound/17_Reverb.js
        @@ -7,15 +7,6 @@
          * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        -=======
        - *  @name Reverb
        - *  @description Reverb gives depth and perceived space to a sound. Here,
        - *  noise is processed with reverb.
        - *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let sound, reverb;
         
        @@ -23,13 +14,8 @@ function preload() {
           soundFormats('mp3', 'ogg');
           soundFile = loadSound('assets/Damscray_DancingTiger');
         
        -<<<<<<< HEAD
           // 기본값으로 설정된 연결 상태를 해제하여
           // reverb.process를 통해서만 사운드를 들을 수 있도록 처리합니다.
        -=======
        -  // disconnect the default connection
        -  // so that we only hear the sound via the reverb.process
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           soundFile.disconnect();
         }
         
        @@ -39,19 +25,11 @@ function setup() {
         
           reverb = new p5.Reverb();
         
        -<<<<<<< HEAD
           // 6초의 reverbTime(리버브 시간)과 0.2%의 decayRate(감쇠 속도)를 갖는
           // 리버브에 사운드 파일 연결하기 
           reverb.process(soundFile, 6, 0.2);
         
           reverb.amp(4); // 턴잇업!
        -=======
        -  // sonnects soundFile to reverb with a
        -  // reverbTime of 6 seconds, decayRate of 0.2%
        -  reverb.process(soundFile, 6, 0.2);
        -
        -  reverb.amp(4); // turn it up!
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         }
         
         function mousePressed() {
        diff --git a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        index b29d6e0557..51fa1b3416 100644
        --- a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        +++ b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 컨볼루션 리버브
          * @description <p>The p5.Convolver
          * p5.Convolver는 컨볼루션을 사용하여 실제 공간 사운드를 재현합니다. 
        @@ -12,30 +11,12 @@
          * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          * 컨볼루션 샘플들은 <a href="https://www.freesound.org/people/recordinghopkins/">
          * recordinghopkins</a>가 제작한 크리에이티브 커먼즈(CC)입니다.</span></p>
        -=======
        - * @name Convolution Reverb
        - * @description <p>The p5.Convolver can recreate the sound of actual
        - * spaces using convolution. Convolution takes an Impulse Response,
        - * (the sound of a room reverberating), and uses that to
        - * recreate the sound of that space.</p><p>Click to play a sound through
        - * convolution. Every time you click, the sound is convolved with
        - * a different Impulse Response. To hear the Impulse Response itself,
        - * press any key.</p>
        - *
        - * <p><em><span class="small">To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
        - * These convolution samples are Creative Commons BY
        - * <a href="https://www.freesound.org/people/recordinghopkins/">
        - * recordinghopkins</a></em></span></p>
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let sound, env, cVerb, fft;
         let currentIR = 0;
         let rawImpulse;
         
         function preload() {
        -<<<<<<< HEAD
           // 모든 임펄스/사운드들의 MP3 및 OGG 버전을 이 스케치에 포함시킵니다.
           soundFormats('ogg', 'mp3');
         
        @@ -43,25 +24,12 @@ function preload() {
           cVerb = createConvolver('assets/bx-spring');
         
           // bx-spring에 더해, cVerb.impulses 배열에 임펄스 응답 추가하기
        -=======
        -  // we have included both MP3 and OGG versions of all the impulses/sounds
        -  soundFormats('ogg', 'mp3');
        -
        -  // create a p5.Convolver
        -  cVerb = createConvolver('assets/bx-spring');
        -
        -  // add Impulse Responses to cVerb.impulses array, in addition to bx-spring
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           cVerb.addImpulse('assets/small-plate');
           cVerb.addImpulse('assets/drum');
           cVerb.addImpulse('assets/beatbox');
           cVerb.addImpulse('assets/concrete-tunnel');
         
        -<<<<<<< HEAD
           // p5.ConvultionReverb로 처리될 사운드 불러오기 
        -=======
        -  // load a sound that will be processed by the p5.ConvultionReverb
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           sound = loadSound('assets/Damscray_DancingTiger');
         }
         
        @@ -69,17 +37,10 @@ function setup() {
           createCanvas(710, 400);
           rawImpulse = loadSound('assets/' + cVerb.impulses[currentIR].name);
         
        -<<<<<<< HEAD
           // 마스터 출력으로부터 연결 해제하고...
           sound.disconnect();
           // ... cVerb로 처리하여
           // 오직 리버브만 들을 수 있도록 합니다.
        -=======
        -  // disconnect from master output...
        -  sound.disconnect();
        -  // ... and process with cVerb
        -  // so that we only hear the reverb
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           cVerb.process(sound);
         
           fft = new p5.FFT();
        @@ -91,11 +52,7 @@ function draw() {
         
           let spectrum = fft.analyze();
         
        -<<<<<<< HEAD
           // frequencySpectrum 배열에 있는 모든 값들을 사각형으로 그리기
        -=======
        -  // Draw every value in the frequencySpectrum array as a rectangle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noStroke();
           for (let i = 0; i < spectrum.length; i++) {
             let x = map(i, 0, spectrum.length, 0, width);
        @@ -105,38 +62,23 @@ function draw() {
         }
         
         function mousePressed() {
        -<<<<<<< HEAD
           // cVerb.impulses 배열 반복하기
        -=======
        -  // cycle through the array of cVerb.impulses
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           currentIR++;
           if (currentIR >= cVerb.impulses.length) {
             currentIR = 0;
           }
           cVerb.toggleImpulse(currentIR);
         
        -<<<<<<< HEAD
           // 임펄스를 거쳐 사운드 재생하기
           sound.play();
         
           // 현재 임펄스 응답 이름 보이기(파일 경로)
        -=======
        -  // play the sound through the impulse
        -  sound.play();
        -
        -  // display the current Impulse Response name (the filepath)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           println('Convolution Impulse Response: ' + cVerb.impulses[currentIR].name);
         
           rawImpulse.setPath('assets/' + cVerb.impulses[currentIR].name);
         }
         
        -<<<<<<< HEAD
         // 임펄스 재생하기(컨볼루션 없이)
        -=======
        -// play the impulse (without convolution)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function keyPressed() {
           rawImpulse.play();
         }
        diff --git a/src/data/examples/ko/33_Sound/19_Record_Save.js b/src/data/examples/ko/33_Sound/19_Record_Save.js
        index 641f1bb86c..5d11d49f9b 100644
        --- a/src/data/examples/ko/33_Sound/19_Record_Save.js
        +++ b/src/data/examples/ko/33_Sound/19_Record_Save.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 오디오 녹음/저장
          * @description 
          * 사운드를 녹음하고 재생한 뒤, 클라이언트 컴퓨터에 .wav 파일로 저장하세요
        @@ -12,21 +11,6 @@
         let mic, recorder, soundFile;
         
         let state = 0; // 마우스 버튼이 눌리면 녹음, 정지, 재생 순으로 상태가 변합니다.
        -=======
        - * @name Record Save Audio
        - * @description Record a sound, play it back and save
        - * it as a .wav file to the client's computer.
        - * We need three objects: a p5.AudioIn (mic / sound source),
        - * p5.SoundRecorder (records the sound), and a
        - * p5.SoundFile (play back / save).
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        -let mic, recorder, soundFile;
        -
        -let state = 0; // mousePress will increment from Record, to Stop, to Play
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(400, 400);
        @@ -34,7 +18,6 @@ function setup() {
           fill(0);
           text('Enable mic and click the mouse to begin recording', 20, 20);
         
        -<<<<<<< HEAD
           // AudioIn 생성하기
           mic = new p5.AudioIn();
         
        @@ -48,57 +31,27 @@ function setup() {
           recorder.setInput(mic);
         
           // 녹음된 사운드를 재생할 빈 사운드 파일 생성
        -=======
        -  // create an audio in
        -  mic = new p5.AudioIn();
        -
        -  // users must manually enable their browser microphone for recording to work properly!
        -  mic.start();
        -
        -  // create a sound recorder
        -  recorder = new p5.SoundRecorder();
        -
        -  // connect the mic to the recorder
        -  recorder.setInput(mic);
        -
        -  // create an empty sound file that we will use to playback the recording
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           soundFile = new p5.SoundFile();
         }
         
         function mousePressed() {
        -<<<<<<< HEAD
           // '.enabled' 불리언을 사용하여 사용자의 마이크 활성화 여부 확인(그렇지 않을 경우, 침묵 상태를 녹음하게 됩니다!)
           if (state === 0 && mic.enabled) {
             // p5.SoundFile에 녹음하라고 녹음기에 지시하기. 이 파일은 녹음 사운드를 재생하는 데에 쓰입니다.
        -=======
        -  // use the '.enabled' boolean to make sure user enabled the mic (otherwise we'd record silence)
        -  if (state === 0 && mic.enabled) {
        -    // Tell recorder to record to a p5.SoundFile which we will use for playback
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             recorder.record(soundFile);
         
             background(255, 0, 0);
             text('Recording now! Click to stop.', 20, 20);
             state++;
           } else if (state === 1) {
        -<<<<<<< HEAD
             recorder.stop(); // 녹음기를 멈추고, 결과물을 soundFile에 보내기
        -=======
        -    recorder.stop(); // stop recorder, and send the result to soundFile
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
             background(0, 255, 0);
             text('Recording stopped. Click to play & save', 20, 20);
             state++;
           } else if (state === 2) {
        -<<<<<<< HEAD
             soundFile.play(); // 결과물 재생하기!
             saveSound(soundFile, 'mySound.wav'); // 파일 저장하기
        -=======
        -    soundFile.play(); // play the result!
        -    saveSound(soundFile, 'mySound.wav'); // save file
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             state++;
           }
         }
        diff --git a/src/data/examples/ko/33_Sound/21_FreqModulation.js b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        index 33c64224e0..27140d9a8f 100644
        --- a/src/data/examples/ko/33_Sound/21_FreqModulation.js
        +++ b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 주파수 변조(FM)
          * @description <p> 주파수 변조(Frequancy Modulator, FM)는 강력한 합성 방식입니다.
          * 아주 간단히 말하자면, FM은 반송파와 변조기라는 두 개의 오실레이터를 포함합니다.
        @@ -58,72 +57,6 @@ let analyzer; // 이것을 사용해 파형을 시각화합니다.
         let carrierBaseFreq = 220;
         
         // 변조기의 최저/최고 범위
        -=======
        - * @name Frequency Modulation
        - * @description <p>Frequency Modulation is a powerful form of synthesis.
        - * In its simplest form, FM involves two oscillators, referred
        - * to as the carrier and the modulator. As the modulator's waveform oscillates
        - * between some minimum and maximum amplitude value, that momentary value
        - * is added to ("modulates") the frequency of the carrier.</p>
        - * <p>The <b>carrier</b> is typically set to oscillate at an audible frequency
        - * that we perceive as a pitch—in this case, it is a sine wave oscilaltor at 220Hz,
        - * equivalent to an "A3" note. The carrier is connected to master output by default
        - * (this is the case for all p5.Oscillators).</p>
        - * <p>We will <code>disconnect</code> the <b>modulator</b> from master output,
        - * and instead connect to the frequency of the carrier:
        - * <code>carrier.freq(modulator)</code>. This adds the output amplitude of the
        - * modulator to the frequency of the carrier.</p>
        - * <p>
        - * <b>Modulation Depth</b> describes how much the carrier frequency will modulate.
        - * It is based on the amplitude of the modulator.
        - * The modulator produces a continuous stream of amplitude values that we will add
        - * to the carrier frequency. An amplitude of zero means silence, so the modulation will
        - * have no effect. An amplitude of 1.0 scales the range of output values
        - * between +1.0 and -1.0. That is the standard range for sound that gets sent to
        - * your speakers, but in FM we are instead sending the modulator's output to the carrier frequency,
        - * where we'd barely notice the +1Hz / -1Hz modulation.
        - * So we will typically increase the amplitude ("depth") of the modulator to numbers much higher than what
        - * we might send to our speakers.</p>
        - * <p><b>Modulation Frequency</b> is the speed of modulation. When the modulation frequency is lower
        - * than 20Hz, we stop hearing its frequency as pitch, and start to hear it as a beating rhythm.
        - * For example, try 7.5Hz at a depth of 20 to mimic the "vibrato" effect of an operatic vocalist.
        - * The term for this is Low Frequency Oscillator, or LFO. Modulators set to higher frequencies can
        - * also produce interesting effects, especially when the frequency has a harmonic relationship
        - * to the carrier signal. For example, listen to what happens when the modulator's frequency is
        - * half or twice that of the carrier. This is the basis for FM Synthesis, developed by John Chowning
        - * in the 1960s, which came to revolutionize synthesis in the 1980s and is often used to synthesize
        - * brass and bell-like sounds.
        - *
        - * <p>In this example,</p><p>
        - * - MouseX controls the modulation depth (the amplitude of the modulator) from -150 to 150.
        - * When the modulator's amplitude is set to 0 (in the middle), notice how the modulation
        - * has no effect. The greater (the absolute value of) the number, the greater the effect.
        - * If the modulator waveform is symetrical like a square <code>[]</code>, sine <code>~</code>
        - * or triangle <code>/\</code>, the negative amplitude will be the same as positive amplitude.
        - * But in this example, the modulator is an asymetrical sawtooth wave, shaped like this /.
        - * When we multiply it by a negative number, it goes backwards like this \. To best
        - * observe the difference, try lowering the frequency.
        - * </p>
        - * <p>- MouseY controls the frequency of the modulator from 0 to 112 Hz.
        - * Try comparing modulation frequencies below the audible range (which starts around 20hz),
        - * and above it, especially in a harmonic relationship to the carrier frequency (which is 220hz, so
        - * try half that, 1/3, 1/4 etc...).
        - *
        - * <p><em><span class="small">You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * for this example to work in your own project.</em></span></p>
        - */
        -
        -let carrier; // this is the oscillator we will hear
        -let modulator; // this oscillator will modulate the frequency of the carrier
        -
        -let analyzer; // we'll use this visualize the waveform
        -
        -// the carrier frequency pre-modulation
        -let carrierBaseFreq = 220;
        -
        -// min/max ranges for modulator
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let modMaxFreq = 112;
         let modMinFreq = 0;
         let modMaxDepth = 150;
        @@ -134,7 +67,6 @@ function setup() {
           noFill();
         
           carrier = new p5.Oscillator('sine');
        -<<<<<<< HEAD
           carrier.amp(0); // 진폭 설정
           carrier.freq(carrierBaseFreq); // 주파수 설정
           carrier.start(); // 오실레이팅 시작
        @@ -151,61 +83,26 @@ function setup() {
           analyzer = new p5.FFT();
         
           // 마우스 오버 / 스타트 터치 시, 반송파 페이드 인/아웃
        -=======
        -  carrier.amp(0); // set amplitude
        -  carrier.freq(carrierBaseFreq); // set frequency
        -  carrier.start(); // start oscillating
        -
        -  // try changing the type to 'square', 'sine' or 'triangle'
        -  modulator = new p5.Oscillator('sawtooth');
        -  modulator.start();
        -
        -  // add the modulator's output to modulate the carrier's frequency
        -  modulator.disconnect();
        -  carrier.freq(modulator);
        -
        -  // create an FFT to analyze the audio
        -  analyzer = new p5.FFT();
        -
        -  // fade carrier in/out on mouseover / touch start
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           toggleAudio(cnv);
         }
         
         function draw() {
           background(30);
         
        -<<<<<<< HEAD
        -
           // 최대 및 최소 주파수 사이의 변조기 주파수에 mouseY를 매핑하기
           let modFreq = map(mouseY, height, 0, modMinFreq, modMaxFreq);
           modulator.freq(modFreq);
         
           // 변조기의 진폭 바꾸기
           // 음수의 amp는 톱니 파형을 반대로 뒤집고, 두드리는 듯한 사운드를 만듭니다.
        -=======
        -  // map mouseY to modulator freq between a maximum and minimum frequency
        -  let modFreq = map(mouseY, height, 0, modMinFreq, modMaxFreq);
        -  modulator.freq(modFreq);
        -
        -  // change the amplitude of the modulator
        -  // negative amp reverses the sawtooth waveform, and sounds percussive
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           //
           let modDepth = map(mouseX, 0, width, modMinDepth, modMaxDepth);
           modulator.amp(modDepth);
         
        -<<<<<<< HEAD
           // 파형 분석하기
           waveform = analyzer.waveform();
         
           // 파형 그리기
        -=======
        -  // analyze the waveform
        -  waveform = analyzer.waveform();
        -
        -  // draw the shape of the waveform
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(255);
           strokeWeight(10);
           beginShape();
        @@ -217,11 +114,7 @@ function draw() {
           endShape();
         
           strokeWeight(1);
        -<<<<<<< HEAD
           // 어떤 일이 일어나는 지에 대한 설명을 추가합니다.
        -=======
        -  // add a note about what's happening
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20);
           text(
             'Modulator Amplitude (Modulation Depth): ' + modDepth.toFixed(3),
        @@ -235,11 +128,7 @@ function draw() {
           );
         }
         
        -<<<<<<< HEAD
         // 사운드 토글을 위한 helper 함수
        -=======
        -// helper function to toggle sound
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function toggleAudio(cnv) {
           cnv.mouseOver(function() {
             carrier.amp(1.0, 0.01);
        diff --git a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        index 3981f8726b..a45481d22d 100644
        --- a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        +++ b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        @@ -1,5 +1,4 @@
         /**
        -<<<<<<< HEAD
          * @name 진폭 변조(AM)
          * @description <p>진폭 변조(Amplitude Modulation, AM)은
          * 반송파와 변조기라는 두 개의 오실레이터를 포함하고, 이는 반송파의 진폭을 조정합니다.</p>
        @@ -27,116 +26,47 @@
         let carrier; // 이것이 바로 우리가 듣게될 오실레이터입니다.
         let modulator; // 이 오실레이터가 반송파 주파수를 변조할 것입니다.
         let fft; // 이것을 사용해 파형을 시각화합니다.
        -=======
        - * @name Amplitude Modulation
        - * @description <p>Amplitude Modulation involves two oscillators, referred
        - * to as the carrier and the modulator, where the modulator controls
        - * the carrier's amplitude.</p>
        - *
        - * <p>The carrier is typically set at an audible frequency (i.e. 440 Hz)
        - * and connected to master output by default. The carrier.amp is
        - * set to zero because we will have the modulator control its amplitude.</p>
        - *
        - * <p>The modulator is disconnected from master output. Instead, it is connected
        - * to the amplitude of the Carrier, like this: carrier.amp(modulator).</p>
        - *
        - * <p>In this example...</p>
        - * <p>- MouseX controls the amplitude of the modulator
        - * from 0 to 1. When the modulator's amplitude is set to 0, the
        - * amplitude modulation has no effect.</p>
        - *
        - * <p>- MouseY controls the frequency of the modulator from 0 to 20hz.
        - * This range is lower frequencies than humans can hear, and we perceive the
        - * modulation as a rhythm. This range can simulate effects such as Tremolo.
        - * Ring Modulation is a type of Amplitude Modulation where the original
        - * carrier signal is not present, and often involves modulation at a faster
        - * frequency. </p>
        - *
        - * <p><em><span class="small">You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * for this example to work in your own project.</em></span></p>
        - */
        -let carrier; // this is the oscillator we will hear
        -let modulator; // this oscillator will modulate the amplitude of the carrier
        -let fft; // we'll visualize the waveform
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
         function setup() {
           createCanvas(800, 400);
           noFill();
        -<<<<<<< HEAD
           background(30); // 알파값
         
           carrier = new p5.Oscillator(); // 기본값으로, 마스터 출력에 연결된 상태입니다.
           carrier.freq(340);
           carrier.amp(0);
           // 반송파의 amp는 기본값으로 0을 가져, 변조기에게 완전한 제어 권한을 부여합니다.
        -=======
        -  background(30); // alpha
        -
        -  carrier = new p5.Oscillator(); // connects to master output by default
        -  carrier.freq(340);
        -  carrier.amp(0);
        -  // carrier's amp is 0 by default, giving our modulator total control
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         
           carrier.start();
         
           modulator = new p5.Oscillator('triangle');
        -<<<<<<< HEAD
           modulator.disconnect(); // 변조기를 마스터 출력과 연결 해제합니다.
        -=======
        -  modulator.disconnect(); // disconnect the modulator from master output
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           modulator.freq(5);
           modulator.amp(1);
           modulator.start();
         
        -<<<<<<< HEAD
           // 변조기를 사용해 반송파의 진폭을 변조하기
           // 추가적으로, 신호도 조정할 수 있습니다.
           carrier.amp(modulator.scale(-1, 1, 1, -1));
         
           // 오디오 분석을 위해 FFT 생성하기
        -=======
        -  // Modulate the carrier's amplitude with the modulator
        -  // Optionally, we can scale the signal.
        -  carrier.amp(modulator.scale(-1, 1, 1, -1));
        -
        -  // create an fft to analyze the audio
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           fft = new p5.FFT();
         }
         
         function draw() {
        -<<<<<<< HEAD
           background(30, 30, 30, 100); // 알파값
         
           // 0과 20hz 사이의 변조기 주파수에 mouseY를 매핑하기
        -=======
        -  background(30, 30, 30, 100); // alpha
        -
        -  // map mouseY to moodulator freq between 0 and 20hz
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let modFreq = map(mouseY, 0, height, 20, 0);
           modulator.freq(modFreq);
         
           let modAmp = map(mouseX, 0, width, 0, 1);
        -<<<<<<< HEAD
           modulator.amp(modAmp, 0.01); // 페이드 타임을 0.1로 조정하여 페이딩을 부드럽게 만들기
         
           // 파형 분석하기
           waveform = fft.waveform();
         
           // 파형 그리기
        -=======
        -  modulator.amp(modAmp, 0.01); // fade time of 0.1 for smooth fading
        -
        -  // analyze the waveform
        -  waveform = fft.waveform();
        -
        -  // draw the shape of the waveform
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           drawWaveform();
         
           drawText(modFreq, modAmp);
        diff --git a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        index 60613d1cde..83902a3de1 100644
        --- a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        +++ b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        @@ -1,6 +1,5 @@
         /*
        -<<<<<<< HEAD
        - * @name 가속 공 바운스
        + * @name 가속도와 바운스
          * @description accelerationX와 accelerationY 값을 활용해 타원을 움직이고, 캔버스의 경계에 닿았을 때 튕기도록 만듭니다.
          */
         
        @@ -13,21 +12,6 @@ let vx = 0;
         let vy = 0;
         
         // 가속 변수들
        -=======
        - * @name Acceleration Ball Bounce
        - * @description Move an ellipse around based on accelerationX and accelerationY values, and bounces when touch the edge of the canvas.
        - */
        -
        -// Position Variables
        -let x = 0;
        -let y = 0;
        -
        -// Speed - Velocity
        -let vx = 0;
        -let vy = 0;
        -
        -// Acceleration
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let ax = 0;
         let ay = 0;
         
        @@ -54,11 +38,7 @@ function ballMove() {
           y = y + vy * vMultiplier;
           x = x + vx * vMultiplier;
         
        -<<<<<<< HEAD
           // 캔버스의 경계에 닿았을 때 튕기기
        -=======
        -  // Bounce when touch the edge of the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (x < 0) {
             x = 0;
             vx = -vx * bMultiplier;
        diff --git a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        index 8c36866044..de4f128884 100644
        --- a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        +++ b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 간단한 드로잉
          * @description mouseX, mouseY, pmouseX, pmouseY 값을 사용하여 스크린을 터치했을 때 그려지도록 합니다.
        -=======
        - * @name Simple Draw
        - * @description Touch to draw on the screen using mouseX, mouseY, pmouseX, and pmouseY values.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        index 09279d7207..cecd1bed76 100644
        --- a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        +++ b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 가속도 색상
          * @description deviceMoved()를 사용해 모바일 기기의 회전을 감지합니다. 배경의 RGB 색상값은 각각 accelerationX, accelerationY, accelerationZ 값에 매핑됩니다.
        -=======
        - * @name Acceleration Color
        - * @description Use deviceMoved() to detect when the device is rotated. The background RGB color values are mapped to accelerationX, accelerationY, and accelerationZ values.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let r, g, b;
        diff --git a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        index c30827ce08..404fae8810 100644
        --- a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        +++ b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        @@ -1,15 +1,9 @@
         /*
        -<<<<<<< HEAD
        - * @name 공 흔들고 튕기기
        + * @name 흔들기와 바운스
          * @description Ball 클래스를 생성하고 복수의 객체를 인스턴스화한 뒤, 화면 위에서 움직여보세요.
          * 공이 캔버스의 경계에 닿으면 튕깁니다. 
          * accelerationX와 accelerationY의 총 변화를 기반으로 흔들림을 감지하고,
          * 그러한 감지를 기반으로 객체의 속도를 높이거나 줄입니다.
        -=======
        - * @name Shake Ball Bounce
        - * @description Create a Ball class, instantiate multiple objects, move it around the screen, and bounce when touch the edge of the canvas.
        - * Detect shake event based on total change in accelerationX and accelerationY and speed up or slow down objects based on detection.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         
         let balls = [];
        @@ -39,30 +33,18 @@ function draw() {
         }
         
         function checkForShake() {
        -<<<<<<< HEAD
        -  // accelerationX and accelerationY의 총 변화 계산
        +  // accelerationX와 accelerationY의 총 변화 계산
           accChangeX = abs(accelerationX - pAccelerationX);
           accChangeY = abs(accelerationY - pAccelerationY);
           accChangeT = accChangeX + accChangeY;
           // 만약 흔들린다면,
        -=======
        -  // Calculate total change in accelerationX and accelerationY
        -  accChangeX = abs(accelerationX - pAccelerationX);
        -  accChangeY = abs(accelerationY - pAccelerationY);
        -  accChangeT = accChangeX + accChangeY;
        -  // If shake
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (accChangeT >= threshold) {
             for (let i = 0; i < balls.length; i++) {
               balls[i].shake();
               balls[i].turn();
             }
           }
        -<<<<<<< HEAD
           // 만약 흔들리지 않는다면,
        -=======
        -  // If not shake
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           else {
             for (let i = 0; i < balls.length; i++) {
               balls[i].stopShake();
        @@ -72,11 +54,7 @@ function checkForShake() {
           }
         }
         
        -<<<<<<< HEAD
         // Ball 클래스
        -=======
        -// Ball class
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Ball {
           constructor() {
             this.x = random(width);
        @@ -94,11 +72,7 @@ class Ball {
             this.y += this.yspeed * this.direction;
           }
         
        -<<<<<<< HEAD
           // 캔버스 경계에 닿았을 때 공 튀기기
        -=======
        -  // Bounce when touch the edge of the canvas
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           turn() {
             if (this.x < 0) {
               this.x = 0;
        @@ -115,23 +89,14 @@ class Ball {
             }
           }
         
        -<<<<<<< HEAD
           // accerlerationX 값의 변화를 기반으로
           // xspeed와 yspeed에 더하기
        -=======
        -  // Add to xspeed and yspeed based on
        -  // the change in accelerationX value
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           shake() {
             this.xspeed += random(5, accChangeX / 3);
             this.yspeed += random(5, accChangeX / 3);
           }
         
        -<<<<<<< HEAD
           // 점점 느려지기
        -=======
        -  // Gradually slows down
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stopShake() {
             if (this.xspeed > this.oxspeed) {
               this.xspeed -= 0.6;
        diff --git a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        index b9bb7c96b3..7479b4c77c 100644
        --- a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        +++ b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        @@ -1,11 +1,6 @@
         /*
        -<<<<<<< HEAD
          * @name 기울어진 3D상자
          * @description 모바일 기기를 이용해 상자를 기울게 만듭니다.
        -=======
        - * @name Tilted 3D Box
        - * @description Use mobile to tilt a box
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(displayWidth, displayHeight, WEBGL);
        diff --git a/src/data/examples/ko/90_Hello_P5/01_shapes.js b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        index 8bd6bd5b40..308d10ed3e 100644
        --- a/src/data/examples/ko/90_Hello_P5/01_shapes.js
        +++ b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 간단한 도형들
          * @description 이 예제는 원, 사각형, 삼각형, 그리고 꽃 모양을 포함합니다.
          */
        @@ -20,28 +19,6 @@ function setup() {
           triangle(300, 100, 320, 100, 310, 80);
         
           // 간단한 꽃 그리기
        -=======
        - * @name Simple Shapes
        - * @description This examples includes a circle, square, triangle, and a flower.
        - */
        -function setup() {
        -  // Create the canvas
        -  createCanvas(720, 400);
        -  background(200);
        -
        -  // Set colors
        -  fill(204, 101, 192, 127);
        -  stroke(127, 63, 120);
        -
        -  // A rectangle
        -  rect(40, 120, 120, 40);
        -  // An ellipse
        -  ellipse(240, 240, 80, 80);
        -  // A triangle
        -  triangle(300, 100, 320, 100, 310, 80);
        -
        -  // A design for a simple flower
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           translate(580, 200);
           noStroke();
           for (let i = 0; i < 10; i ++) {
        diff --git a/src/data/examples/ko/90_Hello_P5/02_interactivity.js b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        index 5ac35b37a1..95c1733fec 100644
        --- a/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        +++ b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 인터랙티비티 1
          * @frame 720,425
          * @description 원을 클릭하면 색상이 바뀝니다.
        @@ -9,26 +8,11 @@
          */
         
         // 빨강(r), 초록(g), 파랑(b) 색상값들
        -=======
        - * @name Interactivity 1
        - * @frame 720,425
        - * @description The circle changes color when you click on it.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.
        - * </em></p>
        - */
        -
        -// for red, green, and blue color values
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let r, g, b;
         
         function setup() {
           createCanvas(720, 400);
        -<<<<<<< HEAD
           // 임의의 색상 고르기
        -=======
        -  // Pick colors randomly
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           r = random(255);
           g = random(255);
           b = random(255);
        @@ -36,32 +20,19 @@ function setup() {
         
         function draw() {
           background(127);
        -<<<<<<< HEAD
           // 원 그리기
        -=======
        -  // Draw a circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           strokeWeight(2);
           stroke(r, g, b);
           fill(r, g, b, 127);
           ellipse(360, 200, 200, 200);
         }
         
        -<<<<<<< HEAD
         // 사용자가 마우스를 클릭했을 때,
         function mousePressed() {
           // 마우스가 원의 안쪽에 있는지 확인하기
           let d = dist(mouseX, mouseY, 360, 200);
           if (d < 100) {
             // 새로운 임의의 색상 고르기
        -=======
        -// When the user clicks the mouse
        -function mousePressed() {
        -  // Check if mouse is inside the circle
        -  let d = dist(mouseX, mouseY, 360, 200);
        -  if (d < 100) {
        -    // Pick new random color values
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             r = random(255);
             g = random(255);
             b = random(255);
        diff --git a/src/data/examples/ko/90_Hello_P5/03_interactivity.js b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        index 08af063d3b..6a64eec90a 100644
        --- a/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        +++ b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        @@ -1,20 +1,20 @@
         /*
        - * @name Interactivity 2
        + * @name 인터랙티비티 2
          * @frame 720,425
        - * @description The circle changes color when you move the slider.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
        + * @description 슬라이더를 움직이면 원의 색상이 바뀝니다.
        + * 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가해야 됩니다.
          */
         
        -// A HTML range slider
        +// HTML 범위 슬라이더
         let slider;
         
         function setup() {
           createCanvas(720, 400);
        -  // hue, saturation, and brightness
        +  // 색조(H), 채도(S), 밝기(B)
           colorMode(HSB, 255);
        -  // slider has a range between 0 and 255 with a starting value of 127
        +  // 슬라이더의 범위를 0부터 255까지로, 그 시작값을 127로 설정하기
           slider = createSlider(0, 255, 127);
         }
         
        @@ -22,7 +22,7 @@ function draw() {
           background(127);
           strokeWeight(2);
         
        -  // Set the hue according to the slider
        +  // 슬라이더에 따라 채도 설정하기
           stroke(slider.value(), 255, 255);
           fill(slider.value(), 255, 255, 127);
           ellipse(360, 200, 200, 200);
        diff --git a/src/data/examples/ko/90_Hello_P5/04_animate.js b/src/data/examples/ko/90_Hello_P5/04_animate.js
        index c255b0ee90..f746dd15ea 100644
        --- a/src/data/examples/ko/90_Hello_P5/04_animate.js
        +++ b/src/data/examples/ko/90_Hello_P5/04_animate.js
        @@ -1,24 +1,13 @@
         /*
        -<<<<<<< HEAD
          * @name 애니메이션
          * @description 원이 움직입니다.
          */
         // 원의 위치를 알기 위해
        -=======
        - * @name Animation
        - * @description The circle moves.
        - */
        -// Where is the circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let x, y;
         
         function setup() {
           createCanvas(720, 400);
        -<<<<<<< HEAD
           // 화면 가운데에서 시작하기
        -=======
        -  // Starts in the middle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           x = width / 2;
           y = height;
         }
        @@ -26,30 +15,17 @@ function setup() {
         function draw() {
           background(200);
           
        -<<<<<<< HEAD
           // 원 그리기
        -=======
        -  // Draw a circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           stroke(50);
           fill(100);
           ellipse(x, y, 24, 24);
           
        -<<<<<<< HEAD
           // 가로축에서 무작위로 흔들리기
           x = x + random(-1, 1);
           // 일정 속도로 위를 향해 움직이기
           y = y - 1;
           
           // 화면 하단으로 리셋
        -=======
        -  // Jiggling randomly on the horizontal axis
        -  x = x + random(-1, 1);
        -  // Moving up at a constant speed
        -  y = y - 1;
        -  
        -  // Reset to the bottom
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (y < 0) {
             y = height;
           }
        diff --git a/src/data/examples/ko/90_Hello_P5/04_flocking.js b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        index 99e7776d6d..a5b5c9600b 100644
        --- a/src/data/examples/ko/90_Hello_P5/04_flocking.js
        +++ b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        @@ -1,27 +1,16 @@
         /*
        -<<<<<<< HEAD
          * @name 플로킹
          * @description 크레이그 레이놀즈(Craig Reynolds)의
          * <a href="http://www.red3d.com/cwr/">"군집(Flocking)" 행위</a>를 묘사합니다.<br>
          * (규칙: 응집, 분리, 정렬)<br>
          * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
        -=======
        - * @name Flocking
        - * @description Demonstration of <a href="http://www.red3d.com/cwr/">Craig Reynolds' "Flocking" behavior</a>.<br>
        - * (Rules: Cohesion, Separation, Alignment.)<br>
        - * From <a href="http://natureofcode.com">natureofcode.com</a>.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let boids = [];
         
         function setup() {
           createCanvas(720, 400);
         
        -<<<<<<< HEAD
           // 시스템에 초기 개체(boid) 더하기
        -=======
        -  // Add an initial set of boids into the system
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < 100; i++) {
             boids[i] = new Boid(random(width), random(height));
           }
        @@ -29,36 +18,22 @@ function setup() {
         
         function draw() {
           background(51);
        -<<<<<<< HEAD
           // 모든 개체 실행하기
        -=======
        -  // Run all the boids
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for (let i = 0; i < boids.length; i++) {
             boids[i].run(boids);
           }
         }
         
        -<<<<<<< HEAD
         // Boid 클래스
         // Separation(분리), Cohesion(응집), Alignment(정렬)을 위한 메소드 추가하기
        -=======
        -// Boid class
        -// Methods for Separation, Cohesion, Alignment added
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Boid {
           constructor(x, y) {
             this.acceleration = createVector(0, 0);
             this.velocity = p5.Vector.random2D();
             this.position = createVector(x, y);
             this.r = 3.0;
        -<<<<<<< HEAD
             this.maxspeed = 3;    // 최고 속도
             this.maxforce = 0.05; // 최고 조타력
        -=======
        -    this.maxspeed = 3;    // Maximum speed
        -    this.maxforce = 0.05; // Maximum steering force
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           }
         
           run(boids) {
        @@ -68,16 +43,11 @@ class Boid {
             this.render();
           }
           
        -<<<<<<< HEAD
           // Force는 acceleration에 담깁니다.
        -=======
        -  // Forces go into acceleration
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           applyForce(force) {
             this.acceleration.add(force);
           }
           
        -<<<<<<< HEAD
           // 세 가지 규칙을 기반으로 새로운 accerlation(가속도)를 축적합니다.
           flock(boids) {
             let sep = this.separate(boids); // 분리
        @@ -88,24 +58,11 @@ class Boid {
             ali.mult(1.0);
             coh.mult(1.0);
             // 가속도에 force 벡터 더하기
        -=======
        -  // We accumulate a new acceleration each time based on three rules
        -  flock(boids) {
        -    let sep = this.separate(boids); // Separation
        -    let ali = this.align(boids);    // Alignment
        -    let coh = this.cohesion(boids); // Cohesion
        -    // Arbitrarily weight these forces
        -    sep.mult(2.5);
        -    ali.mult(1.0);
        -    coh.mult(1.0);
        -    // Add the force vectors to acceleration
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             this.applyForce(sep);
             this.applyForce(ali);
             this.applyForce(coh);
           }
           
        -<<<<<<< HEAD
           // 위치 업데이트를 위한 메소드
           update() {
             // 속도 업데이트
        @@ -122,41 +79,15 @@ class Boid {
           seek(target) {
             let desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
           // desired를 표준화하고 최대 속도로 조정
        -=======
        -  // Method to update location
        -  update() {
        -    // Update velocity
        -    this.velocity.add(this.acceleration);
        -    // Limit speed
        -    this.velocity.limit(this.maxspeed);
        -    this.position.add(this.velocity);
        -    // Reset acceleration to 0 each cycle
        -    this.acceleration.mult(0);
        -  }
        -  
        -  // A method that calculates and applies a steering force towards a target
        -  // STEER = DESIRED MINUS VELOCITY
        -  seek(target) {
        -    let desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
        -    // Normalize desired and scale to maximum speed
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             desired.normalize();
             desired.mult(this.maxspeed);
             // Steering = Desired minus Velocity
             let steer = p5.Vector.sub(desired, this.velocity);
        -<<<<<<< HEAD
             steer.limit(this.maxforce); // 최대 조타력으로 제한
             return steer;
           }
           
           // 개체(boid)를 원형으로 그리기
        -=======
        -    steer.limit(this.maxforce); // Limit to maximum steering force
        -    return steer;
        -  }
        -  
        -  // Draw boid as a circle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           render() {
             fill(127, 127);
             stroke(200);
        @@ -171,18 +102,12 @@ class Boid {
             if (this.position.y > height + this.r) this.position.y = -this.r;
           }
           
        -<<<<<<< HEAD
           // 분리 Seperation
           // 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
        -=======
        -  // Separation
        -  // Method checks for nearby boids and steers away
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           separate(boids) {
             let desiredseparation = 25.0;
             let steer = createVector(0, 0);
             let count = 0;
        -<<<<<<< HEAD
             // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
             for (let i = 0; i < boids.length; i++) {
               let d = p5.Vector.dist(this.position, boids[i].position);
        @@ -197,35 +122,13 @@ class Boid {
               }
             }
             // 평균 -- 얼마로 나눌 것인가
        -=======
        -    // For every boid in the system, check if it's too close
        -    for (let i = 0; i < boids.length; i++) {
        -      let d = p5.Vector.dist(this.position, boids[i].position);
        -      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
        -      if ((d > 0) && (d < desiredseparation)) {
        -        // Calculate vector pointing away from neighbor
        -        let diff = p5.Vector.sub(this.position, boids[i].position);
        -        diff.normalize();
        -        diff.div(d); // Weight by distance
        -        steer.add(diff);
        -        count++; // Keep track of how many
        -      }
        -    }
        -    // Average -- divide by how many
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (count > 0) {
               steer.div(count);
             }
           
        -<<<<<<< HEAD
             // 벡터가 0보다 크다면,
             if (steer.mag() > 0) {
               // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
        -=======
        -    // As long as the vector is greater than 0
        -    if (steer.mag() > 0) {
        -      // Implement Reynolds: Steering = Desired - Velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               steer.normalize();
               steer.mult(this.maxspeed);
               steer.sub(this.velocity);
        @@ -234,13 +137,8 @@ class Boid {
             return steer;
           }
           
        -<<<<<<< HEAD
           // 배열 Alignment
           // 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
        -=======
        -  // Alignment
        -  // For every nearby boid in the system, calculate the average velocity
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           align(boids) {
             let neighbordist = 50;
             let sum = createVector(0, 0);
        @@ -264,38 +162,22 @@ class Boid {
             }
           }
           
        -<<<<<<< HEAD
           // 응집 Cohesion
           // 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
           cohesion(boids) {
             let neighbordist = 50;
             let sum = createVector(0, 0); // 빈 벡터값으로 시작하여 모든 위치들을 축적
        -=======
        -  // Cohesion
        -  // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
        -  cohesion(boids) {
        -    let neighbordist = 50;
        -    let sum = createVector(0, 0); // Start with empty vector to accumulate all locations
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             let count = 0;
             for (let i = 0; i < boids.length; i++) {
               let d = p5.Vector.dist(this.position, boids[i].position);
               if ((d > 0) && (d < neighbordist)) {
        -<<<<<<< HEAD
                 sum.add(boids[i].position); // 위치 추가
        -=======
        -        sum.add(boids[i].position); // Add location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
                 count++;
               }
             }
             if (count > 0) {
               sum.div(count);
        -<<<<<<< HEAD
               return this.seek(sum); // 해당 위치를 향해 조타
        -=======
        -      return this.seek(sum); // Steer towards the location
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             } else {
               return createVector(0, 0);
             }
        diff --git a/src/data/examples/ko/90_Hello_P5/05_weather.js b/src/data/examples/ko/90_Hello_P5/05_weather.js
        index 5084201490..b415a3c4d7 100644
        --- a/src/data/examples/ko/90_Hello_P5/05_weather.js
        +++ b/src/data/examples/ko/90_Hello_P5/05_weather.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 날씨
          * @frame 720,280
          * @description 이 예제는 apixu.com로부터 JSON 날씨 데이터를 받아옵니다.
        @@ -11,55 +10,26 @@
         // 풍향 벡터
         let wind;
         // 원의 위치
        -=======
        - * @name Weather
        - * @frame 720,280
        - * @description This example grabs JSON weather data from apixu.com.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
        -*/
        -
        -// A wind direction vector
        -let wind;
        -// Circle position
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let position;
         
         function setup() {
           createCanvas(720, 200);
        -<<<<<<< HEAD
           // apixu.com에 데이터 요청하기
           let url = 'https://api.apixu.com/v1/current.json?key=513d8003c8b348f1a2461629162106&q=NYC';
           loadJSON(url, gotWeather);
           // 화면의 가운데에서 원그리기 시작
           position = createVector(width/2, height/2);
           // 바람은 (0,0)에서 시작
        -=======
        -  // Request the data from apixu.com
        -  let url = 'https://api.apixu.com/v1/current.json?key=513d8003c8b348f1a2461629162106&q=NYC';
        -  loadJSON(url, gotWeather);
        -  // Circle starts in the middle
        -  position = createVector(width/2, height/2);
        -  // wind starts as (0,0)
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           wind = createVector();
         }
         
         function draw() {
           background(200);
         
        -<<<<<<< HEAD
           // 이 섹션에서는 풍향을 나타내는 화살표를 그립니다.
           push();
           translate(32, height - 32);
           // 바람의 각도에 따라 회전하기
        -=======
        -  // This section draws an arrow pointing in the direction of wind
        -  push();
        -  translate(32, height - 32);
        -  // Rotate by the wind's angle
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           rotate(wind.heading() + PI/2);
           noStroke();
           fill(255);
        @@ -74,11 +44,7 @@ function draw() {
           triangle(0, -18, -6, -10, 6, -10);
           pop();
           
        -<<<<<<< HEAD
           // 풍향에 따라 움직이기
        -=======
        -  // Move in the wind's direction
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           position.add(wind);
           
           stroke(0);
        @@ -93,7 +59,6 @@ function draw() {
         
         function gotWeather(weather) {
           
        -<<<<<<< HEAD
           // 각도 받아오기 (래디언으로 변환)
           let angle = radians(Number(weather.current.wind_degree));
           // 풍속 받아오기
        @@ -104,17 +69,5 @@ function gotWeather(weather) {
           let windDiv = createDiv("WIND " + windmag + " <small>MPH</small>");
           
           // 벡터 생성하기
        -=======
        -  // Get the angle (convert to radians)
        -  let angle = radians(Number(weather.current.wind_degree));
        -  // Get the wind speed
        -  let windmag = Number(weather.current.wind_mph);
        -  
        -  // Display as HTML elements
        -  let temperatureDiv = createDiv(floor(weather.current.temp_f) + '&deg;');
        -  let windDiv = createDiv("WIND " + windmag + " <small>MPH</small>");
        -  
        -  // Make a vector
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           wind = p5.Vector.fromAngle(angle);
         }
        diff --git a/src/data/examples/ko/90_Hello_P5/06_drawing.js b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        index 18839c46c0..db309cbd67 100644
        --- a/src/data/examples/ko/90_Hello_P5/06_drawing.js
        +++ b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
         * @name 드로잉
         * @description 제너레이티브 페인팅 프로그램입니다.
         */
        @@ -11,19 +10,6 @@ let painting = false;
         // 다음 원까지 걸리는 시간
         let next = 0;
         // 현재 및 이전 위치
        -=======
        -* @name Drawing
        -* @description Generative painting program.
        -*/
        -
        -// All the paths
        -let paths = [];
        -// Are we painting?
        -let painting = false;
        -// How long until the next circle
        -let next = 0;
        -// Where are we now and where were we?
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let current;
         let previous;
         
        @@ -36,7 +22,6 @@ function setup() {
         function draw() {
           background(200);
           
        -<<<<<<< HEAD
           // 새로운 점을 만들어 봅시다.
           if (millis() > next && painting) {
         
        @@ -55,46 +40,18 @@ function draw() {
             next = millis() + random(100);
         
             // 더 많은 마우스값 저장하기
        -=======
        -  // If it's time for a new point
        -  if (millis() > next && painting) {
        -
        -    // Grab mouse position      
        -    current.x = mouseX;
        -    current.y = mouseY;
        -
        -    // New particle's force is based on mouse movement
        -    let force = p5.Vector.sub(current, previous);
        -    force.mult(0.05);
        -
        -    // Add new particle
        -    paths[paths.length - 1].add(current, force);
        -    
        -    // Schedule next circle
        -    next = millis() + random(100);
        -
        -    // Store mouse values
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             previous.x = current.x;
             previous.y = current.y;
           }
         
        -<<<<<<< HEAD
           // 모든 경로 그리기
        -=======
        -  // Draw all paths
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           for( let i = 0; i < paths.length; i++) {
             paths[i].update();
             paths[i].display();
           }
         }
         
        -<<<<<<< HEAD
         // 시작하기
        -=======
        -// Start it up
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function mousePressed() {
           next = 0;
           painting = true;
        @@ -103,20 +60,12 @@ function mousePressed() {
           paths.push(new Path());
         }
         
        -<<<<<<< HEAD
         // 정지
        -=======
        -// Stop
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function mouseReleased() {
           painting = false;
         }
         
        -<<<<<<< HEAD
         // Path(경로)는 파티클들의 목록입니다.
        -=======
        -// A Path is a list of particles
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Path {
           constructor() {
             this.particles = [];
        @@ -124,26 +73,17 @@ class Path {
           }
         
           add(position, force) {
        -<<<<<<< HEAD
             // 새로운 파티클을 그 위치, 힘, 색조값과 함께 추가하기
             this.particles.push(new Particle(position, force, this.hue));
           }
           
           // 파티클 길이 화면에 보이기
        -=======
        -    // Add a new particle with a position, force, and hue
        -    this.particles.push(new Particle(position, force, this.hue));
        -  }
        -  
        -  // Display plath
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           update() {  
             for (let i = 0; i < this.particles.length; i++) {
               this.particles[i].update();
             }
           }  
           
        -<<<<<<< HEAD
           // 파티클 길이 화면에 보이기
           display() {    
             // 뒤로 반복하기
        @@ -152,16 +92,6 @@ class Path {
               if (this.particles[i].lifespan <= 0) {
                 this.particles.splice(i, 1);
               // 그렇지 않다면, 화면에 보이기
        -=======
        -  // Display plath
        -  display() {    
        -    // Loop through backwards
        -    for (let i = this.particles.length - 1; i >= 0; i--) {
        -      // If we shold remove it
        -      if (this.particles[i].lifespan <= 0) {
        -        this.particles.splice(i, 1);
        -      // Otherwise, display it
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               } else {
                 this.particles[i].display(this.particles[i+1]);
               }
        @@ -170,11 +100,7 @@ class Path {
           }  
         }
         
        -<<<<<<< HEAD
         // 경로 위 파티클들
        -=======
        -// Particles along the path
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         class Particle {
           constructor(position, force, hue) {
             this.position = createVector(position.x, position.y);
        @@ -192,22 +118,13 @@ class Particle {
             this.lifespan--;
           }
         
        -<<<<<<< HEAD
           // 파티클을 그리고 선으로 잇기
           // 다른 파티클을 향해 선그리기
        -=======
        -  // Draw particle and connect it with a line
        -  // Draw a line to another
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           display(other) {
             stroke(0, this.lifespan);
             fill(0, this.lifespan/2);    
             ellipse(this.position.x,this.position.y, 8, 8);    
        -<<<<<<< HEAD
             // 선을 그려야 한다면,
        -=======
        -    // If we need to draw a line
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (other) {
               line(this.position.x, this.position.y, other.position.x, other.position.y);
             }
        diff --git a/src/data/examples/ko/90_Hello_P5/07_song.js b/src/data/examples/ko/90_Hello_P5/07_song.js
        index 25a561f108..2c3bbd65ab 100644
        --- a/src/data/examples/ko/90_Hello_P5/07_song.js
        +++ b/src/data/examples/ko/90_Hello_P5/07_song.js
        @@ -1,5 +1,4 @@
         /*
        -<<<<<<< HEAD
          * @name 노래
          * @frame 720, 430
          * @description 노래를 재생하세요.
        @@ -10,20 +9,6 @@
         // MIDI 음계의 음표들
         let notes = [ 60, 62, 64, 65, 67, 69, 71];
         
        -// 노래를 자동 재생하기 위한 처리
        -=======
        - * @name Song
        - * @frame 720, 430
        - * @description Play a song.
        - * You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound
        - * library</a> for this example to work in your own project.
        - */
        -// The midi notes of a scale
        -let notes = [ 60, 62, 64, 65, 67, 69, 71];
        -
        -// For automatically playing the song
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         let index = 0;
         let song = [
           { note: 4, duration: 400, display: "D" },
        @@ -45,11 +30,7 @@ function setup() {
           div.id("instructions");
           let button = createButton("play song automatically.");
           button.parent("instructions");
        -<<<<<<< HEAD
           // 자동 재생 트리거하기
        -=======
        -  // Trigger automatically playing
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           button.mousePressed(function() {
             if (!autoplay) {
               index = 0;
        @@ -57,20 +38,13 @@ function setup() {
             }
           });
         
        -<<<<<<< HEAD
           // 삼각형 오실레이터
           osc = new p5.TriOsc();
           // 무음 시작
        -=======
        -  // A triangle oscillator
        -  osc = new p5.TriOsc();
        -  // Start silent
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           osc.start();
           osc.amp(0);
         }
         
        -<<<<<<< HEAD
         // 음표를 재생하기 위한 함수
         function playNote(note, duration) {
           osc.freq(midiToFreq(note));
        @@ -78,15 +52,6 @@ function playNote(note, duration) {
           osc.fade(0.5,0.2);
         
           // 만약 재생 시간을 설정한다면, 페이드 아웃
        -=======
        -// A function to play a note
        -function playNote(note, duration) {
        -  osc.freq(midiToFreq(note));
        -  // Fade it in
        -  osc.fade(0.5,0.2);
        -
        -  // If we sest a duration, fade it out
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           if (duration) {
             setTimeout(function() {
               osc.fade(0,0.2);
        @@ -96,7 +61,6 @@ function playNote(note, duration) {
         
         function draw() {
         
        -<<<<<<< HEAD
           // 만약 현재 자동 재생 중이고 다음 음표를 재생할 때가 되었다면,
           if (autoplay && millis() > trigger){
             playNote(notes[song[index].note], song[index].duration);
        @@ -104,22 +68,12 @@ function draw() {
             // 다음 음표로 이동하기
             index ++;
           // 끝에 다다랐다면, 자동 재생 중지
        -=======
        -  // If we are autoplaying and it's time for the next note
        -  if (autoplay && millis() > trigger){
        -    playNote(notes[song[index].note], song[index].duration);
        -    trigger = millis() + song[index].duration;
        -    // Move to the next note
        -    index ++;
        -  // We're at the end, stop autoplaying.
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           } else if (index >= song.length) {
             autoplay = false;
           }
         
         
        -<<<<<<< HEAD
        -  // 키보드 긜기
        +  // 키보드 그리기
         
           // 각 건반의 너비
           let w = width / notes.length;
        @@ -131,20 +85,6 @@ function draw() {
               if (mouseIsPressed) {
                 fill(100,255,200);
               // 또는 마우스가 건반 위를 롤오버 중이라면,
        -=======
        -  // Draw a keyboard
        -
        -  // The width for each key
        -  let w = width / notes.length;
        -  for (let i = 0; i < notes.length; i++) {
        -    let x = i * w;
        -    // If the mouse is over the key
        -    if (mouseX > x && mouseX < x + w && mouseY < height) {
        -      // If we're clicking
        -      if (mouseIsPressed) {
        -        fill(100,255,200);
        -      // Or just rolling over
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
               } else {
                 fill(127);
               }
        @@ -152,46 +92,27 @@ function draw() {
               fill(200);
             }
         
        -<<<<<<< HEAD
             // 또는, 노래가 재생 중이라면 하이라이트를 줍니다.  
        -=======
        -    // Or if we're playing the song, let's highlight it too
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             if (autoplay && i === song[index-1].note) {
               fill(100,255,200);
             }
         
        -<<<<<<< HEAD
             // 건반 그리기
        -=======
        -    // Draw the key
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             rect(x, 0, w-1, height-1);
           }
         
         }
         
        -<<<<<<< HEAD
         // 클릭하면,
         function mousePressed(event) {
           if(event.button == 0 && event.clientX < width && event.clientY < height) {
             // 건반 인덱스에 마우스를 매핑하기
        -=======
        -// When we click
        -function mousePressed(event) {
        -  if(event.button == 0 && event.clientX < width && event.clientY < height) {
        -    // Map mouse to the key index
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             let key = floor(map(mouseX, 0, width, 0, notes.length));
             playNote(notes[key]);
           }
         }
         
        -<<<<<<< HEAD
         // 마우스 버튼을 놓으면 페이드 아웃하기
        -=======
        -// Fade it out when we release
        ->>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         function mouseReleased() {
           osc.fade(0,0.5);
         }
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 8cfb93b9b6..4c3546c046 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -16,7 +16,7 @@ Contribute: "함께하기"
         Forum: "포럼"
         Showcase: "쇼케이스"
         
        -footerxh1: "Credits"
        +footerxh1: "크레딧"
         footer1: "p5.js는 로렌 맥카시 "
         footer2: " 가 창안하고 협력자 커뮤니티와 함께 개발하였습니다. 지원: 프로세싱 재단 "
         footer3: "과 "
        @@ -67,8 +67,8 @@ copyright:
           copyright-title: "저작권"
           copyright1: "p5.js 라이브러리는 무료 소프트웨어입니다."
           copyright2: " Free Software Foundation의 조항(version 2.1.)에 따라 재배포 및 수정할 수 있습니다."
        -  copyright3: "The Reference for the language is under a "
        -  copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited."
        +  copyright3: "p5.js의 레퍼런스는 "
        +  copyright4: " 라이선스에 속하며, 이 콘텐츠는 크레딧을 인용한다는 전제 하에 비영리 목적을 위해 재사용될 수 있습니다."
         
         get started:
           get-started-title: "시작하기"
        @@ -476,7 +476,7 @@ community:
           sharing-title: "공유하기"
           sharing1: "이 성명서는 "
           sharing2: "크리에이티브 커먼즈(CC) 라이선스"
        -  sharing3: "에 의해 라이선스를 부여받습니다. 출처와 함께 자유롭게 공유하고 응용하셔도 좋습니다."
        +  sharing3: "에 의해 라이선스를 부여받습니다. 출처를 명시하면 자유롭게 공유하고 응용하셔도 좋습니다."
         
           contribute-title: "함께하기"
           contribute1: "우리 커뮤니티는 다양한 방법으로 도움을 줄 수 있는 열정가 분들을 항시 찾고 있습니다. "
        @@ -615,7 +615,7 @@ examples:
           Math: "수학"
           Simulate: "시뮬레이션"
           Interaction: "인터랙션"
        -  Objects: "오브젝트"
        +  Objects: "객체"
           Lights: "라이트"
           Motion: "모션"
           Instance_Mode: "인스턴스 모드"
        @@ -628,7 +628,7 @@ examples:
           Advanced_Data: "고급 데이터"
           Sound: "사운드"
           Mobile: "모바일"
        -  Hello_P5: "Hello p5"
        +  Hello_P5: "안녕 p5"
         
         reference:
           Reference: "레퍼런스"
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 9e24eb2b20..f6e9e1ca95 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -59,23 +59,23 @@
           "Environment": "환경",  
           "DOM": "DOM", 
           "Rendering": "렌더링",  
        -  "Transform": "변형(Transform)", 
        +  "Transform": "변형", 
           "Data": "데이터",  
           "Dictionary": "사전(Dictionary)",  
           "Array Functions": "배열 기능",  
           "Conversion": "변환(Conversion)", 
        -  "String Functions": "문자열(String) 기능",  
        +  "String Functions": "문자열 기능",  
           "Events": "이벤트",  
           "Acceleration": "가속",  
           "Keyboard": "키보드",  
           "Mouse": "마우스", 
           "Touch": "터치", 
           "Image": "이미지",  
        -  "Loading & Displaying": "로딩 & 디스플레이", 
        +  "Loading & Displaying": "불러오기 & 보이기", 
           "Pixels": "픽셀",  
           "IO": "IO", 
        -  "Input": "입력(Input)", 
        -  "Output": "아웃풋", 
        +  "Input": "입력", 
        +  "Output": "출력", 
           "Table": "테이블", 
           "Time & Date": "날짜 & 시간",  
           "XML": "XML", 
        
        From c68de5c5fbf7deb5c9a6605a79eb82add7caa040 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Mon, 27 Apr 2020 09:58:54 +0900
        Subject: [PATCH 11/36] thrid push to Korean translation on examples
        
        ---
         .../ko/08_Math/19_parametricEquation.js       |  43 ++++++
         src/data/examples/ko/09_Simulate/18_Koch.js   | 141 ++++++++++++++++++
         .../examples/ko/09_Simulate/19_Bubblesort.js  |  66 ++++++++
         .../ko/09_Simulate/20_SteepingFeet.js         |  81 ++++++++++
         .../examples/ko/09_Simulate/21_Particle.js    |  68 +++++++++
         .../ko/10_Interaction/28_ArduinoSensor.js     |  38 +++++
         .../ko/10_Interaction/29_kaleidoscope.js      |  76 ++++++++++
         .../ko/11_Objects/05_Composite_Objects.js     |  98 ++++++++++++
         src/data/examples/ko/20_3D/05_ray_casting.js  | 100 +++++++++++++
         src/data/examples/ko/20_3D/08_basic_shader.js |  27 ++++
         .../ko/20_3D/09_shader_as_a_texture.js        |  68 +++++++++
         .../ko/20_3D/10_passing_shader_uniforms.js    |  34 +++++
         .../ko/20_3D/11_shader_using_webcam.js        |  37 +++++
         13 files changed, 877 insertions(+)
         create mode 100644 src/data/examples/ko/08_Math/19_parametricEquation.js
         create mode 100644 src/data/examples/ko/09_Simulate/18_Koch.js
         create mode 100644 src/data/examples/ko/09_Simulate/19_Bubblesort.js
         create mode 100644 src/data/examples/ko/09_Simulate/20_SteepingFeet.js
         create mode 100644 src/data/examples/ko/09_Simulate/21_Particle.js
         create mode 100644 src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
         create mode 100644 src/data/examples/ko/10_Interaction/29_kaleidoscope.js
         create mode 100644 src/data/examples/ko/11_Objects/05_Composite_Objects.js
         create mode 100644 src/data/examples/ko/20_3D/05_ray_casting.js
         create mode 100644 src/data/examples/ko/20_3D/08_basic_shader.js
         create mode 100644 src/data/examples/ko/20_3D/09_shader_as_a_texture.js
         create mode 100644 src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
         create mode 100644 src/data/examples/ko/20_3D/11_shader_using_webcam.js
        
        diff --git a/src/data/examples/ko/08_Math/19_parametricEquation.js b/src/data/examples/ko/08_Math/19_parametricEquation.js
        new file mode 100644
        index 0000000000..598c45ee3c
        --- /dev/null
        +++ b/src/data/examples/ko/08_Math/19_parametricEquation.js
        @@ -0,0 +1,43 @@
        +/*
        + * @name 매개변수 방정식
        + * @description 매겨번수 방정식은 x와 y 좌표값이 다른 문자로서 표기된 식을 말합니다.
        + * 이러한 문자를 매개변수라 부르며, 일반적으로 t 또는 θ로 표기됩니다.
        + * 알렉산더 밀러(Alexander Miller)의 유투브 채널로부터 영감을 얻었습니다.
        + */
        +
        +function setup(){
        +  createCanvas(720,400);
        +}
        +
        +// x와 y의 매개 변수는 일반적으로 세타(theta)를 뜻하는 't' 또는 그 기호(θ)로 표기됩니다.
        +let t = 0;
        +function draw(){
        +  background('#fff');
        +  translate(width/2,height/2);
        +  stroke('#0f0f0f');
        +  strokeWeight(1.5);
        +  //100개의 선 추가를 위한 반복문
        +  for(let i = 0;i<100;i++){
        +    line(x1(t+i),y1(t+i),x2(t+i)+20,y2(t+i)+20);
        +  }
        +  t+=0.15;
        +}
        +// 선의 초기 x 좌표값을 변경하는 함수 
        +function x1(t){
        +  return sin(t/10)*125+sin(t/20)*125+sin(t/30)*125;
        +}
        +
        +// 선의 초기 y 좌표값을 변경하는 함수
        +function y1(t){
        +  return cos(t/10)*125+cos(t/20)*125+cos(t/30)*125;
        +}
        +
        +// 선의 최종 x 좌표값을 변경하는 함수
        +function x2(t){
        +  return sin(t/15)*125+sin(t/25)*125+sin(t/35)*125;
        +}
        +
        +// 선의 최종 y 좌표값을 변경하는 함수
        +function y2(t){
        +  return cos(t/15)*125+cos(t/25)*125+cos(t/35)*125;
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/18_Koch.js b/src/data/examples/ko/09_Simulate/18_Koch.js
        new file mode 100644
        index 0000000000..cdac9067e5
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/18_Koch.js
        @@ -0,0 +1,141 @@
        +/*
        + * @name 코흐 곡선
        + * @description 간단한 코흐 곡선 즉, 눈송이형 프랙탈을 만듭니다.
        + * 각각의 재귀 단계는 순차적으로 그려집니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 제작
        + */
        +
        +let k;
        +
        +function setup() {
        +  createCanvas(710, 400);
        +  frameRate(1);  // 천천히 움직이기
        +  k = new KochFractal();
        +}
        +
        +function draw() {
        +  background(0);
        +  // 눈송이 그리기!
        +  k.render();
        +  // 반복하기
        +  k.nextLevel();
        +  // 5회를 초과하진 않습니다...
        +  if (k.getCount() > 5) {
        +    k.restart();
        +  }
        +}
        +
        +// 선 하나를 프랙탈로 표현해주는 클래스
        +// midp5.Vectors가 코크 알고리즘에 의거하여 선을 계산하는 메소드를 포함합니다.
        +
        +class KochLine {
        +  constructor(a,b) {
        +    // 두개의 p5.Vectors,
        +    // 시작은 "왼쪽" p5.Vector이고
        +    // 끝은 "오른쪽" p5.Vector입니다.
        +    this.start = a.copy();
        +    this.end = b.copy();
        +  }
        +
        +  display() {
        +    stroke(255);
        +    line(this.start.x, this.start.y, this.end.x, this.end.y);
        +  }
        +
        +  kochA() {
        +    return this.start.copy();
        +  }
        +
        +  // 쉽지요? 여기까지 전체 내용의 1/3을 진행했어요.
        +  kochB() {
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.div(3);
        +    v.add(this.start);
        +    return v;
        +  }
        +
        +  // 약간 복잡한데요, 이 p5의 위치를 알아내기 위해 약간의 삼각법을 사용합니다!
        +  kochC() {
        +    let a = this.start.copy(); // Start at the beginning
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.div(3);
        +    a.add(v);  // 점 B로 이동하기
        +    v.rotate(-PI/3); // 60도 회전하기
        +    a.add(v);  // 점 C로 이동하기
        +    return a;
        +  }
        +
        +  // 쉽지요? 여기까지 전체 내용의 2/3을 진행했어요.
        +  kochD() {
        +    let v = p5.Vector.sub(this.end, this.start);
        +    v.mult(2/3.0);
        +    v.add(this.start);
        +    return v;
        +  }
        +
        +  kochE() {
        +    return this.end.copy();
        +  }
        +}
        +
        +//눈송이 패턴을 갖는 선분들을 배열로 관리하는 클래스입니다.
        +class KochFractal {
        +  constructor() {
        +    this.start = createVector(0,height-20);   // 시작점 p5.Vector
        +    this.end = createVector(width,height-20); // 끝점 p5.Vector
        +    this.lines = [];                         // 모든 선분을 추적하는 배열
        +    this.count = 0;
        +    this.restart();
        +  }
        +
        +  nextLevel() {
        +    // 배열에 담긴 각각의 선분들에 대해
        +    // 4개의 선분들을 추가한, 새로운 배열을 만듭니다.
        +    this.lines = this.iterate(this.lines);
        +    this.count++;
        +  }
        +
        +  restart() {
        +    this.count = 0;      // 카운트 리셋하기
        +    this.lines = [];  // 배열 비우기
        +    this.lines.push(new KochLine(this.start,this.end));  // 초기 선분 더하기(하나의 끝점 p5.Vector에서 다른 p5.Vector로)
        +  }
        +
        +  getCount() {
        +    return this.count;
        +  }
        +
        +  // 이 부분도 쉽습니다. 모든 선들을 그리는 함수이지요.
        +  render() {
        +    for(let i = 0; i < this.lines.length; i++) {
        +      this.lines[i].display();
        +    }
        +  }
        +
        +  // This is where the **MAGIC** happens
        +  // Step 1: Create an empty arraylist
        +  // Step 2: For every line currently in the arraylist
        +  //   - calculate 4 line segments based on Koch algorithm
        +  //   - add all 4 line segments into the new arraylist
        +  // Step 3: Return the new arraylist and it becomes the list of line segments for the structure
        +
        +  // As we do this over and over again, each line gets broken into 4 lines, which gets broken into 4 lines, and so on. . .
        +  iterate(before) {
        +    let now = [];    // Create emtpy list
        +    for(let i = 0; i < this.lines.length; i++) {
        +      let l = this.lines[i];
        +      // Calculate 5 koch p5.Vectors (done for us by the line object)
        +      let a = l.kochA();
        +      let b = l.kochB();
        +      let c = l.kochC();
        +      let d = l.kochD();
        +      let e = l.kochE();
        +      // Make line segments between all the p5.Vectors and add them
        +      now.push(new KochLine(a,b));
        +      now.push(new KochLine(b,c));
        +      now.push(new KochLine(c,d));
        +      now.push(new KochLine(d,e));
        +    }
        +    return now;
        +  }
        +}
        diff --git a/src/data/examples/ko/09_Simulate/19_Bubblesort.js b/src/data/examples/ko/09_Simulate/19_Bubblesort.js
        new file mode 100644
        index 0000000000..bff2f5a7bf
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/19_Bubblesort.js
        @@ -0,0 +1,66 @@
        +/*
        + * @name 버블 정렬
        + * @description 전체 정렬 과정을 시뮬레이션하면서,
        + * 무작위로 분포된 막대들을 그 높이에 따라 오름차순으로 정렬합니다.
        + * 코딩 트레인(Coding Train)의 코딩 챌린지(Coding Challenge)를 참조하였습니다.
        + */
        +
        +let values = [];
        +let i = 0;
        +let j = 0;
        +
        +// setup() 함수 속 명령문들은
        +// 프로그램 시작시 한 번 실행됩니다.
        +// 배열은 setup()함수를 통해 임의의 값들로 채워집니다.
        +function setup() {
        +  createCanvas(720, 400);
        +  for(let i = 0;i<width/8;i++){
        +    values.push(random(height));
        +  }
        +}
        +
        +// draw() 함수 속 명령문들은 
        +// 프로그램이 멈출 때까지 실행됩니다.
        +// 각 명령문은 순차적으로 실행되며,
        +// 마지막 명령문 실행한 후에는 첫 명령문으로 돌아가 실행합니다.
        +function draw() {
        +  background(220);
        +  bubbleSort();
        +  simulateSorting();
        +}
        +
        +// bubbleSort() 함수는 매 프레임마다
        +// 8개의 배열 요소를 가져옵니다.
        +// 이 함수가 사용하는 알고리즘은 버블 정렬입니다.
        +function bubbleSort() {
        +  for(let k = 0;k<8;k++){
        +    if(i<values.length){
        +      let temp = values[j];
        +      if(values[j] > values[j+1]){
        +        values[j] = values[j+1];
        +        values[j+1] = temp;
        +      }
        +      j++;
        +      
        +      if(j>=values.length-i-1){
        +        j = 0;
        +        i++;
        +      }
        +    }
        +    else{
        +      noLoop();
        +    }
        +  }
        +}
        +
        +// simulateSorting() 함수는 버블 정렬 알고리즘에
        +// 애니메이션을 적용합니다.
        +// 이 함수는 배열의 값을 사각형 길이로 치환해
        +// 사각형을 그립니다.
        +function simulateSorting(){
        +  for(let i = 0;i<values.length;i++){
        +    stroke(100, 143, 143);
        +     fill(50);
        +     rect(i*8 , height, 8, -values[i],20);
        +   }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/20_SteepingFeet.js b/src/data/examples/ko/09_Simulate/20_SteepingFeet.js
        new file mode 100644
        index 0000000000..a2c017f424
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/20_SteepingFeet.js
        @@ -0,0 +1,81 @@
        +/*
        + * @name 스테핑 피트 일루전
        + * @description 스테핑 피트 이루전(Stepping feet illusion)은 저명한
        + * 심리학 실험입니다.
        + * 두 사각형은 동일한 속도로 움직이나,
        + * 마치 다른 속도로 움직이는 것처럼 보입니다.
        + * 캔버스를 마우스로 클릭해 두 사각형이 동일한 속도로
        + * 이동하는지 확인해보세요.
        + * 사가 아로라(Sagar Arora) 기여.
        + */
        +
        +// 이 클래스는 전체 구조와 사각형의 움직임을
        +// 표현합니다.
        +class Brick{
        +  constructor(bc, y){
        +    this.brickColor = bc;
        +    this.yPos = y;
        +    this.xPos = 0;
        +  }
        +
        +  // 이 함수는 사각형을 생성합니다.
        +  createBrick(){
        +    fill(this.brickColor);
        +    rect(this.xPos, this.yPos, 100, 50);
        +  }
        +
        +  // 이 함수는 사각형의 움직임을 1로
        +  // 설정합니다. 
        +  setSpeed(){
        +    this.xSpeed = 1;
        +  }
        +
        +  // 이 함수는 사각형을 움직입니다.
        +  moveBrick(){
        +    this.xPos+=this.xSpeed;
        +    if(this.xPos+100 >= width || this.xPos <= 0){
        +      this.xSpeed*=-1;
        +    }
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  createP("Keep the mouse clicked").style('color','#ffffff');
        +  createP("to check whether the bricks").style('color','#ffffff');
        +  createP("are moving at same speed or not").style('color','#ffffff');
        +}
        +
        +// 두 개의 사각형을 각각
        +// 흰색과 검정색으로 지정합니다.
        +let brick1 = new Brick("white",100);
        +let brick2 = new Brick("black",250);
        +
        +//
        +brick1.setSpeed();
        +brick2.setSpeed();
        +
        +function draw () {
        +  background(0);
        +  if(mouseIsPressed){
        +    background(50);
        +  }
        +  brick1.createBrick();
        +  brick1.moveBrick();
        +  if(!mouseIsPressed){
        +    createBars();
        +  }
        +  brick2.createBrick();
        +  brick2.moveBrick();
        +}
        +
        +// 이 함수는 화면에
        +// 검정색 및 흰색 막대기들을 생성합니다.
        +function createBars() {
        +  let len = 12;
        +  for(let i = 0;i<width/len;i++){
        +    fill("white");
        +    if(i%2 == 0)
        +    rect(i*len,height,len,-height);
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/21_Particle.js b/src/data/examples/ko/09_Simulate/21_Particle.js
        new file mode 100644
        index 0000000000..8b953d7235
        --- /dev/null
        +++ b/src/data/examples/ko/09_Simulate/21_Particle.js
        @@ -0,0 +1,68 @@
        +/*
        + * @name 파티클
        + * @description particle.js는 가벼운 자바스크립트 라이브러리로,
        + * 매우 아름다운 파티클 시스템을 만듭니다.
        + * 이 예제는 p5.js를 사용하여 particle.js의 파티클 시스템을 재현합니다.
        + * 사가 아로라(Sagar Arora)가 기여하고, Particle.js로부터 영감을 얻었습니다.
        + */
        +
        +
        +// 이 클래스는 각 파티클의 속성들을 표현합니다.
        +class Particle {
        +// 파티클의 좌표값, 반경, 그리고 속도를
        +// 두 좌표축에 의거하여 설정합니다.
        +  constructor(){
        +    this.x = random(0,width);
        +    this.y = random(0,height);
        +    this.r = random(1,8);
        +    this.xSpeed = random(-2,2);
        +    this.ySpeed = random(-1,1.5);
        +  }
        +
        +// 파티클 생성하기
        +  createParticle() {
        +    noStroke();
        +    fill('rgba(200,169,169,0.5)');
        +    circle(this.x,this.y,this.r);
        +  }
        +
        +// 파티클이 움직이도록 설정하기
        +  moveParticle() {
        +    if(this.x < 0 || this.x > width)
        +      this.xSpeed*=-1;
        +    if(this.y < 0 || this.y > height)
        +      this.ySpeed*=-1;
        +    this.x+=this.xSpeed;
        +    this.y+=this.ySpeed;
        +  }
        +
        +// 이 함수는 특정 거리 안쪽에 위치한 파티클들 사이에 연결선을 만듭니다.
        +  joinParticles(paraticles) {
        +    particles.forEach(element =>{
        +      let dis = dist(this.x,this.y,element.x,element.y);
        +      if(dis<85) {
        +        stroke('rgba(255,255,255,0.04)');
        +        line(this.x,this.y,element.x,element.y);
        +      }
        +    });
        +  }
        +}
        +
        +// 복수의 파티클들을 추가하기 위한 배열
        +let particles = [];
        +
        +function setup() {
        +  createCanvas(720, 400);
        +  for(let i = 0;i<width/10;i++){
        +    particles.push(new Particle());
        +  }
        +}
        +
        +function draw() {
        +  background('#0f0f0f');
        +  for(let i = 0;i<particles.length;i++) {
        +    particles[i].createParticle();
        +    particles[i].moveParticle();
        +    particles[i].joinParticles(particles.slice(i));
        +  }
        +}
        \ No newline at end of file
        diff --git a/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js b/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
        new file mode 100644
        index 0000000000..e801838d69
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/28_ArduinoSensor.js
        @@ -0,0 +1,38 @@
        +/*
        + * @name WebJack과 아두이노 센서 데이터
        + * @description 웹잭(WebJack)은 오디오를 사용하여 아두이노와
        + * 다른 소스들로부터 데이터를 읽어오는 한 방식입니다.
        + * 기본적으로, 아두이노를 오디오 모뎀으로 변환합니다.
        + * 
        + * https://github.com/publiclab/webjack
        + * 
        + * 주의: 이 예제를 로컬 프로젝트에서 실행하려면, index.html 파일에 WebJack과 p5-webjack 라이브러리를 다음과같이 추가해야 합니다:
        + * <pre><code class="language-markup">&lt;script src="https://webjack.io/dist/webjack.js">&lt;/script></code></pre>
        + * <pre><code class="language-markup">&lt;script src="https://jywarren.github.io/p5-webjack/lib.js">&lt;/script></code></pre>
        + * 
        + * 작동 예시: https://editor.p5js.org/jywarren/sketches/rkztwSt8M
        + * 
        + * 오디오 테스팅: https://www.youtube.com/watch?v=GtJW1Dlt3cg
        + * 이 스케치를 아두이노로 불러오세요: 
        + * https://create.arduino.cc/editor/jywarren/023158d8-be51-4c78-99ff-36c63126b554/preview
        + * 아두이노가 pin 3 + ground로부터 오디오를 출력할 것입니다. 마이크나 오디오 케이블을 사용하세요.
        + */
        +
        +function setup() { 
        +  createCanvas(400, 400);
        +  noStroke();
        +  fill('#ff00aa22');
        +  receiveSensorData(handleData);
        +}
        +
        +function handleData(data, connection) {
        +
        +  console.log(data); // 값을 로그에 출력
        +  // data[0] = 첫번째 값, data[1] = 두번째 값 ...
        +
        +  // 그려보세요! 참고: http://p5js.org/reference/
        +  background('#ddd');
        +  ellipse(100, 200, data[0]+10, data[0]+10);
        +
        +  // connection.send('아두이노가 오디오리스닝 중이라면 아두이노로 데이터를 다시 전송하기');
        +}
        diff --git a/src/data/examples/ko/10_Interaction/29_kaleidoscope.js b/src/data/examples/ko/10_Interaction/29_kaleidoscope.js
        new file mode 100644
        index 0000000000..56b1b24cb7
        --- /dev/null
        +++ b/src/data/examples/ko/10_Interaction/29_kaleidoscope.js
        @@ -0,0 +1,76 @@
        +/*
        + * @name 만화경
        + * @description
        +436/5000
        +만화경은 두 개 이상의 반사면이 서로를 향해 비스듬히 기울어진 광학 기기를 말합니다.
        +이 예제는 만화경의 작동 원리를 복제하고 재현합니다. "대칭(symmetry)" 변수를 통해 반사 횟수를 조정하고 화면 위에 그림을 그려보세요.
        +슬라이더를 사용하여 브러시 크기를 조정할 수 있습니다. "clearButton"은 화면을 지웁니다. "saveButton" 버튼은 사용자가 만든 작품을 .jpg 파일로 다운로드합니다.
        +*/
        +// 반사 횟수에 따른 대칭을 설정합니다. 반사 횟수를 조정해보세요.
        +let symmetry = 6;   
        +
        +let angle = 360 / symmetry;
        +let saveButton, clearButton, mouseButton, keyboardButton;
        +let slider;
        +
        +function setup() { 
        +  createCanvas(710, 710);
        +  angleMode(DEGREES);
        +  background(127);
        +
        +  // 파일 저장을 위한 saveButton 생성하기
        +  saveButton = createButton('save');
        +  saveButton.mousePressed(saveFile);
        +
        +  // 화면 지우기를 위한 claerButton 생성하기
        +  clearButton = createButton('clear');
        +  clearButton.mousePressed(clearScreen);
        +
        +  // 전체 화면 보기를 위한 fullscreenButton 생성하기
        +  fullscreenButton = createButton('Full Screen');
        +  fullscreenButton.mousePressed(screenFull);
        +
        +  // 브러시 두께 조정을 위한 슬라이더 설정하기
        +  brushSizeSlider = createButton('Brush Size Slider');
        +  sizeSlider = createSlider(1, 32, 4, 0.1);
        +}
        +
        +// 파일 저장 함수
        +function saveFile() {
        +  save('design.jpg');
        +}
        +
        +// 화면 지우기 함수
        +function clearScreen() {
        +  background(127);
        +}
        +
        +// 전체 화면 보기 함수
        +function screenFull() {
        +  let fs = fullscreen();
        +  fullscreen(!fs);
        +}
        +
        +function draw() {
        +  translate(width / 2, height / 2);
        +
        +  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
        +    let mx = mouseX - width / 2;
        +    let my = mouseY - height / 2;
        +    let pmx = pmouseX - width / 2;
        +    let pmy = pmouseY - height / 2;
        +    
        +    if (mouseIsPressed) {
        +      for (let i = 0; i < symmetry; i++) {
        +        rotate(angle);
        +        let sw = sizeSlider.value();
        +        strokeWeight(sw);
        +        line(mx, my, pmx, pmy);
        +        push();
        +        scale(1, -1);
        +        line(mx, my, pmx, pmy);
        +        pop();
        +      }
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/11_Objects/05_Composite_Objects.js b/src/data/examples/ko/11_Objects/05_Composite_Objects.js
        new file mode 100644
        index 0000000000..af575305a8
        --- /dev/null
        +++ b/src/data/examples/ko/11_Objects/05_Composite_Objects.js
        @@ -0,0 +1,98 @@
        +/* @name 합성 객체
        + * @description 한 객체는 여러 개의 다른 객체들을 포함할 수 있습니다.
        + * 합성 객체를 생성하면 모듈화 원칙들을 활용하거나, 또 높은 수준의 추상을 구축하기에 좋습니다.
        + */
        +let er1, er2;
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  er1 = new EggRing(width*0.45, height*0.5, 0.1, 120);
        +  er2 = new EggRing(width*0.65, height*0.8, 0.05, 180);
        +}
        +
        +function draw() {
        +  background(0);
        +  er1.transmit();
        +  er2.transmit();
        +}
        +
        +class Egg {
        +  constructor(xpos, ypos, t, s) {
        +    this.x = xpos;
        +    this.y = ypos;
        +    this.tilt = t;
        +    this.scalar = s / 100.0;
        +    this.angle = 0.0;
        +  }
        +
        +  wobble() {
        +    this.tilt = cos(this.angle) / 8;
        +    this.angle += 0.1;
        +  }
        +
        +  display() {
        +    noStroke();
        +    fill(255);
        +    push();
        +    translate(this.x, this.y);
        +    rotate(this.tilt);
        +    scale(this.scalar);
        +    beginShape();
        +    vertex(0, -100);
        +    bezierVertex(25, -100, 40, -65, 40, -40);
        +    bezierVertex(40, -15, 25, 0, 0, 0);
        +    bezierVertex(-25, 0, -40, -15, -40, -40);
        +    bezierVertex(-40, -65, -25, -100, 0, -100);
        +    endShape();
        +    pop();
        +  }
        +}
        +
        +class Ring {
        +  start(xpos, ypos) {
        +    this.x = xpos;
        +    this.y = ypos;
        +    this.on = true;
        +    this.diameter = 1;
        +  }
        +
        +  grow() {
        +    if (this.on == true) {
        +      this.diameter += 0.5;
        +      if (this.diameter > width*2) {
        +        this.diameter = 0.0;
        +      }
        +    }
        +  }
        +
        +  display() {
        +    if (this.on == true) {
        +      noFill();
        +      strokeWeight(4);
        +      stroke(155, 153);
        +      ellipse(this.x, this.y, this.diameter, this.diameter);
        +    }
        +  }
        +}
        +
        +class EggRing {
        +  constructor(x, y, t, sp) {
        +    this.x = x;
        +    this.y = y;
        +    this.t = t;
        +    this.sp = sp;
        +    this.circle = new Ring();
        +    this.ovoid = new Egg(this.x, this.y, this.t, this.sp);
        +    this.circle.start(this.x, this.y - this.sp/2);
        +  }
        +
        +  transmit() {
        +    this.ovoid.wobble();
        +    this.ovoid.display();
        +    this.circle.grow();
        +    this.circle.display();
        +    if (circle.on == false) {
        +      circle.on = true;
        +    }
        +  }
        +}
        diff --git a/src/data/examples/ko/20_3D/05_ray_casting.js b/src/data/examples/ko/20_3D/05_ray_casting.js
        new file mode 100644
        index 0000000000..ac4fc40e06
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/05_ray_casting.js
        @@ -0,0 +1,100 @@
        +/*
        + * @name 레이 캐스팅
        + * @description 예제 원본: 조나단 왓슨(Jonathan Watson) 제작
        + * <br><br>광선 투사(ray casting) 기능으로 3D 공간 속 마우스의 위치를 감지합니다.
        + */
        +const objects = [];
        +let eyeZ;
        +
        +function setup() {
        +  createCanvas(710, 400, WEBGL);
        +
        +  eyeZ = height / 2 / tan((30 * PI) / 180); // 카메라가 원점에서 떨어진 기본 위치
        +
        +  objects.push(new IntersectPlane(1, 0, 0, -100, 0, 0)); // 왼쪽 벽
        +  objects.push(new IntersectPlane(1, 0, 0, 100, 0, 0)); // 오른쪽 벽
        +  objects.push(new IntersectPlane(0, 1, 0, 0, -100, 0)); // 바닥
        +  objects.push(new IntersectPlane(0, 1, 0, 0, 100, 0)); // 천장
        +  objects.push(new IntersectPlane(0, 0, 1, 0, 0, 0)); // 뒷면 벽
        +
        +  noStroke();
        +  ambientMaterial(250);
        +}
        +
        +function draw() {
        +  background(0);
        +
        +  // 조명들
        +  pointLight(255, 255, 255, 0, 0, 400);
        +  ambientLight(244, 122, 158);
        +
        +  // 왼쪽 벽
        +  push();
        +  translate(-100, 0, 200);
        +  rotateY((90 * PI) / 180);
        +  plane(400, 200);
        +  pop();
        +
        +  // 오른쪽 벽
        +  push();
        +  translate(100, 0, 200);
        +  rotateY((90 * PI) / 180);
        +  plane(400, 200);
        +  pop();
        +
        +  // 바닥
        +  push();
        +  translate(0, 100, 200);
        +  rotateX((90 * PI) / 180);
        +  plane(200, 400);
        +  pop();
        +
        +  // 천장
        +  push();
        +  translate(0, -100, 200);
        +  rotateX((90 * PI) / 180);
        +  plane(200, 400);
        +  pop();
        +
        +  plane(200, 200); // 뒷면 벽
        +
        +  const x = mouseX - width / 2;
        +  const y = mouseY - height / 2;
        +
        +  const Q = createVector(0, 0, eyeZ); // 광선 위의 점과 카메라의 기본 위치
        +  const v = createVector(x, y, -eyeZ); // 광선의 방향 벡터
        +
        +  let intersect; // 광선과 벽면의 교차점
        +  let closestLambda = eyeZ * 10; // 거리 그리기
        +
        +  for (let x = 0; x < objects.length; x += 1) {
        +    let object = objects[x];
        +    let lambda = object.getLambda(Q, v); // 광선과 객체 간 교차점의  람다값
        +
        +    if (lambda < closestLambda && lambda > 0) {
        +      // 광선과 객체의 교차점 위치 찾기
        +      intersect = p5.Vector.add(Q, p5.Vector.mult(v, lambda));
        +      closestLambda = lambda;
        +    }
        +  }
        +
        +  // 커서
        +  push();
        +  translate(intersect);
        +  fill(237, 34, 93);
        +  sphere(10);
        +  pop();
        +}
        +
        +// 무한대로 확장하는 벽면 생성을 위한 클래스
        +class IntersectPlane {
        +  constructor(n1, n2, n3, p1, p2, p3) {
        +    this.normal = createVector(n1, n2, n3); // 면의 기본 벡터
        +    this.point = createVector(p1, p2, p3); // 면 위의 점
        +    this.d = this.point.dot(this.normal);
        +  }
        +
        +  getLambda(Q, v) {
        +    return (-this.d - this.normal.dot(Q)) / this.normal.dot(v);
        +  }
        +}
        diff --git a/src/data/examples/ko/20_3D/08_basic_shader.js b/src/data/examples/ko/20_3D/08_basic_shader.js
        new file mode 100644
        index 0000000000..f335a266f8
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/08_basic_shader.js
        @@ -0,0 +1,27 @@
        +/*
        + * @name 셰이더 기초
        + * @description p5.js에 셰이더를 불러오는 방법을 설명하는 기본 예제입니다. 
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        +// 이 변수는 셰이더 객체를 담습니다.
        +let theShader;
        +
        +function preload(){
        +  // 셰이더 불러오기
        +  theShader = loadShader('assets/basic.vert', 'assets/basic.frag');
        +}
        +
        +function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +  createCanvas(710, 400, WEBGL);
        +  noStroke();
        +}
        +
        +function draw() {
        +  // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +  shader(theShader);
        +
        +  // rect()함수로 화면에 기하 추가하기
        +  rect(0,0,width, height);
        +}
        diff --git a/src/data/examples/ko/20_3D/09_shader_as_a_texture.js b/src/data/examples/ko/20_3D/09_shader_as_a_texture.js
        new file mode 100644
        index 0000000000..3e12f552c7
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/09_shader_as_a_texture.js
        @@ -0,0 +1,68 @@
        +/*
        + * @name 셰이더로 텍스처 만들기
        + * @description 셰이더는 2D/3D 도형에 텍스처로서 적용될 수 있습니다.
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        + // 이 변수는 createGraphics 레이어를 담습니다.
        + let shaderTexture;
        +
        + let theta = 0;
        +
        + let x;
        + let y;
        + let outsideRadius = 200;
        + let insideRadius = 100;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/texture.vert','assets/texture.frag');
        + }
        +
        + function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        +
        +   // createGraphics 레이어 초기화하기
        +   shaderTexture = createGraphics(710, 400, WEBGL);
        +
        +   // createGraphics 레이어의 테두리 없애기
        +   shaderTexture.noStroke();
        +
        +    x = -50;
        +    y = 0;
        + }
        +
        + function draw() {
        +
        +   // theShader를 활성화 셰이더로 설정하는 대신, createGraphics 레이어로 보냅니다.
        +   shaderTexture.shader(theShader);
        +
        +   // setUniform()를 사용하여 유니폼을 theShader로 보냅니다.
        +   theShader.setUniform("resolution", [width, height]);
        +   theShader.setUniform("time", millis() / 1000.0);
        +   theShader.setUniform("mouse", [mouseX, map(mouseY, 0, height, height, 0)]);
        +
        +   // shaderTexture 레이어 위 기하 형상의 렌더링을 위한 설정
        +   shaderTexture.rect(0,0,width,height);
        +
        +   background(255);
        +
        +   // 셰이더를 텍스쳐로서 설정하기
        +   texture(shaderTexture);
        +
        +   translate(-150, 0, 0);
        +   push();
        +   rotateZ(theta * mouseX * 0.0001);
        +   rotateX(theta * mouseX * 0.0001);
        +   rotateY(theta * mouseX * 0.0001);
        +   theta += 0.05;
        +   sphere(125);
        +   pop();
        +
        +   // 5번째 매개변수를 3D 상의 부드러운 모서리 처리를 위한 값으로 보내기
        +   ellipse(260,0,200,200,100);
        + }
        diff --git a/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js b/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
        new file mode 100644
        index 0000000000..3b274aef49
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/10_passing_shader_uniforms.js
        @@ -0,0 +1,34 @@
        +/*
        + * @name 셰이더 유니폼
        + * @description 유니폼(Uniform)을 통해 p5에서 셰이더로 정보를 전송합니다.
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/uniforms.vert', 'assets/uniforms.frag');
        + }
        +
        + function setup() {
        +  // 셰이더를 작동하기 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        + }
        +
        + function draw() {
        +   // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +   shader(theShader);
        +
        +   // 마우스 + 데이터 수정 시간을 보내기에 앞서,
        +   // 해상도, 마우스, 시간을 셰이더에 보냅니다.
        +   // 이렇게 하면 셰이더에서 사용하기가 더 쉬워집니다.
        +   theShader.setUniform('resolution', [width, height]);
        +   theShader.setUniform('mouse', map(mouseX, 0, width, 0, 7));
        +   theShader.setUniform('time', frameCount * 0.01);
        +
        +  // rect()함수로 화면에 기하 형상 추가하기
        +   rect(0,0,width, height);
        + }
        diff --git a/src/data/examples/ko/20_3D/11_shader_using_webcam.js b/src/data/examples/ko/20_3D/11_shader_using_webcam.js
        new file mode 100644
        index 0000000000..0763b93fac
        --- /dev/null
        +++ b/src/data/examples/ko/20_3D/11_shader_using_webcam.js
        @@ -0,0 +1,37 @@
        +/*
        + * @name 웹캠을 사용한 셰이더
        + * @description 웹캠을 텍스처로서 셰이더에 보낼 수 있습니다. 
        + * <br> p5.js로 셰이더를 사용하는 방법에 대해 더 알고 싶다면: <a href="https://itp-xstory.github.io/p5js-shaders/">p5.js Shaders</a>
        + */
        +
        + // 이 변수는 셰이더 객체를 담습니다.
        + let theShader;
        + // 이 변수는 웹캠 비디오를 담습니다.
        + let cam;
        +
        + function preload(){
        +   // 셰이더 불러오기
        +   theShader = loadShader('assets/webcam.vert', 'assets/webcam.frag');
        + }
        +
        + function setup() {
        +  // 셰이더 작동을 위해 WEBGL 모드가 필요합니다.
        +   createCanvas(710, 400, WEBGL);
        +   noStroke();
        +
        +   cam = createCapture(VIDEO);
        +   cam.size(710, 400);
        +
        +   cam.hide();
        + }
        +
        + function draw() {
        +   // shader()는 활성화 셰이더를 theShader로 설정합니다.
        +   shader(theShader);
        +
        +   // cam을 텍스처로 보내기
        +   theShader.setUniform('tex0', cam);
        +
        +  // rect()함수로 화면에 기하 추가하기
        +   rect(0,0,width,height);
        + }
        
        From 9d7b3cc9fce50f6e6a71953acd05eea4b0ee0f21 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Mon, 27 Apr 2020 10:06:31 +0900
        Subject: [PATCH 12/36] update in Korean branch
        
        ---
         Gruntfile.js                                  |    1 +
         contributor_docs/i18n_contribution.md         |    3 +-
         i18n-tracking.yml                             | 1387 +++++------------
         offline-reference/extra/css/main.css          |    1 +
         offline-reference/extra/index.html            |    1 -
         offline-reference/extra/js/reference.js       |   13 +-
         package-lock.json                             |  135 +-
         src/assets/css/main.css                       |   94 +-
         src/assets/img/books/generative_design.jpg    |  Bin 0 -> 138449 bytes
         .../img/books/generative_gestaltung.jpg       |  Bin 0 -> 88666 bytes
         src/assets/img/books/learn_javascript.jpg     |  Bin 0 -> 55524 bytes
         src/assets/js/render.js                       |   13 +-
         src/assets/learn/curves/bezier/embed.html     |    1 -
         src/assets/learn/curves/curve_ex/embed.html   |    1 -
         .../trigonometry/sincoscurves/embed.html      |    1 -
         .../trigonometry/sincoscurves/embed1.html     |    1 -
         .../learn/trigonometry/unitCircle/embed.html  |    1 -
         .../p5_featured/Tai_PursuingRelief/sketch.js  |  523 -------
         src/data/en.yml                               |   52 +-
         src/data/es.yml                               |   55 +-
         src/data/examples/assets/bubbles.csv          |    5 +
         .../examples/en/16_Dom/03_Input_Button.js     |    5 +-
         src/data/examples/en/16_Dom/04_Slider.js      |    5 +-
         src/data/examples/en/16_Dom/07_Modify_DOM.js  |    6 +-
         src/data/examples/en/16_Dom/08_Video.js       |    5 +-
         .../examples/en/16_Dom/09_Video_Canvas.js     |    7 +-
         .../examples/en/16_Dom/10_Video_Pixels.js     |    7 +-
         src/data/examples/en/16_Dom/11_Capture.js     |    5 +-
         src/data/examples/en/16_Dom/12_Drop.js        |    5 +-
         .../22_Advanced_Data/01_Load_Saved_Table.js   |  110 ++
         .../en/90_Hello_P5/02_interactivity.js        |    3 -
         .../en/90_Hello_P5/03_interactivity.js        |    3 -
         .../examples/en/90_Hello_P5/05_weather.js     |    3 -
         .../examples/es/08_Math/10_Interpolate.js     |   22 +-
         src/data/examples/es/08_Math/15_Noise2D.js    |   14 +-
         src/data/examples/es/08_Math/16_Noise3D.js    |   24 +-
         .../examples/es/08_Math/17_Randomchords.js    |   18 +-
         src/data/examples/es/08_Math/18_Map.js        |   16 +-
         .../es/08_Math/19_parametricEquation.js       |   25 +-
         .../examples/es/09_Simulate/09_Springs.js     |   12 +-
         .../es/09_Simulate/11_SmokeParticleSystem.js  |    2 +-
         .../09_Simulate/14_SnowflakeParticleSystem.js |    8 +-
         .../es/09_Simulate/15_penrose_tiles.js        |    6 +-
         .../es/09_Simulate/16_Recursive_Tree.js       |   10 +-
         src/data/examples/es/09_Simulate/18_Koch.js   |    6 +-
         .../examples/es/09_Simulate/19_Bubblesort.js  |   16 +-
         .../es/09_Simulate/20_SteepingFeet.js         |   18 +-
         .../examples/es/09_Simulate/21_Particle.js    |   12 +-
         .../examples/es/16_Dom/03_Input_Button.js     |    5 +-
         src/data/examples/es/16_Dom/04_Slider.js      |    5 +-
         src/data/examples/es/16_Dom/07_Modify_DOM.js  |    5 +-
         src/data/examples/es/16_Dom/08_Video.js       |    5 +-
         .../examples/es/16_Dom/09_Video_Canvas.js     |    7 +-
         .../examples/es/16_Dom/10_Video_Pixels.js     |    7 +-
         src/data/examples/es/16_Dom/11_Capture.js     |    6 +-
         src/data/examples/es/16_Dom/12_Drop.js        |    5 +-
         .../22_Advanced_Data/01_Load_Saved_Table.js   |  110 ++
         .../es/90_Hello_P5/02_interactivity.js        |    3 -
         .../es/90_Hello_P5/03_interactivity.js        |    2 -
         .../examples/es/90_Hello_P5/05_weather.js     |    3 -
         .../ko/00_Structure/00_Coordinates.js         |   35 +-
         .../ko/00_Structure/01_Width_and_Height.js    |    7 +-
         .../ko/00_Structure/02_Setup_and_Draw.js      |   22 +-
         .../examples/ko/00_Structure/03_No_Loop.js    |   22 +-
         src/data/examples/ko/00_Structure/04_Loop.js  |   22 +-
         .../examples/ko/00_Structure/05_Redraw.js     |   16 +-
         .../examples/ko/00_Structure/06_Functions.js  |    7 +-
         .../examples/ko/00_Structure/07_Recursion.js  |    8 +-
         .../ko/00_Structure/08_Create_Graphics.js     |   10 +-
         .../ko/01_Form/00_Points_and_Lines.js         |   14 +-
         .../ko/01_Form/01_Shape_Primitives.js         |   11 +
         src/data/examples/ko/01_Form/02_Pie_Chart.js  |    7 +-
         .../examples/ko/01_Form/03_Regular_Polygon.js |    9 +-
         src/data/examples/ko/01_Form/04_Star.js       |    7 +-
         .../examples/ko/01_Form/05_Triangle_Strip.js  |    8 +-
         src/data/examples/ko/01_Form/06_Bezier.js     |    8 +-
         .../examples/ko/01_Form/07_3D_Primitives.js   |    8 +-
         src/data/examples/ko/02_Data/00_Variables.js  |    5 +-
         .../examples/ko/02_Data/01_True_and_False.js  |   15 +-
         .../examples/ko/02_Data/03_Variable_Scope.js  |   33 +-
         src/data/examples/ko/02_Data/04_Numbers.js    |   17 +-
         src/data/examples/ko/03_Arrays/00_Array.js    |   14 +-
         src/data/examples/ko/03_Arrays/01_Array_2d.js |   21 +-
         .../examples/ko/03_Arrays/02_Array_Objects.js |    8 +-
         .../examples/ko/04_Control/00_Iteration.js    |   10 +-
         .../ko/04_Control/01_Embedded_Iteration.js    |    4 +-
         .../ko/04_Control/02_Conditionals_1.js        |   18 +-
         .../ko/04_Control/03_Conditionals_2.js        |   17 +-
         .../ko/04_Control/04_Logical_Operators.js     |   20 +-
         .../ko/05_Image/00_Load_and_Display_Image.js  |   19 +-
         .../ko/05_Image/01_Background_Image.js        |   19 +-
         .../examples/ko/05_Image/02_Transparency.js   |   18 +-
         .../examples/ko/05_Image/03_Alpha_Mask.js     |   12 +-
         .../examples/ko/05_Image/04_Create_Image.js   |    8 +-
         .../examples/ko/05_Image/05_Pointillism.js    |   12 +-
         src/data/examples/ko/07_Color/00_Hue.js       |    8 +-
         .../examples/ko/07_Color/01_Saturation.js     |    9 +-
         .../examples/ko/07_Color/02_Brightness.js     |   20 +-
         .../ko/07_Color/03_Color_Variables.js         |   10 +-
         .../examples/ko/07_Color/04_Relativity.js     |   10 +-
         .../ko/07_Color/05_Linear_Gradient.js         |   17 +-
         .../ko/07_Color/06_Radial_Gradient.js         |    5 +
         .../examples/ko/07_Color/07_Lerp_Color.js     |    6 +-
         .../ko/08_Math/00_incrementdecrement.js       |    6 +-
         .../ko/08_Math/01_operatorprecedence.js       |   53 +-
         src/data/examples/ko/08_Math/02_distance1d.js |    5 +-
         src/data/examples/ko/08_Math/03_distance2d.js |    7 +-
         src/data/examples/ko/08_Math/04_sine.js       |    4 +-
         src/data/examples/ko/08_Math/05_sincosine.js  |   10 +-
         src/data/examples/ko/08_Math/06_sinewave.js   |   27 +-
         .../examples/ko/08_Math/07_additivewave.js    |   33 +-
         .../ko/08_Math/08_polartocartesian.js         |   22 +-
         src/data/examples/ko/08_Math/09_arctangent.js |    4 +-
         .../examples/ko/08_Math/10_Interpolate.js     |   20 +-
         .../examples/ko/08_Math/11_doubleRandom.js    |    8 +-
         src/data/examples/ko/08_Math/12_random.js     |    6 +-
         src/data/examples/ko/08_Math/13_noise1D.js    |   16 +-
         src/data/examples/ko/08_Math/14_noisewave.js  |   28 +-
         src/data/examples/ko/08_Math/15_Noise2D.js    |   18 +-
         src/data/examples/ko/08_Math/16_Noise3D.js    |   22 +-
         .../examples/ko/08_Math/17_Randomchords.js    |   18 +-
         src/data/examples/ko/08_Math/18_Map.js        |   15 +-
         src/data/examples/ko/09_Simulate/00_Forces.js |   55 +-
         .../ko/09_Simulate/01_ParticleSystem.js       |   12 +-
         .../examples/ko/09_Simulate/02_Flocking.js    |  106 +-
         .../examples/ko/09_Simulate/03_WolframCA.js   |   32 +-
         .../examples/ko/09_Simulate/04_GameOfLife.js  |   41 +-
         .../09_Simulate/05_MultipleParticleSystems.js |   52 +-
         .../examples/ko/09_Simulate/06_Spirograph.js  |   78 +-
         .../examples/ko/09_Simulate/07_LSystems.js    |   81 +-
         src/data/examples/ko/09_Simulate/08_Spring.js |   43 +-
         .../examples/ko/09_Simulate/09_Springs.js     |   53 +-
         .../examples/ko/09_Simulate/10_SoftBody.js    |   38 +-
         .../ko/09_Simulate/11_SmokeParticleSystem.js  |   75 +-
         .../ko/09_Simulate/12_BrownianMotion.js       |   14 +-
         src/data/examples/ko/09_Simulate/13_Chain.js  |   13 +-
         .../09_Simulate/14_SnowflakeParticleSystem.js |   38 +-
         .../ko/09_Simulate/15_penrose_tiles.js        |   28 +-
         .../ko/09_Simulate/16_Recursive_Tree.js       |   42 +-
         .../examples/ko/09_Simulate/17_Mandelbrot.js  |   42 +-
         .../examples/ko/10_Interaction/10_Tickle.js   |   18 +-
         .../examples/ko/10_Interaction/20_Follow1.js  |    6 +-
         .../examples/ko/10_Interaction/21_Follow2.js  |    8 +-
         .../examples/ko/10_Interaction/22_Follow3.js  |    8 +-
         .../examples/ko/10_Interaction/23_snake.js    |   52 +-
         .../ko/10_Interaction/24_Wavemaker.js         |   25 +-
         .../examples/ko/10_Interaction/25_reach1.js   |    6 +-
         .../examples/ko/10_Interaction/26_reach2.js   |   10 +-
         .../examples/ko/10_Interaction/27_reach3.js   |   10 +-
         src/data/examples/ko/11_Objects/01_Objects.js |   14 +-
         .../ko/11_Objects/02_Multiple_Objects.js      |   12 +-
         .../ko/11_Objects/03_Objects_Array.js         |   12 +-
         .../03_Objects_Optional_Arguments.js          |   18 +-
         .../examples/ko/11_Objects/04_Inheritance.js  |   12 +-
         .../examples/ko/12_Lights/02_Directional.js   |   11 +-
         src/data/examples/ko/12_Lights/05_Mixture.js  |   10 +-
         .../13_Motion/01_non_orthogonal_reflection.js |   48 +-
         .../examples/ko/13_Motion/02_Linear_Motion.js |    8 +-
         src/data/examples/ko/13_Motion/03_Bounce.js   |   26 +-
         .../ko/13_Motion/04_Bouncy_Bubbles.js         |    4 +-
         src/data/examples/ko/13_Motion/05_Morph.js    |   51 +-
         .../ko/13_Motion/06_Moving_On_Curves.js       |   28 +-
         .../ko/15_Instance_Mode/01_Instantiating.js   |    8 +-
         .../15_Instance_Mode/02_Instance_Container.js |   16 +-
         .../examples/ko/16_Dom/03_Input_Button.js     |   12 +-
         src/data/examples/ko/16_Dom/04_Slider.js      |   14 +-
         src/data/examples/ko/16_Dom/07_Modify_DOM.js  |   23 +-
         src/data/examples/ko/16_Dom/08_Video.js       |   16 +-
         .../examples/ko/16_Dom/09_Video_Canvas.js     |   25 +-
         .../examples/ko/16_Dom/10_Video_Pixels.js     |   12 +-
         src/data/examples/ko/16_Dom/11_Capture.js     |   16 +-
         src/data/examples/ko/16_Dom/12_Drop.js        |   20 +-
         .../ko/17_Drawing/00_Continuous_Lines.js      |    6 +-
         src/data/examples/ko/17_Drawing/01_Pattern.js |   19 +-
         src/data/examples/ko/17_Drawing/02_Pulses.js  |   11 +-
         .../examples/ko/18_Transform/00_Translate.js  |   25 +-
         src/data/examples/ko/18_Transform/01_Scale.js |   35 +-
         .../examples/ko/18_Transform/02_Rotate.js     |   35 +-
         src/data/examples/ko/18_Transform/03_Arm.js   |   26 +-
         .../examples/ko/19_Typography/00_Letters.js   |   32 +-
         .../examples/ko/19_Typography/01_Words.js     |   31 +-
         src/data/examples/ko/20_3D/00_geometries.js   |    4 +-
         .../examples/ko/20_3D/01_sine_cosine_in_3D.js |    4 +-
         .../examples/ko/20_3D/02_multiple_lights.js   |    5 +
         src/data/examples/ko/20_3D/03_materials.js    |    7 +
         src/data/examples/ko/20_3D/04_textures.js     |    8 +-
         .../examples/ko/20_3D/07_orbit_control.js     |    6 +-
         src/data/examples/ko/21_Input/00_Clock.js     |   18 +-
         src/data/examples/ko/21_Input/01_Constrain.js |    6 +-
         src/data/examples/ko/21_Input/02_Easing.js    |   12 +-
         src/data/examples/ko/21_Input/03_Keyboard.js  |   16 +-
         src/data/examples/ko/21_Input/04_Mouse1D.js   |    7 +-
         src/data/examples/ko/21_Input/05_Mouse2D.js   |    5 +-
         .../examples/ko/21_Input/06_MouseIsPressed.js |    6 +-
         .../ko/21_Input/07_Mouse_Functions.js         |    8 +-
         .../examples/ko/21_Input/08_Mouse_Signals.js  |   13 +-
         .../examples/ko/21_Input/09_Storing_Input.js  |   18 +-
         .../ko/22_Advanced_Data/00_Load_Saved_JSON.js |   48 +-
         .../ko/33_Sound/00_Load_and_Play_Sound.js     |   12 +
         .../examples/ko/33_Sound/01_Preload_Sound.js  |   23 +-
         .../examples/ko/33_Sound/02_soundFormats.js   |   50 +-
         src/data/examples/ko/33_Sound/03_Play_Mode.js |   16 +-
         .../examples/ko/33_Sound/04_Pan_SoundFile.js  |   16 +-
         .../examples/ko/33_Sound/05_Sound_Effect.js   |   36 +-
         .../ko/33_Sound/06_Manipulate_Sound.js        |   33 +-
         .../ko/33_Sound/07_Amplitude_Analysis.js      |   39 +-
         .../examples/ko/33_Sound/08_Noise_Envelope.js |   44 +-
         .../examples/ko/33_Sound/09_Note_Envelope.js  |   34 +-
         .../ko/33_Sound/10_Oscillator_Waveform.js     |   17 +-
         .../examples/ko/33_Sound/11_Live_Input.js     |   27 +-
         .../examples/ko/33_Sound/12_FFT_Spectrum.js   |    8 +-
         .../examples/ko/33_Sound/13_Mic_Threshold.js  |   25 +-
         .../examples/ko/33_Sound/14_Filter_LowPass.js |   10 +
         .../ko/33_Sound/15_Filter_BandPass.js         |   28 +
         src/data/examples/ko/33_Sound/16_Delay.js     |   24 +-
         src/data/examples/ko/33_Sound/17_Reverb.js    |   23 +-
         .../ko/33_Sound/18_Convolution_Reverb.js      |   51 +-
         .../examples/ko/33_Sound/19_Record_Save.js    |   39 +-
         .../examples/ko/33_Sound/21_FreqModulation.js |  130 +-
         .../ko/33_Sound/22_AmplitudeModulation.js     |   70 +-
         .../35_Mobile/00_Acceleration_Ball_Bounce.js  |   12 +-
         .../examples/ko/35_Mobile/01_Simple_Draw.js   |    4 +-
         .../ko/35_Mobile/02_Acceleration_Color.js     |    4 +-
         .../ko/35_Mobile/03_Shake_Ball_Bounce.js      |   24 +-
         .../examples/ko/35_Mobile/04_Tilted_3D_Box.js |    4 +-
         src/data/examples/ko/90_Hello_P5/01_shapes.js |   16 +-
         .../ko/90_Hello_P5/02_interactivity.js        |   22 +-
         .../ko/90_Hello_P5/03_interactivity.js        |   18 +-
         .../examples/ko/90_Hello_P5/04_animate.js     |   16 +-
         .../examples/ko/90_Hello_P5/04_flocking.js    |   87 +-
         .../examples/ko/90_Hello_P5/05_weather.js     |   34 +-
         .../examples/ko/90_Hello_P5/06_drawing.js     |   52 +-
         src/data/examples/ko/90_Hello_P5/07_song.js   |   51 +-
         .../zh-Hans/00_Structure/00_Coordinates.js    |    2 +-
         .../05_Image/00_Load_and_Display_Image.js     |   18 +-
         .../zh-Hans/05_Image/01_Background_Image.js   |   17 +-
         .../zh-Hans/05_Image/02_Transparency.js       |   18 +-
         .../zh-Hans/05_Image/03_Alpha_Mask.js         |   14 +-
         .../zh-Hans/05_Image/04_Create_Image.js       |   13 +-
         .../zh-Hans/05_Image/05_Pointillism.js        |   23 +-
         src/data/examples/zh-Hans/07_Color/00_Hue.js  |    8 +-
         .../zh-Hans/07_Color/01_Saturation.js         |    9 +-
         .../zh-Hans/07_Color/02_Brightness.js         |   22 +-
         .../zh-Hans/07_Color/03_Color_Variables.js    |   10 +-
         .../zh-Hans/07_Color/04_Relativity.js         |   10 +-
         .../zh-Hans/07_Color/05_Linear_Gradient.js    |   17 +-
         .../zh-Hans/07_Color/06_Radial_Gradient.js    |    5 +-
         .../zh-Hans/07_Color/07_Lerp_Color.js         |    5 +-
         .../zh-Hans/08_Math/00_incrementdecrement.js  |    5 +-
         .../zh-Hans/08_Math/01_operatorprecedence.js  |   48 +-
         .../examples/zh-Hans/08_Math/02_distance1d.js |    5 +-
         .../examples/zh-Hans/08_Math/03_distance2d.js |    7 +-
         src/data/examples/zh-Hans/08_Math/04_sine.js  |    6 +-
         .../examples/zh-Hans/08_Math/05_sincosine.js  |    9 +-
         .../examples/zh-Hans/08_Math/06_sinewave.js   |   27 +-
         .../zh-Hans/08_Math/07_additivewave.js        |   33 +-
         .../zh-Hans/08_Math/08_polartocartesian.js    |   19 +-
         .../examples/zh-Hans/08_Math/09_arctangent.js |    5 +-
         .../zh-Hans/08_Math/10_Interpolate.js         |   19 +-
         .../zh-Hans/08_Math/11_doubleRandom.js        |    7 +-
         .../examples/zh-Hans/08_Math/12_random.js     |    7 +-
         .../examples/zh-Hans/08_Math/13_noise1D.js    |   16 +-
         .../examples/zh-Hans/08_Math/14_noisewave.js  |   28 +-
         .../examples/zh-Hans/08_Math/15_Noise2D.js    |   14 +-
         .../examples/zh-Hans/08_Math/16_Noise3D.js    |   24 +-
         .../zh-Hans/08_Math/17_Randomchords.js        |   17 +-
         src/data/examples/zh-Hans/08_Math/18_Map.js   |   14 +-
         .../zh-Hans/08_Math/19_parametricEquation.js  |   21 +-
         .../zh-Hans/10_Interaction/10_Tickle.js       |   16 +-
         .../zh-Hans/10_Interaction/20_Follow1.js      |    6 +-
         .../zh-Hans/10_Interaction/21_Follow2.js      |    8 +-
         .../zh-Hans/10_Interaction/22_Follow3.js      |    8 +-
         .../zh-Hans/10_Interaction/23_snake.js        |   48 +-
         .../zh-Hans/10_Interaction/24_Wavemaker.js    |   22 +-
         .../zh-Hans/10_Interaction/25_reach1.js       |    6 +-
         .../zh-Hans/10_Interaction/26_reach2.js       |   10 +-
         .../zh-Hans/10_Interaction/27_reach3.js       |   10 +-
         .../10_Interaction/28_ArduinoSensor.js        |   38 +-
         .../zh-Hans/10_Interaction/29_kaleidoscope.js |   31 +-
         .../examples/zh-Hans/11_Objects/01_Objects.js |   13 +-
         .../zh-Hans/11_Objects/02_Multiple_Objects.js |   11 +-
         .../zh-Hans/11_Objects/03_Objects_Array.js    |   11 +-
         .../03_Objects_Optional_Arguments.js          |   19 +-
         .../zh-Hans/11_Objects/04_Inheritance.js      |   11 +-
         .../11_Objects/05_Composite_Objects.js        |    7 +-
         .../15_Instance_Mode/01_Instantiating.js      |   13 +-
         .../15_Instance_Mode/02_Instance_Container.js |   24 +-
         .../zh-Hans/16_Dom/03_Input_Button.js         |    5 +-
         src/data/examples/zh-Hans/16_Dom/04_Slider.js |    5 +-
         .../examples/zh-Hans/16_Dom/07_Modify_DOM.js  |    6 +-
         src/data/examples/zh-Hans/16_Dom/08_Video.js  |    5 +-
         .../zh-Hans/16_Dom/09_Video_Canvas.js         |    7 +-
         .../zh-Hans/16_Dom/10_Video_Pixels.js         |    7 +-
         .../examples/zh-Hans/16_Dom/11_Capture.js     |    7 +-
         src/data/examples/zh-Hans/16_Dom/12_Drop.js   |    5 +-
         .../22_Advanced_Data/01_Load_Saved_Table.js   |  110 ++
         .../zh-Hans/90_Hello_P5/02_interactivity.js   |    3 -
         .../zh-Hans/90_Hello_P5/03_interactivity.js   |    3 -
         .../zh-Hans/90_Hello_P5/05_weather.js         |    3 -
         src/data/ko.txt                               |  633 --------
         src/data/ko.yml                               |   66 +-
         src/data/reference/ko.json                    |   10 +-
         src/data/zh-Hans.yml                          |   52 +-
         src/templates/layouts/default.hbs             |    4 +-
         src/templates/pages/books/index.hbs           |  104 +-
         src/templates/pages/community/index.hbs       |    8 +-
         src/templates/pages/download/index.hbs        |    4 +-
         src/templates/pages/get-started/index.hbs     |    6 +-
         src/templates/pages/index.hbs                 |    4 +-
         .../learn/coordinate-system-and-shapes.hbs    |    4 +-
         .../pages/reference/assets/js/reference.js    |    9 +-
         .../reference/assets/js/reference.js.map      |   10 +-
         src/templates/pages/reference/index.hbs       |    8 +-
         src/templates/partials/asterisk.hbs           |    1 -
         src/yuidoc-p5-theme-src/scripts/main.js       |    2 +-
         .../scripts/tpl/class.html                    |   36 +-
         .../scripts/tpl/library.html                  |    2 +-
         .../scripts/views/listView.js                 |    3 +
         318 files changed, 3631 insertions(+), 4969 deletions(-)
         create mode 100644 src/assets/img/books/generative_design.jpg
         create mode 100644 src/assets/img/books/generative_gestaltung.jpg
         create mode 100644 src/assets/img/books/learn_javascript.jpg
         create mode 100644 src/data/examples/assets/bubbles.csv
         create mode 100644 src/data/examples/en/22_Advanced_Data/01_Load_Saved_Table.js
         create mode 100644 src/data/examples/es/22_Advanced_Data/01_Load_Saved_Table.js
         create mode 100644 src/data/examples/zh-Hans/22_Advanced_Data/01_Load_Saved_Table.js
         delete mode 100644 src/data/ko.txt
        
        diff --git a/Gruntfile.js b/Gruntfile.js
        index e7975899fb..a3d993d65b 100644
        --- a/Gruntfile.js
        +++ b/Gruntfile.js
        @@ -408,6 +408,7 @@ module.exports = function(grunt) {
             'update-version',
             'exec',
             'clean',
        +    'requirejs:yuidoc_theme',
             'requirejs',
             'copy',
             'assemble',
        diff --git a/contributor_docs/i18n_contribution.md b/contributor_docs/i18n_contribution.md
        index a57f0458d0..9a07ba8e59 100644
        --- a/contributor_docs/i18n_contribution.md
        +++ b/contributor_docs/i18n_contribution.md
        @@ -136,7 +136,8 @@ p5.js-website/
             ```
         4. Duplicate `en.yml` - stored under `src/data/` - and name it `language_abbreviation.yml`. For example, when the Spanish version was created it was named `es.yml`. Check [How the website works](#how-the-website-works) and [File Structure](#file-structure) for further information.
         5. Duplicate `es.json` - stored under `src/data/reference/` - and name it `[language_abbreviation].json`.
        -6. Add a new menu entry in [`src/templates/partials/i18n.hbs`](https://github.com/processing/p5.js-website/blob/master/src/templates/partials/i18n.hbs#L8) like so `<li><a href='#' lang='[language_abbreviation]' data-lang='[language_abbreviation]'>[language_name]</a></li>`.
        +6. Duplicate `en` folder - stored under `src/data/examples` - and name it `language_abbreviation`.
        +7. Add a new menu entry in [`src/templates/partials/i18n.hbs`](https://github.com/processing/p5.js-website/blob/master/src/templates/partials/i18n.hbs#L8) like so `<li><a href='#' lang='[language_abbreviation]' data-lang='[language_abbreviation]'>[language_name]</a></li>`.
         
         ## Working on existing translations
         
        diff --git a/i18n-tracking.yml b/i18n-tracking.yml
        index 92288aaa11..85db2dc8db 100644
        --- a/i18n-tracking.yml
        +++ b/i18n-tracking.yml
        @@ -1,300 +1,106 @@
         es:
           src/data/en.yml:
        -    line 49: '  RotatingKnobs'
        -    line 94: '  project-phuong'
        -    line 95: '  credit-phuong'
        -    line 98: '  credit-daein'
        -    line 107: '  credit-moon-xin'
        -    line 84: '  project-tag-curriculum'
        -    line 105: '  description-casey-louise'
        -    line 106: '  project-moon-xin'
        -    line 66: '  2015cc_5'
        -    line 75: showcase
        -    line 99: '  description-daein'
        -    line 108: '  description-moon-xin'
        -    line 89: '  project-tag-tool'
        -    line 90: '  project-tag-tutorial'
        -    line 91: '  project-roni'
        -    line 92: '  credit-roni'
        -    line 93: '  description-roni'
        -    line 96: '  description-phuong'
        -    line 97: '  project-daein'
        -    line 85: '  project-tag-documentation'
        -    line 86: '  project-tag-game'
        -    line 87: '  project-tag-library'
        -    line 15: Showcase
        -    line 74: ''
        -    line 76: '  showcase-title'
        -    line 88: '  project-tag-organizing'
        -    line 100: '  project-qianqian'
        -    line 101: '  credit-qianqian'
        -    line 102: '  description-qianqian'
        -    line 103: '  project-casey-louise'
        -    line 104: '  credit-casey-louise'
        -    line 7: Donate
        -    line 31: '  p5js-wiki-title'
        -    line 32: '  p5js-wiki'
        -    line 77: '  showcase-intro1'
        -    line 78: '  showcase-intro2'
        -    line 79: '  showcase-intro3'
        -    line 80: '  showcase-featuring'
        -    line 81: '  project-tag-art'
        -    line 82: '  project-tag-design'
        -    line 83: '  project-tag-code'
        -    line 52: '  p3xh2'
        -    line 44: '  p2x1'
        -    line 45: '  p2x2'
        -    line 48: '  p2x5'
        -    line 55: '  p3xp3'
        -    line 56: '  p3xp4'
        -    line 57: '  p3xp5'
        -    line 5: Editor
        -    line 46: '  p2x3'
        -    line 47: '  p2x4'
        -    line 50: '  p2x7'
        -    line 51: ''
        -    line 53: '  p3xp1'
        -    line 54: '  p3xp2'
        -    line 58: '  p3xp6'
        -    line 63: '  p4xp3'
        -    line 43: '  p2xh2'
        -    line 380: '  2019cc_18'
        -    line 373: '  2019cc_11'
        -    line 381: '  2019cc_19'
        -    line 371: '  2019cc_9'
        -    line 358: '  output11'
        -    line 364: '  2019cc_2'
        -    line 368: '  2019cc_6'
        -    line 377: '  2019cc_15'
        -    line 363: '  2019cc_1'
        -    line 329: '  2015cc_9'
        -    line 341: '  2019contributors-conference4'
        -    line 274: '  sharing2'
        -    line 275: '  sharing3'
        -    line 276: ''
        -    line 290: '  contributors-conference-title'
        -    line 291: '  contributors-conference1'
        -    line 292: '  contributors-conference2'
        -    line 293: '  participants-title'
        -    line 294: '  support-title'
        -    line 295: '  support1'
        -    line 296: '  support2'
        -    line 297: '  support3'
        -    line 298: '  support4'
        -    line 299: '  support5'
        -    line 300: '  support6'
        -    line 305: ''
        -    line 306: '  2015contributors-conference-title'
        -    line 307: '  2015contributors-conference-date'
        -    line 308: '  2015contributors-conference1'
        -    line 309: '  2015contributors-conference2'
        -    line 310: '  2015contributors-conference3'
        -    line 311: '  2015contributors-conference-diversity-title'
        -    line 312: '  2015contributors-conference-diversity1'
        -    line 313: '  2015contributors-conference-diversity2'
        -    line 314: '  2015contributors-conference-diversity3'
        -    line 315: '  2015contributors-conference-diversity4'
        -    line 316: '  2015contributors-conference-diversity5'
        -    line 317: '  2015contributors-conference-diversity6'
        -    line 318: '  2015contributors-conference-diversity7'
        -    line 319: '  2015contributors-conference-diversity8'
        -    line 320: '  2015contributors-conference-diversity9'
        -    line 321: '  2015cc_1'
        -    line 322: '  2015cc_2'
        -    line 323: '  2015cc_3'
        -    line 324: '  2015cc_4'
        -    line 325: '  2015cc_5'
        -    line 326: '  2015cc_6'
        -    line 327: '  2015cc_7'
        -    line 328: '  2015cc_8'
        -    line 330: '  2015cc_10'
        -    line 331: '  2015cc_11'
        -    line 332: '  2015cc_12'
        -    line 333: '  2015cc_13'
        -    line 334: '  2015cc_14'
        -    line 335: '  2015cc_15'
        -    line 336: '  2019contributors-conference-title'
        -    line 337: '  2019contributors-conference-date'
        -    line 338: '  2019contributors-conference1'
        -    line 339: '  2019contributors-conference2'
        -    line 340: '  2019contributors-conference3'
        -    line 342: '  outputs'
        -    line 343: '  output1'
        -    line 344: '  output2'
        -    line 345: '  output3'
        -    line 346: '  output3-1'
        -    line 347: '  output4'
        -    line 348: '  output5'
        -    line 386: '  2019cc_24'
        -    line 359: '  output12'
        -    line 362: '  output15'
        -    line 374: '  2019cc_12'
        -    line 376: '  2019cc_14'
        -    line 379: '  2019cc_17'
        -    line 382: '  2019cc_20'
        -    line 355: '  output9'
        -    line 356: '  output9-1'
        -    line 360: '  output13'
        -    line 357: '  output10'
        -    line 361: '  output14'
        -    line 1: Skip-To-Content
        -    line 39: '  start-creating'
        -    line 40: '  p1xh1'
        -    line 41: '  p1x1'
        -    line 42: '  p1x2'
        -    line 59: ''
        -    line 60: '  p4xh2'
        -    line 61: '  p4xp1'
        -    line 62: '  p4xp2'
        -    line 64: '  p4xp4'
        -    line 65: '  p4xp5'
        -    line 2: Language-Settings
        -    line 3: Sidebar-Title
        -    line 67: ''
        -    line 370: '  2019cc_8'
        -    line 372: '  2019cc_10'
        -    line 383: '  2019cc_21'
        -    line 151: '  report-bugs'
        -    line 168: '  support-23'
        -    line 72: '  sketch_info_link'
        -    line 8: Start
        -    line 16: footerxh1
        -    line 71: '  sketch_info'
        -    line 117: '  book1'
        -    line 121: '  download-intro'
        -    line 122: '  editor-title'
        -    line 123: '  p5.js-editor'
        -    line 124: '  p5.js-editor-intro'
        -    line 125: '  editor-includes'
        -    line 127: '  complete-library-intro1'
        -    line 128: '  complete-library-intro2'
        -    line 129: '  complete-library-intro3'
        -    line 133: '  includes-2'
        -    line 136: '  single-files-intro'
        -    line 148: '  etc-title'
        -    line 149: '  older-releases'
        -    line 150: '  github-repository'
        -    line 153: ''
        -    line 155: '  support-options'
        -    line 164: '  support-20'
        -    line 176: '  support-17-alt'
        -    line 177: '  support-18-alt'
        -    line 178: '  support-19-alt'
        -    line 179: '  support-20-alt'
        -    line 180: '  support-21-alt'
        -    line 181: '  support-22-alt'
        -    line 182: '  support-23-alt'
        -    line 183: '  support-24-alt'
        -    line 184: '  support-25-alt'
        -    line 185: '  support-26-alt'
        -    line 186: '  support-27-alt'
        -    line 187: '  support-28-alt'
        -    line 188: '  support-29-alt'
        -    line 189: '  support-30-alt'
        -    line 190: '  support-30-alt'
        -    line 191: '  support-31-alt'
        -    line 200: '  core-libraries'
        -    line 201: '  community-libraries'
        -    line 202: '  libraries-created-by'
        -    line 213: '  asciiart'
        -    line 214: '  p5.ble'
        -    line 215: '  blizard.js'
        -    line 222: '  p5.clickable'
        -    line 223: '  p5.cmyk.js'
        -    line 224: '  p5.collide2D'
        -    line 225: '  p5.createloop'
        -    line 226: '  p5.dimensions'
        -    line 227: '  p5.EasyCam'
        -    line 228: '  p5.experience'
        -    line 229: '  p5.func'
        -    line 230: '  p5.geolocation'
        -    line 231: '  p5.gibber'
        -    line 232: '  grafica.js'
        -    line 233: '  p5.gui'
        -    line 234: '  p5.localmessage'
        -    line 235: '  marching'
        -    line 236: '  mappa'
        -    line 237: '  ml5.js'
        -    line 238: '  p5.play'
        -    line 239: '  p5.particle'
        -    line 240: '  p5.Riso'
        -    line 241: '  rita.js'
        -    line 242: '  Rotating Knobs'
        -    line 243: '  p5.scenemanager'
        -    line 244: '  p5.screenPosition'
        -    line 254: '  p5.serial'
        -    line 255: '  Shape5'
        -    line 256: '  p5.shape.js'
        -    line 257: '  p5.speech'
        -    line 258: '  p5.start2d.js'
        -    line 259: '  p5.tiledmap'
        -    line 260: '  p5.touchgui'
        -    line 261: '  tramontana'
        -    line 262: '  vida'
        -    line 263: '  p5.voronoi'
        -    line 264: '  p5.3D'
        -    line 272: '  sharing-title'
        -    line 273: '  sharing1'
        -    line 349: '  output6'
        -    line 350: '  output6-1'
        -    line 351: '  output6-2'
        -    line 352: '  output7'
        -    line 353: '  output8'
        -    line 354: '  output8-1'
        -    line 365: '  2019cc_3'
        -    line 366: '  2019cc_4'
        -    line 367: '  2019cc_5'
        -    line 369: '  2019cc_7'
        -    line 375: '  2019cc_13'
        -    line 378: '  2019cc_16'
        -    line 384: '  2019cc_22'
        -    line 385: '  2019cc_23'
        -    line 387: '  2019cc_25'
        -    line 559: '  output3-1'
        -    line 568: '  output9'
        -    line 569: '  output9-1'
        -    line 555: '  output1'
        -    line 565: '  output8'
        -    line 566: '  output8-1'
        -    line 572: '  output14'
        -    line 554: '  outputs'
        -    line 556: '  output2'
        -    line 557: '  output3'
        -    line 558: '  output3-1'
        -    line 560: '  output5'
        -    line 561: '  output6'
        -    line 562: '  output6-1'
        -    line 563: '  output6-2'
        -    line 564: '  output7'
        -    line 567: '  output9'
        -    line 570: '  output12'
        -    line 571: '  output13'
        -    line 581: '  2019cc_25'
        -    line 413: '  p5.EasyCam'
        -    line 552: '  2019contributors-conference2'
        -    line 412: '  p5.EasyCam'
        -    line 425: '  p5.touchgui'
        -    line 13: '  start-creating'
        -    line 109: '  2019cc_21'
        -    line 110: '  2019cc_22'
        -    line 111: '  2019cc_23'
        -    line 545: '  2019contributors-conference-date'
        -    line 504: '  participants-title'
        -    line 505: '  support-title'
        -    line 506: '  support1'
        -    line 507: '  support2'
        -    line 508: '  support3'
        -    line 509: '  support4'
        -    line 510: '  support5'
        -    line 511: '  support6'
        -    line 34: '  p2xh2'
        -    line 391: '  p5.localmessage'
        -    line 399: '  Rotating Knobs'
        -    line 401: '  p5.screenPosition'
        -    line 404: '  Shape5'
        -    line 406: '  p5.start.js'
        -    line 407: '  p5.start2d.js'
        -    line 409: '  tramontana'
        +    line 39: '  p2x1'
        +    line 51: '  notes-title'
        +    line 52: '  notes1'
        +    line 53: '  notes2'
        +    line 54: '  notes3'
        +    line 55: '  notes4'
        +    line 56: '  notes5'
        +    line 99: '  book-5-pages'
        +    line 64: '  book-1-title'
        +    line 65: '  book-1-authors'
        +    line 66: '  book-1-publisher'
        +    line 67: '  book-1-pages'
        +    line 68: '  book-1-type'
        +    line 69: '  book-1-description'
        +    line 70: '  book-1-order-a'
        +    line 71: '  book-1-order-b'
        +    line 72: '  book-2-title'
        +    line 73: '  book-2-authors'
        +    line 74: '  book-2-publisher'
        +    line 75: '  book-2-pages'
        +    line 76: '  book-2-type'
        +    line 77: '  book-2-description'
        +    line 78: '  book-2-order-a'
        +    line 79: '  book-2-order-b'
        +    line 80: '  book-3-title'
        +    line 81: '  book-3-authors'
        +    line 82: '  book-3-publisher'
        +    line 83: '  book-3-pages'
        +    line 84: '  book-3-type'
        +    line 85: '  book-3-description'
        +    line 86: '  book-3-order-a'
        +    line 87: '  book-3-order-b'
        +    line 88: '  book-4-title'
        +    line 89: '  book-4-authors'
        +    line 90: '  book-4-publisher'
        +    line 91: '  book-4-pages'
        +    line 92: '  book-4-type'
        +    line 93: '  book-4-description'
        +    line 94: '  book-4-order-a'
        +    line 95: '  book-4-order-b'
        +    line 96: '  book-5-title'
        +    line 97: '  book-5-authors'
        +    line 98: '  book-5-publisher'
        +    line 100: '  book-5-type'
        +    line 101: '  book-5-description'
        +    line 102: '  book-5-order-a'
        +    line 103: '  book-5-order-b'
        +    line 480: '  notes3'
        +    line 44: '  description-roni'
        +    line 45: '  project-phuong'
        +    line 17: Showcase
        +    line 25: ''
        +    line 26: showcase
        +    line 27: '  showcase-title'
        +    line 28: '  showcase-intro1'
        +    line 29: '  showcase-intro2'
        +    line 30: '  showcase-intro3'
        +    line 31: '  showcase-featuring'
        +    line 32: '  project-tag-art'
        +    line 33: '  project-tag-design'
        +    line 34: '  project-tag-code'
        +    line 35: '  project-tag-curriculum'
        +    line 36: '  project-tag-documentation'
        +    line 37: '  project-tag-game'
        +    line 38: '  project-tag-library'
        +    line 40: '  project-tag-tool'
        +    line 41: '  project-tag-tutorial'
        +    line 42: '  project-roni'
        +    line 43: '  credit-roni'
        +    line 46: '  credit-phuong'
        +    line 47: '  description-phuong'
        +    line 48: '  project-daein'
        +    line 49: '  credit-daein'
        +    line 50: '  description-daein'
        +    line 57: '  project-moon-xin'
        +    line 58: '  credit-moon-xin'
        +    line 59: '  description-moon-xin'
        +    line 516: '  showcase-intro3'
        +    line 517: '  showcase-featuring'
        +    line 518: '  project-tag-art'
        +    line 519: '  project-tag-design'
        +    line 520: '  project-tag-code'
        +    line 521: '  project-tag-curriculum'
        +    line 522: '  project-tag-documentation'
        +    line 523: '  project-tag-game'
        +    line 524: '  project-tag-library'
        +    line 525: '  project-tag-organizing'
        +    line 526: '  project-tag-tool'
        +    line 527: '  project-tag-tutorial'
        +    line 531: '  description-roni'
        +    line 358: '  p5.ble'
        +    line 364: '  p5.createloop'
        +    line 368: '  p5.experience'
        +    line 377: '  vida'
        +    line 380: '  p5.3D'
        +    line 363: '  p5.experience'
        +    line 329: '  coordinate-system-simple-shapes-p2x1'
        +    line 341: '  coordinate-system-simple-shapes-p9x1'
        +    line 274: '  color-description1'
        +    line 275: '  color-description2'
        +    line 276: '  color-title'
             line 277: '  color-p1x1'
             line 278: '  color-p2x1'
             line 279: '  color-p2x2'
        @@ -308,716 +114,301 @@ es:
             line 287: '  color-p3x5'
             line 288: '  color-p4x1'
             line 289: '  color-rgb-title'
        +    line 290: '  color-rgb-p1x1'
        +    line 291: '  color-rgb-li1'
        +    line 292: '  color-rgb-li2'
        +    line 293: '  color-rgb-li3'
        +    line 294: '  color-rgb-li4'
        +    line 295: '  color-rgb-li5'
        +    line 296: '  color-rgb-p2x1'
        +    line 297: '  color-transparency-title'
        +    line 298: '  color-transparency-p1x1'
        +    line 299: '  color-transparency-p2x1'
        +    line 300: '  color-transparency-p3x1'
             line 301: '  color-custom-ranges-title'
             line 302: '  color-custom-ranges-p1x1'
             line 303: '  color-custom-ranges-p2x1'
             line 304: '  color-custom-ranges-p3x1'
        +    line 305: '  color-custom-ranges-p4x1'
        +    line 306: '  color-custom-ranges-p5x1'
        +    line 307: '  color-custom-ranges-li1x1'
        +    line 308: '  color-custom-ranges-li1x2'
        +    line 309: '  color-custom-ranges-li2x1'
        +    line 310: '  color-custom-ranges-li2x2'
        +    line 311: '  color-custom-ranges-li3x1'
        +    line 312: '  color-custom-ranges-li3x2'
        +    line 313: '  color-custom-ranges-p6x1'
        +    line 314: '  color-custom-ranges-p6x2'
        +    line 315: '  coordinate-system-description1'
        +    line 316: '  coordinate-system-description2'
        +    line 317: '  coordinate-system-description3'
        +    line 318: '  coordinate-system-description4'
        +    line 319: '  coordinate-system-description5'
        +    line 320: '  coordinate-system-description-title'
        +    line 321: '  coordinate-system-description-p1x1'
        +    line 322: '  coordinate-system-description-p2x1'
        +    line 323: '  coordinate-system-description-p3x1'
        +    line 324: '  coordinate-system-description-p4x1'
        +    line 325: '  coordinate-system-description-p5x1'
        +    line 326: '  coordinate-system-simple-shapes-title'
        +    line 327: '  coordinate-system-simple-shapes-p1x1'
        +    line 328: '  coordinate-system-simple-shapes-p2x1'
        +    line 330: '  coordinate-system-simple-shapes-p3x2'
        +    line 331: '  coordinate-system-simple-shapes-p4x1'
        +    line 332: '  coordinate-system-simple-shapes-p4x2'
        +    line 333: '  coordinate-system-simple-shapes-p5x1'
        +    line 334: '  coordinate-system-simple-shapes-p5x2'
        +    line 335: '  coordinate-system-simple-shapes-p6x1'
        +    line 336: '  coordinate-system-simple-shapes-p6x2'
        +    line 337: '  coordinate-system-simple-shapes-p7x1'
        +    line 338: '  coordinate-system-simple-shapes-p7x2'
        +    line 339: '  coordinate-system-simple-shapes-p8x1'
        +    line 340: '  coordinate-system-simple-shapes-p8x2'
        +    line 342: '  coordinate-system-simple-shapes-p8x4'
        +    line 343: '  coordinate-system-simple-shapes-p8x5'
        +    line 344: '  coordinate-system-simple-shapes-p8x6'
        +    line 345: '  coordinate-system-simple-shapes-p9x1'
        +    line 346: '  coordinate-system-simple-shapes-p9x2'
        +    line 347: '  coordinate-system-simple-shapes-p9x3'
        +    line 348: '  coordinate-system-simple-shapes-p10x1'
        +    line 108: '  coordinate-system-simple-shapes-p2x1'
             line 120: '  coordinate-system-simple-shapes-p9x1'
        -    line 38: '  p1xh1'
        -    line 4: Sidebar-Title
        -    line 400: '  p5.collide2D'
        -    line 402: '  p5.dimensions'
        -    line 403: '  p5.experience'
        -    line 405: '  p5.geolocation'
        -    line 408: '  p5.gui'
        -    line 410: '  p5.play'
        -    line 411: '  p5.particle'
        -    line 424: '  p5.serial'
        -    line 426: '  p5.tiledmap'
        -    line 427: '  vida'
        -    line 428: '  p5.voronoi'
        -    line 429: '  p5.3D'
        -    line 156: '  etc-title'
        -    line 157: '  older-releases'
        -    line 158: '  github-repository'
        -    line 159: '  report-bugs'
        -    line 392: '  marching'
        -    line 394: '  ml5.js'
        -    line 397: '  p5.Riso'
        -    line 476: '  contributors-conference-title'
        -    line 477: '  contributors-conference1'
        -    line 478: '  contributors-conference2'
        -    line 479: '  contributors-conference3'
        -    line 480: '  contributors-conference4'
        -    line 485: ''
        -    line 486: '  2015contributors-conference-title'
        -    line 487: '  2015contributors-conference-date'
        -    line 488: '  2015contributors-conference1'
        -    line 489: '  2015contributors-conference2'
        -    line 490: '  2015contributors-conference3'
        -    line 491: '  2015contributors-conference-participants-title'
        -    line 492: '  2015contributors-conference-diversity-title'
        -    line 493: '  2015contributors-conference-diversity1'
        -    line 494: '  2015contributors-conference-diversity2'
        -    line 495: '  2015contributors-conference-diversity3'
        -    line 496: '  2015contributors-conference-diversity4'
        -    line 497: '  2015contributors-conference-diversity5'
        -    line 498: '  2015contributors-conference-diversity6'
        -    line 499: '  2015contributors-conference-diversity7'
        -    line 500: '  2015contributors-conference-diversity8'
        -    line 501: '  2015contributors-conference-diversity9'
        -    line 502: '  2015contributors-conference-support-title'
        -    line 503: '  2015contributors-conference-support1'
        -    line 512: '  2015cc_4'
        -    line 513: '  2015cc_5'
        -    line 514: '  2015cc_6'
        -    line 515: '  2015cc_7'
        -    line 516: '  2015cc_8'
        -    line 517: '  2015cc_9'
        -    line 518: '  2015cc_10'
        -    line 519: '  2015cc_11'
        -    line 520: '  2015cc_12'
        -    line 521: '  2015cc_13'
        -    line 522: '  2015cc_14'
        -    line 523: '  2015cc_15'
        -    line 139: '  download-intro'
        -    line 140: '  editor-title'
        -    line 141: '  p5.js-editor'
        -    line 142: '  p5.js-editor-intro'
        -    line 143: '  editor-includes'
        -    line 145: '  complete-library-intro1'
        -    line 146: '  complete-library-intro2'
        -    line 147: '  complete-library-intro3'
        -    line 154: '  single-files-intro'
        -    line 541: '  2019contributors-conference-title'
        -    line 542: '  2019contributors-conference-date'
        -    line 546: '  2019contributors-conference2'
        -    line 547: '  2019contributors-conference3'
        -    line 548: '  2019contributors-conference4'
        -    line 549: '  2019cc_1'
        -    line 550: '  2019cc_2'
        -    line 551: '  2019cc_3'
        -    line 553: '  2019cc_5'
        -    line 21: '  support-options'
        -    line 112: '  2019cc_24'
        -    line 420: '  p5.shape.js'
        -    line 573: '  output15'
        +    line 386: '  create-your-own4'
        +    line 359: '  p5.clickable'
        +    line 362: '  p5.dimensions1'
        +    line 373: '  mappa'
        +    line 374: '  p5.play'
        +    line 376: '  rita.js'
        +    line 379: '  p5.serial1'
        +    line 381: '  p5.serial3'
        +    line 382: '  p5.speech'
        +    line 391: '  p5.3D'
        +    line 355: '  asciiart'
        +    line 356: '  p5.ble'
        +    line 360: '  p5.createloop'
        +    line 371: '  vida'
        +    line 357: '  asciiart'
        +    line 361: '  p5.clickable'
        +    line 12: Showcase
        +    line 20: ''
        +    line 21: showcase
        +    line 22: '  Showcase'
        +    line 23: '  test'
        +    line 515: '  showcase-title'
        +    line 528: '  project-qianqian'
        +    line 529: '  credit-qianqian'
        +    line 530: '  description-qianqian'
        +    line 532: '  credit-conchinha-lessel'
        +    line 533: '  description-conchinha-lessel'
        +    line 535: '  description-phuong'
        +    line 539: '  description-daein'
        +    line 546: '  description-qianqian'
        +    line 547: '  project-casey-louise'
        +    line 548: '  credit-casey-louise'
        +    line 549: '  description-casey-louise'
        +    line 550: '  project-moon-xin'
        +    line 551: '  credit-moon-xin'
        +    line 552: '  description-moon-xin'
        +    line 669: '  credit-moon-xin'
        +    line 481: '  notes1'
        +    line 482: '  notes2'
        +    line 483: '  notes3'
        +    line 484: '  notes4'
        +    line 485: '  notes5'
        +    line 608: '  book-1-authors'
        +    line 617: '  book-2-authors'
         ko:
           src/data/en.yml:
        -    line 49: '  RotatingKnobs'
        -    line 66: '  2015cc_5'
        -    line 75: showcase
        -    line 84: '  project-tag-curriculum'
        -    line 94: '  project-phuong'
        -    line 95: '  credit-phuong'
        -    line 98: '  credit-daein'
        -    line 105: '  description-casey-louise'
        -    line 106: '  project-moon-xin'
        -    line 107: '  credit-moon-xin'
        -    line 7: Donate
        -    line 15: Showcase
        -    line 31: '  p5js-wiki-title'
        -    line 32: '  p5js-wiki'
        -    line 74: ''
        -    line 76: '  showcase-title'
        -    line 77: '  showcase-intro1'
        -    line 78: '  showcase-intro2'
        -    line 79: '  showcase-intro3'
        -    line 80: '  showcase-featuring'
        -    line 81: '  project-tag-art'
        -    line 82: '  project-tag-design'
        -    line 83: '  project-tag-code'
        -    line 85: '  project-tag-documentation'
        -    line 86: '  project-tag-game'
        -    line 87: '  project-tag-library'
        -    line 88: '  project-tag-organizing'
        -    line 89: '  project-tag-tool'
        -    line 90: '  project-tag-tutorial'
        -    line 91: '  project-roni'
        -    line 92: '  credit-roni'
        -    line 93: '  description-roni'
        -    line 96: '  description-phuong'
        -    line 97: '  project-daein'
        -    line 99: '  description-daein'
        -    line 100: '  project-qianqian'
        -    line 101: '  credit-qianqian'
        -    line 102: '  description-qianqian'
        -    line 103: '  project-casey-louise'
        -    line 104: '  credit-casey-louise'
        -    line 108: '  description-moon-xin'
        -    line 1: Skip-To-Content
        -    line 2: Language-Settings
        -    line 3: Sidebar-Title
        -    line 5: Editor
        -    line 8: Start
        -    line 16: footerxh1
        -    line 39: '  start-creating'
        -    line 40: '  p1xh1'
        -    line 41: '  p1x1'
        -    line 42: '  p1x2'
        -    line 43: '  p2xh2'
        -    line 44: '  p2x1'
        -    line 45: '  p2x2'
        -    line 46: '  p2x3'
        -    line 47: '  p2x4'
        -    line 48: '  p2x5'
        -    line 50: '  p2x7'
        -    line 51: ''
        -    line 52: '  p3xh2'
        -    line 53: '  p3xp1'
        -    line 54: '  p3xp2'
        -    line 55: '  p3xp3'
        -    line 56: '  p3xp4'
        -    line 57: '  p3xp5'
        -    line 58: '  p3xp6'
        -    line 59: ''
        -    line 60: '  p4xh2'
        -    line 61: '  p4xp1'
        -    line 62: '  p4xp2'
        -    line 63: '  p4xp3'
        -    line 64: '  p4xp4'
        -    line 65: '  p4xp5'
        -    line 67: ''
        -    line 71: '  sketch_info'
        -    line 72: '  sketch_info_link'
        -    line 117: '  book1'
        -    line 121: '  download-intro'
        -    line 122: '  editor-title'
        -    line 123: '  p5.js-editor'
        -    line 124: '  p5.js-editor-intro'
        -    line 125: '  editor-includes'
        -    line 127: '  complete-library-intro1'
        -    line 128: '  complete-library-intro2'
        -    line 129: '  complete-library-intro3'
        -    line 133: '  includes-2'
        -    line 136: '  single-files-intro'
        -    line 148: '  etc-title'
        -    line 149: '  older-releases'
        -    line 150: '  github-repository'
        -    line 151: '  report-bugs'
        -    line 153: ''
        -    line 155: '  support-options'
        -    line 164: '  support-20'
        -    line 168: '  support-23'
        -    line 176: '  support-17-alt'
        -    line 177: '  support-18-alt'
        -    line 178: '  support-19-alt'
        -    line 179: '  support-20-alt'
        -    line 180: '  support-21-alt'
        -    line 181: '  support-22-alt'
        -    line 182: '  support-23-alt'
        -    line 183: '  support-24-alt'
        -    line 184: '  support-25-alt'
        -    line 185: '  support-26-alt'
        -    line 186: '  support-27-alt'
        -    line 187: '  support-28-alt'
        -    line 188: '  support-29-alt'
        -    line 189: '  support-30-alt'
        -    line 190: '  support-30-alt'
        -    line 191: '  support-31-alt'
        -    line 200: '  core-libraries'
        -    line 201: '  community-libraries'
        -    line 202: '  libraries-created-by'
        -    line 213: '  asciiart'
        -    line 214: '  p5.ble'
        -    line 215: '  blizard.js'
        -    line 222: '  p5.clickable'
        -    line 223: '  p5.cmyk.js'
        -    line 224: '  p5.collide2D'
        -    line 225: '  p5.createloop'
        -    line 226: '  p5.dimensions'
        -    line 227: '  p5.EasyCam'
        -    line 228: '  p5.experience'
        -    line 229: '  p5.func'
        -    line 230: '  p5.geolocation'
        -    line 231: '  p5.gibber'
        -    line 232: '  grafica.js'
        -    line 233: '  p5.gui'
        -    line 234: '  p5.localmessage'
        -    line 235: '  marching'
        -    line 236: '  mappa'
        -    line 237: '  ml5.js'
        -    line 238: '  p5.play'
        -    line 239: '  p5.particle'
        -    line 240: '  p5.Riso'
        -    line 241: '  rita.js'
        -    line 242: '  Rotating Knobs'
        -    line 243: '  p5.scenemanager'
        -    line 244: '  p5.screenPosition'
        -    line 254: '  p5.serial'
        -    line 255: '  Shape5'
        -    line 256: '  p5.shape.js'
        -    line 257: '  p5.speech'
        -    line 258: '  p5.start2d.js'
        -    line 259: '  p5.tiledmap'
        -    line 260: '  p5.touchgui'
        -    line 261: '  tramontana'
        -    line 262: '  vida'
        -    line 263: '  p5.voronoi'
        -    line 264: '  p5.3D'
        -    line 272: '  sharing-title'
        -    line 273: '  sharing1'
        -    line 274: '  sharing2'
        -    line 275: '  sharing3'
        -    line 276: ''
        -    line 290: '  contributors-conference-title'
        -    line 291: '  contributors-conference1'
        -    line 292: '  contributors-conference2'
        -    line 293: '  participants-title'
        -    line 294: '  support-title'
        -    line 295: '  support1'
        -    line 296: '  support2'
        -    line 297: '  support3'
        -    line 298: '  support4'
        -    line 299: '  support5'
        -    line 300: '  support6'
        -    line 305: ''
        -    line 306: '  2015contributors-conference-title'
        -    line 307: '  2015contributors-conference-date'
        -    line 308: '  2015contributors-conference1'
        -    line 309: '  2015contributors-conference2'
        -    line 310: '  2015contributors-conference3'
        -    line 311: '  2015contributors-conference-diversity-title'
        -    line 312: '  2015contributors-conference-diversity1'
        -    line 313: '  2015contributors-conference-diversity2'
        -    line 314: '  2015contributors-conference-diversity3'
        -    line 315: '  2015contributors-conference-diversity4'
        -    line 316: '  2015contributors-conference-diversity5'
        -    line 317: '  2015contributors-conference-diversity6'
        -    line 318: '  2015contributors-conference-diversity7'
        -    line 319: '  2015contributors-conference-diversity8'
        -    line 320: '  2015contributors-conference-diversity9'
        -    line 321: '  2015cc_1'
        -    line 322: '  2015cc_2'
        -    line 323: '  2015cc_3'
        -    line 324: '  2015cc_4'
        -    line 325: '  2015cc_5'
        -    line 326: '  2015cc_6'
        -    line 327: '  2015cc_7'
        -    line 328: '  2015cc_8'
        -    line 329: '  2015cc_9'
        -    line 330: '  2015cc_10'
        -    line 331: '  2015cc_11'
        -    line 332: '  2015cc_12'
        -    line 333: '  2015cc_13'
        -    line 334: '  2015cc_14'
        -    line 335: '  2015cc_15'
        -    line 336: '  2019contributors-conference-title'
        -    line 337: '  2019contributors-conference-date'
        -    line 338: '  2019contributors-conference1'
        -    line 339: '  2019contributors-conference2'
        -    line 340: '  2019contributors-conference3'
        -    line 341: '  2019contributors-conference4'
        -    line 342: '  outputs'
        -    line 343: '  output1'
        -    line 344: '  output2'
        -    line 345: '  output3'
        -    line 346: '  output3-1'
        -    line 347: '  output4'
        -    line 348: '  output5'
        -    line 349: '  output6'
        -    line 350: '  output6-1'
        -    line 351: '  output6-2'
        -    line 352: '  output7'
        -    line 353: '  output8'
        -    line 354: '  output8-1'
        -    line 355: '  output9'
        -    line 356: '  output9-1'
        -    line 357: '  output10'
        -    line 358: '  output11'
        -    line 359: '  output12'
        -    line 360: '  output13'
        -    line 361: '  output14'
        -    line 362: '  output15'
        -    line 363: '  2019cc_1'
        -    line 364: '  2019cc_2'
        -    line 365: '  2019cc_3'
        -    line 366: '  2019cc_4'
        -    line 367: '  2019cc_5'
        -    line 368: '  2019cc_6'
        -    line 369: '  2019cc_7'
        -    line 370: '  2019cc_8'
        -    line 371: '  2019cc_9'
        -    line 372: '  2019cc_10'
        -    line 373: '  2019cc_11'
        -    line 374: '  2019cc_12'
        -    line 375: '  2019cc_13'
        -    line 376: '  2019cc_14'
        -    line 377: '  2019cc_15'
        -    line 378: '  2019cc_16'
        -    line 379: '  2019cc_17'
        -    line 380: '  2019cc_18'
        -    line 381: '  2019cc_19'
        -    line 382: '  2019cc_20'
        -    line 383: '  2019cc_21'
        -    line 384: '  2019cc_22'
        -    line 385: '  2019cc_23'
        -    line 386: '  2019cc_24'
        -    line 387: '  2019cc_25'
        +    line 39: '  p2x1'
        +    line 51: '  notes-title'
        +    line 52: '  notes1'
        +    line 53: '  notes2'
        +    line 54: '  notes3'
        +    line 55: '  notes4'
        +    line 56: '  notes5'
        +    line 64: '  book-1-title'
        +    line 65: '  book-1-authors'
        +    line 66: '  book-1-publisher'
        +    line 67: '  book-1-pages'
        +    line 68: '  book-1-type'
        +    line 69: '  book-1-description'
        +    line 70: '  book-1-order-a'
        +    line 71: '  book-1-order-b'
        +    line 72: '  book-2-title'
        +    line 73: '  book-2-authors'
        +    line 74: '  book-2-publisher'
        +    line 75: '  book-2-pages'
        +    line 76: '  book-2-type'
        +    line 77: '  book-2-description'
        +    line 78: '  book-2-order-a'
        +    line 79: '  book-2-order-b'
        +    line 80: '  book-3-title'
        +    line 81: '  book-3-authors'
        +    line 82: '  book-3-publisher'
        +    line 83: '  book-3-pages'
        +    line 84: '  book-3-type'
        +    line 85: '  book-3-description'
        +    line 86: '  book-3-order-a'
        +    line 87: '  book-3-order-b'
        +    line 88: '  book-4-title'
        +    line 89: '  book-4-authors'
        +    line 90: '  book-4-publisher'
        +    line 91: '  book-4-pages'
        +    line 92: '  book-4-type'
        +    line 93: '  book-4-description'
        +    line 94: '  book-4-order-a'
        +    line 95: '  book-4-order-b'
        +    line 96: '  book-5-title'
        +    line 97: '  book-5-authors'
        +    line 98: '  book-5-publisher'
        +    line 99: '  book-5-pages'
        +    line 100: '  book-5-type'
        +    line 101: '  book-5-description'
        +    line 102: '  book-5-order-a'
        +    line 103: '  book-5-order-b'
         zh-Hans:
           src/data/en.yml:
        -    line 49: '  RotatingKnobs'
        -    line 94: '  project-phuong'
        -    line 95: '  credit-phuong'
        -    line 98: '  credit-daein'
        -    line 107: '  credit-moon-xin'
        -    line 84: '  project-tag-curriculum'
        -    line 105: '  description-casey-louise'
        -    line 106: '  project-moon-xin'
        -    line 66: '  2015cc_5'
        -    line 75: showcase
        -    line 99: '  description-daein'
        -    line 108: '  description-moon-xin'
        -    line 89: '  project-tag-tool'
        -    line 90: '  project-tag-tutorial'
        -    line 91: '  project-roni'
        -    line 92: '  credit-roni'
        -    line 93: '  description-roni'
        -    line 96: '  description-phuong'
        -    line 97: '  project-daein'
        -    line 85: '  project-tag-documentation'
        -    line 86: '  project-tag-game'
        -    line 87: '  project-tag-library'
        -    line 15: Showcase
        -    line 74: ''
        -    line 76: '  showcase-title'
        -    line 88: '  project-tag-organizing'
        -    line 100: '  project-qianqian'
        -    line 101: '  credit-qianqian'
        -    line 102: '  description-qianqian'
        -    line 103: '  project-casey-louise'
        -    line 104: '  credit-casey-louise'
        -    line 7: Donate
        -    line 31: '  p5js-wiki-title'
        -    line 32: '  p5js-wiki'
        -    line 77: '  showcase-intro1'
        -    line 78: '  showcase-intro2'
        -    line 79: '  showcase-intro3'
        -    line 80: '  showcase-featuring'
        -    line 81: '  project-tag-art'
        -    line 82: '  project-tag-design'
        -    line 83: '  project-tag-code'
        -    line 52: '  p3xh2'
        -    line 44: '  p2x1'
        -    line 45: '  p2x2'
        -    line 48: '  p2x5'
        -    line 55: '  p3xp3'
        -    line 56: '  p3xp4'
        -    line 57: '  p3xp5'
        -    line 5: Editor
        -    line 46: '  p2x3'
        -    line 47: '  p2x4'
        -    line 50: '  p2x7'
        -    line 51: ''
        -    line 53: '  p3xp1'
        -    line 54: '  p3xp2'
        -    line 58: '  p3xp6'
        -    line 63: '  p4xp3'
        -    line 43: '  p2xh2'
        -    line 380: '  2019cc_18'
        -    line 373: '  2019cc_11'
        -    line 381: '  2019cc_19'
        -    line 371: '  2019cc_9'
        -    line 358: '  output11'
        -    line 364: '  2019cc_2'
        -    line 368: '  2019cc_6'
        -    line 377: '  2019cc_15'
        -    line 363: '  2019cc_1'
        -    line 329: '  2015cc_9'
        -    line 341: '  2019contributors-conference4'
        -    line 386: '  2019cc_24'
        -    line 359: '  output12'
        -    line 362: '  output15'
        -    line 374: '  2019cc_12'
        -    line 376: '  2019cc_14'
        -    line 379: '  2019cc_17'
        -    line 382: '  2019cc_20'
        -    line 355: '  output9'
        -    line 356: '  output9-1'
        -    line 360: '  output13'
        -    line 357: '  output10'
        -    line 361: '  output14'
        -    line 1: Skip-To-Content
        -    line 39: '  start-creating'
        -    line 40: '  p1xh1'
        -    line 41: '  p1x1'
        -    line 42: '  p1x2'
        -    line 59: ''
        -    line 60: '  p4xh2'
        -    line 61: '  p4xp1'
        -    line 62: '  p4xp2'
        -    line 64: '  p4xp4'
        -    line 65: '  p4xp5'
        -    line 2: Language-Settings
        -    line 3: Sidebar-Title
        -    line 67: ''
        -    line 370: '  2019cc_8'
        -    line 372: '  2019cc_10'
        -    line 383: '  2019cc_21'
        -    line 151: '  report-bugs'
        -    line 168: '  support-23'
        -    line 72: '  sketch_info_link'
        -    line 8: Start
        -    line 16: footerxh1
        -    line 71: '  sketch_info'
        -    line 117: '  book1'
        -    line 121: '  download-intro'
        -    line 122: '  editor-title'
        -    line 123: '  p5.js-editor'
        -    line 124: '  p5.js-editor-intro'
        -    line 125: '  editor-includes'
        -    line 127: '  complete-library-intro1'
        -    line 128: '  complete-library-intro2'
        -    line 129: '  complete-library-intro3'
        -    line 133: '  includes-2'
        -    line 136: '  single-files-intro'
        -    line 148: '  etc-title'
        -    line 149: '  older-releases'
        -    line 150: '  github-repository'
        -    line 153: ''
        -    line 155: '  support-options'
        -    line 164: '  support-20'
        -    line 176: '  support-17-alt'
        -    line 177: '  support-18-alt'
        -    line 178: '  support-19-alt'
        -    line 179: '  support-20-alt'
        -    line 180: '  support-21-alt'
        -    line 181: '  support-22-alt'
        -    line 182: '  support-23-alt'
        -    line 183: '  support-24-alt'
        -    line 184: '  support-25-alt'
        -    line 185: '  support-26-alt'
        -    line 186: '  support-27-alt'
        -    line 187: '  support-28-alt'
        -    line 188: '  support-29-alt'
        -    line 189: '  support-30-alt'
        -    line 190: '  support-30-alt'
        -    line 191: '  support-31-alt'
        -    line 200: '  core-libraries'
        -    line 201: '  community-libraries'
        -    line 202: '  libraries-created-by'
        -    line 213: '  asciiart'
        -    line 214: '  p5.ble'
        -    line 215: '  blizard.js'
        -    line 222: '  p5.clickable'
        -    line 223: '  p5.cmyk.js'
        -    line 224: '  p5.collide2D'
        -    line 225: '  p5.createloop'
        -    line 226: '  p5.dimensions'
        -    line 227: '  p5.EasyCam'
        -    line 228: '  p5.experience'
        -    line 229: '  p5.func'
        -    line 230: '  p5.geolocation'
        -    line 231: '  p5.gibber'
        -    line 232: '  grafica.js'
        -    line 233: '  p5.gui'
        -    line 234: '  p5.localmessage'
        -    line 235: '  marching'
        -    line 236: '  mappa'
        -    line 237: '  ml5.js'
        -    line 238: '  p5.play'
        -    line 239: '  p5.particle'
        -    line 240: '  p5.Riso'
        -    line 241: '  rita.js'
        -    line 242: '  Rotating Knobs'
        -    line 243: '  p5.scenemanager'
        -    line 244: '  p5.screenPosition'
        -    line 254: '  p5.serial'
        -    line 255: '  Shape5'
        -    line 256: '  p5.shape.js'
        -    line 257: '  p5.speech'
        -    line 258: '  p5.start2d.js'
        -    line 259: '  p5.tiledmap'
        -    line 260: '  p5.touchgui'
        -    line 261: '  tramontana'
        -    line 262: '  vida'
        -    line 263: '  p5.voronoi'
        -    line 264: '  p5.3D'
        -    line 272: '  sharing-title'
        -    line 273: '  sharing1'
        -    line 274: '  sharing2'
        -    line 275: '  sharing3'
        -    line 276: ''
        -    line 290: '  contributors-conference-title'
        -    line 291: '  contributors-conference1'
        -    line 292: '  contributors-conference2'
        -    line 293: '  participants-title'
        -    line 294: '  support-title'
        -    line 295: '  support1'
        -    line 296: '  support2'
        -    line 297: '  support3'
        -    line 298: '  support4'
        -    line 299: '  support5'
        -    line 300: '  support6'
        -    line 305: ''
        -    line 306: '  2015contributors-conference-title'
        -    line 307: '  2015contributors-conference-date'
        -    line 308: '  2015contributors-conference1'
        -    line 309: '  2015contributors-conference2'
        -    line 310: '  2015contributors-conference3'
        -    line 311: '  2015contributors-conference-diversity-title'
        -    line 312: '  2015contributors-conference-diversity1'
        -    line 313: '  2015contributors-conference-diversity2'
        -    line 314: '  2015contributors-conference-diversity3'
        -    line 315: '  2015contributors-conference-diversity4'
        -    line 316: '  2015contributors-conference-diversity5'
        -    line 317: '  2015contributors-conference-diversity6'
        -    line 318: '  2015contributors-conference-diversity7'
        -    line 319: '  2015contributors-conference-diversity8'
        -    line 320: '  2015contributors-conference-diversity9'
        -    line 321: '  2015cc_1'
        -    line 322: '  2015cc_2'
        -    line 323: '  2015cc_3'
        -    line 324: '  2015cc_4'
        -    line 325: '  2015cc_5'
        -    line 326: '  2015cc_6'
        -    line 327: '  2015cc_7'
        -    line 328: '  2015cc_8'
        -    line 330: '  2015cc_10'
        -    line 331: '  2015cc_11'
        -    line 332: '  2015cc_12'
        -    line 333: '  2015cc_13'
        -    line 334: '  2015cc_14'
        -    line 335: '  2015cc_15'
        -    line 336: '  2019contributors-conference-title'
        -    line 337: '  2019contributors-conference-date'
        -    line 338: '  2019contributors-conference1'
        -    line 339: '  2019contributors-conference2'
        -    line 340: '  2019contributors-conference3'
        -    line 342: '  outputs'
        -    line 343: '  output1'
        -    line 344: '  output2'
        -    line 345: '  output3'
        -    line 346: '  output3-1'
        -    line 347: '  output4'
        -    line 348: '  output5'
        -    line 349: '  output6'
        -    line 350: '  output6-1'
        -    line 351: '  output6-2'
        -    line 352: '  output7'
        -    line 353: '  output8'
        -    line 354: '  output8-1'
        -    line 365: '  2019cc_3'
        -    line 366: '  2019cc_4'
        -    line 367: '  2019cc_5'
        -    line 369: '  2019cc_7'
        -    line 375: '  2019cc_13'
        -    line 378: '  2019cc_16'
        -    line 384: '  2019cc_22'
        -    line 385: '  2019cc_23'
        -    line 387: '  2019cc_25'
        -    line 559: '  output3-1'
        -    line 568: '  output9'
        -    line 569: '  output9-1'
        -    line 555: '  output1'
        -    line 565: '  output8'
        -    line 566: '  output8-1'
        -    line 572: '  output14'
        -    line 554: '  outputs'
        -    line 556: '  output2'
        -    line 557: '  output3'
        -    line 558: '  output3-1'
        -    line 560: '  output5'
        -    line 561: '  output6'
        -    line 562: '  output6-1'
        -    line 563: '  output6-2'
        -    line 564: '  output7'
        -    line 567: '  output9'
        -    line 570: '  output12'
        -    line 571: '  output13'
        -    line 581: '  2019cc_25'
        -    line 413: '  p5.EasyCam'
        -    line 552: '  2019contributors-conference2'
        -    line 412: '  p5.EasyCam'
        -    line 425: '  p5.touchgui'
        -    line 13: '  start-creating'
        -    line 109: '  2019cc_21'
        -    line 110: '  2019cc_22'
        -    line 111: '  2019cc_23'
        -    line 545: '  2019contributors-conference-date'
        -    line 504: '  participants-title'
        -    line 505: '  support-title'
        -    line 506: '  support1'
        -    line 507: '  support2'
        -    line 508: '  support3'
        -    line 509: '  support4'
        -    line 510: '  support5'
        -    line 511: '  support6'
        -    line 34: '  p2xh2'
        -    line 391: '  p5.localmessage'
        -    line 399: '  Rotating Knobs'
        -    line 401: '  p5.screenPosition'
        -    line 404: '  Shape5'
        -    line 406: '  p5.start.js'
        -    line 407: '  p5.start2d.js'
        -    line 409: '  tramontana'
        +    line 39: '  p2x1'
        +    line 51: '  notes-title'
        +    line 52: '  notes1'
        +    line 53: '  notes2'
        +    line 54: '  notes3'
        +    line 55: '  notes4'
        +    line 56: '  notes5'
        +    line 99: '  book-5-pages'
        +    line 64: '  book-1-title'
        +    line 65: '  book-1-authors'
        +    line 66: '  book-1-publisher'
        +    line 67: '  book-1-pages'
        +    line 68: '  book-1-type'
        +    line 69: '  book-1-description'
        +    line 70: '  book-1-order-a'
        +    line 71: '  book-1-order-b'
        +    line 72: '  book-2-title'
        +    line 73: '  book-2-authors'
        +    line 74: '  book-2-publisher'
        +    line 75: '  book-2-pages'
        +    line 76: '  book-2-type'
        +    line 77: '  book-2-description'
        +    line 78: '  book-2-order-a'
        +    line 79: '  book-2-order-b'
        +    line 80: '  book-3-title'
        +    line 81: '  book-3-authors'
        +    line 82: '  book-3-publisher'
        +    line 83: '  book-3-pages'
        +    line 84: '  book-3-type'
        +    line 85: '  book-3-description'
        +    line 86: '  book-3-order-a'
        +    line 87: '  book-3-order-b'
        +    line 88: '  book-4-title'
        +    line 89: '  book-4-authors'
        +    line 90: '  book-4-publisher'
        +    line 91: '  book-4-pages'
        +    line 92: '  book-4-type'
        +    line 93: '  book-4-description'
        +    line 94: '  book-4-order-a'
        +    line 95: '  book-4-order-b'
        +    line 96: '  book-5-title'
        +    line 97: '  book-5-authors'
        +    line 98: '  book-5-publisher'
        +    line 100: '  book-5-type'
        +    line 101: '  book-5-description'
        +    line 102: '  book-5-order-a'
        +    line 103: '  book-5-order-b'
        +    line 480: '  notes3'
        +    line 44: '  description-roni'
        +    line 45: '  project-phuong'
        +    line 17: Showcase
        +    line 25: ''
        +    line 26: showcase
        +    line 27: '  showcase-title'
        +    line 28: '  showcase-intro1'
        +    line 29: '  showcase-intro2'
        +    line 30: '  showcase-intro3'
        +    line 31: '  showcase-featuring'
        +    line 32: '  project-tag-art'
        +    line 33: '  project-tag-design'
        +    line 34: '  project-tag-code'
        +    line 35: '  project-tag-curriculum'
        +    line 36: '  project-tag-documentation'
        +    line 37: '  project-tag-game'
        +    line 38: '  project-tag-library'
        +    line 40: '  project-tag-tool'
        +    line 41: '  project-tag-tutorial'
        +    line 42: '  project-roni'
        +    line 43: '  credit-roni'
        +    line 46: '  credit-phuong'
        +    line 47: '  description-phuong'
        +    line 48: '  project-daein'
        +    line 49: '  credit-daein'
        +    line 50: '  description-daein'
        +    line 57: '  project-moon-xin'
        +    line 58: '  credit-moon-xin'
        +    line 59: '  description-moon-xin'
        +    line 516: '  showcase-intro3'
        +    line 517: '  showcase-featuring'
        +    line 518: '  project-tag-art'
        +    line 519: '  project-tag-design'
        +    line 520: '  project-tag-code'
        +    line 521: '  project-tag-curriculum'
        +    line 522: '  project-tag-documentation'
        +    line 523: '  project-tag-game'
        +    line 524: '  project-tag-library'
        +    line 525: '  project-tag-organizing'
        +    line 526: '  project-tag-tool'
        +    line 527: '  project-tag-tutorial'
        +    line 531: '  description-roni'
        +    line 358: '  p5.ble'
        +    line 364: '  p5.createloop'
        +    line 368: '  p5.experience'
        +    line 377: '  vida'
        +    line 380: '  p5.3D'
        +    line 363: '  p5.experience'
        +    line 329: '  coordinate-system-simple-shapes-p2x1'
        +    line 341: '  coordinate-system-simple-shapes-p9x1'
        +    line 108: '  coordinate-system-simple-shapes-p2x1'
             line 120: '  coordinate-system-simple-shapes-p9x1'
        -    line 38: '  p1xh1'
        -    line 4: Sidebar-Title
        -    line 400: '  p5.collide2D'
        -    line 402: '  p5.dimensions'
        -    line 403: '  p5.experience'
        -    line 405: '  p5.geolocation'
        -    line 408: '  p5.gui'
        -    line 410: '  p5.play'
        -    line 411: '  p5.particle'
        -    line 424: '  p5.serial'
        -    line 426: '  p5.tiledmap'
        -    line 427: '  vida'
        -    line 428: '  p5.voronoi'
        -    line 429: '  p5.3D'
        -    line 156: '  etc-title'
        -    line 157: '  older-releases'
        -    line 158: '  github-repository'
        -    line 159: '  report-bugs'
        -    line 392: '  marching'
        -    line 394: '  ml5.js'
        -    line 397: '  p5.Riso'
        -    line 476: '  contributors-conference-title'
        -    line 477: '  contributors-conference1'
        -    line 478: '  contributors-conference2'
        -    line 479: '  contributors-conference3'
        -    line 480: '  contributors-conference4'
        -    line 485: ''
        -    line 486: '  2015contributors-conference-title'
        -    line 487: '  2015contributors-conference-date'
        -    line 488: '  2015contributors-conference1'
        -    line 489: '  2015contributors-conference2'
        -    line 490: '  2015contributors-conference3'
        -    line 491: '  2015contributors-conference-participants-title'
        -    line 492: '  2015contributors-conference-diversity-title'
        -    line 493: '  2015contributors-conference-diversity1'
        -    line 494: '  2015contributors-conference-diversity2'
        -    line 495: '  2015contributors-conference-diversity3'
        -    line 496: '  2015contributors-conference-diversity4'
        -    line 497: '  2015contributors-conference-diversity5'
        -    line 498: '  2015contributors-conference-diversity6'
        -    line 499: '  2015contributors-conference-diversity7'
        -    line 500: '  2015contributors-conference-diversity8'
        -    line 501: '  2015contributors-conference-diversity9'
        -    line 502: '  2015contributors-conference-support-title'
        -    line 503: '  2015contributors-conference-support1'
        -    line 512: '  2015cc_4'
        -    line 513: '  2015cc_5'
        -    line 514: '  2015cc_6'
        -    line 515: '  2015cc_7'
        -    line 516: '  2015cc_8'
        -    line 517: '  2015cc_9'
        -    line 518: '  2015cc_10'
        -    line 519: '  2015cc_11'
        -    line 520: '  2015cc_12'
        -    line 521: '  2015cc_13'
        -    line 522: '  2015cc_14'
        -    line 523: '  2015cc_15'
        -    line 139: '  download-intro'
        -    line 140: '  editor-title'
        -    line 141: '  p5.js-editor'
        -    line 142: '  p5.js-editor-intro'
        -    line 143: '  editor-includes'
        -    line 145: '  complete-library-intro1'
        -    line 146: '  complete-library-intro2'
        -    line 147: '  complete-library-intro3'
        -    line 154: '  single-files-intro'
        -    line 541: '  2019contributors-conference-title'
        -    line 542: '  2019contributors-conference-date'
        -    line 546: '  2019contributors-conference2'
        -    line 547: '  2019contributors-conference3'
        -    line 548: '  2019contributors-conference4'
        -    line 549: '  2019cc_1'
        -    line 550: '  2019cc_2'
        -    line 551: '  2019cc_3'
        -    line 553: '  2019cc_5'
        -    line 21: '  support-options'
        -    line 112: '  2019cc_24'
        -    line 420: '  p5.shape.js'
        -    line 573: '  output15'
        +    line 386: '  create-your-own4'
        +    line 359: '  p5.clickable'
        +    line 362: '  p5.dimensions1'
        +    line 373: '  mappa'
        +    line 374: '  p5.play'
        +    line 376: '  rita.js'
        +    line 379: '  p5.serial1'
        +    line 381: '  p5.serial3'
        +    line 382: '  p5.speech'
        +    line 391: '  p5.3D'
        +    line 355: '  asciiart'
        +    line 356: '  p5.ble'
        +    line 360: '  p5.createloop'
        +    line 371: '  vida'
        +    line 357: '  asciiart'
        +    line 361: '  p5.clickable'
        +    line 12: Showcase
        +    line 20: ''
        +    line 21: showcase
        +    line 22: '  Showcase'
        +    line 23: '  test'
        +    line 515: '  showcase-title'
        +    line 528: '  project-qianqian'
        +    line 529: '  credit-qianqian'
        +    line 530: '  description-qianqian'
        +    line 532: '  credit-conchinha-lessel'
        +    line 533: '  description-conchinha-lessel'
        +    line 535: '  description-phuong'
        +    line 539: '  description-daein'
        +    line 546: '  description-qianqian'
        +    line 547: '  project-casey-louise'
        +    line 548: '  credit-casey-louise'
        +    line 549: '  description-casey-louise'
        +    line 550: '  project-moon-xin'
        +    line 551: '  credit-moon-xin'
        +    line 552: '  description-moon-xin'
        +    line 669: '  credit-moon-xin'
        +    line 481: '  notes1'
        +    line 482: '  notes2'
        +    line 483: '  notes3'
        +    line 484: '  notes4'
        +    line 485: '  notes5'
        +    line 608: '  book-1-authors'
        +    line 617: '  book-2-authors'
        diff --git a/offline-reference/extra/css/main.css b/offline-reference/extra/css/main.css
        index 0208315b09..c81131033d 100644
        --- a/offline-reference/extra/css/main.css
        +++ b/offline-reference/extra/css/main.css
        @@ -89,6 +89,7 @@
             padding: 0.4em;
             margin: 1em 1.75em 0 0;
             width: 18.65em;
        +    float: left;
             color: #333 !important;
             height:7.45em;
             position: relative;
        diff --git a/offline-reference/extra/index.html b/offline-reference/extra/index.html
        index 54cec4f0ac..45905e95f3 100644
        --- a/offline-reference/extra/index.html
        +++ b/offline-reference/extra/index.html
        @@ -86,7 +86,6 @@
         
             <script src="./js/p5.min.js"></script>
             <script src="./js/p5.sound.min.js"></script>
        -    <script src="./js/p5.dom.min.js"></script>
             <script src="./js/render.js"></script>
             <!-- prism for code highlighting -->
             <script src="./js/vendor/prism.js"></script>
        diff --git a/offline-reference/extra/js/reference.js b/offline-reference/extra/js/reference.js
        index c4f5b394a6..b16a49d3d1 100644
        --- a/offline-reference/extra/js/reference.js
        +++ b/offline-reference/extra/js/reference.js
        @@ -4595,7 +4595,7 @@ define('router',[
             get: function(searchClass, searchItem) {
         
               // if looking for a library page, redirect
        -      if ((searchClass === 'p5.dom' || searchClass === 'p5.sound')
        +      if (searchClass === 'p5.sound')
                   && !searchItem) {
                 window.location.hash = '/libraries/'+searchClass;
                 return;
        @@ -4743,7 +4743,7 @@ require([
           './documented-method'], function(App, DocumentedMethod) {
         
           // Set collections
        -  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];
        +  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];
         
           // Get json API data
           var data = referenceData;
        @@ -4767,9 +4767,6 @@ require([
             if (m.name == "p5.sound") {
               App.sound.module = m;
             }
        -    else if (m.name == "p5.dom") {
        -      App.dom.module = m;
        -    }
           });
         
         
        @@ -4803,12 +4800,6 @@ require([
               if (el.module === "p5.sound") {
                 App.sound.items.push(el);
               }
        -      else if (el.module === "p5.dom" || el.module === 'DOM') {
        -        if (el.class === 'p5.dom') {
        -          el.class = 'p5';
        -        }
        -        App.dom.items.push(el);
        -      }
             }
           });
         
        diff --git a/package-lock.json b/package-lock.json
        index a22b5b54a4..8b32dc5b08 100644
        --- a/package-lock.json
        +++ b/package-lock.json
        @@ -516,8 +516,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
               "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "arch": {
               "version": "2.1.1",
        @@ -622,7 +621,6 @@
               "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
               "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "delegates": "^1.0.0",
                 "readable-stream": "^2.0.6"
        @@ -2759,7 +2757,6 @@
                   "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
                   "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "p-finally": "^1.0.0"
                   }
        @@ -3164,7 +3161,6 @@
               "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
               "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "get-proxy": "^2.0.0",
                 "isurl": "^1.0.0-alpha5",
        @@ -3517,7 +3513,6 @@
               "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
               "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "graceful-readlink": ">= 1.0.0"
               }
        @@ -3870,7 +3865,6 @@
               "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
               "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "ini": "^1.3.4",
                 "proto-list": "~1.2.1"
        @@ -3898,8 +3892,7 @@
               "version": "1.1.0",
               "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
               "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "console-stream": {
               "version": "0.1.1",
        @@ -3913,7 +3906,6 @@
               "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
               "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "safe-buffer": "5.1.2"
               }
        @@ -4677,7 +4669,6 @@
               "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
               "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.0.0",
                 "decompress-tarbz2": "^4.0.0",
        @@ -4694,7 +4685,6 @@
               "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
               "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "mimic-response": "^1.0.0"
               }
        @@ -4704,7 +4694,6 @@
               "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
               "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "file-type": "^5.2.0",
                 "is-stream": "^1.1.0",
        @@ -4715,8 +4704,7 @@
                   "version": "5.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
                   "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4725,7 +4713,6 @@
               "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
               "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.1.0",
                 "file-type": "^6.1.0",
        @@ -4738,8 +4725,7 @@
                   "version": "6.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
                   "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4748,7 +4734,6 @@
               "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
               "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "decompress-tar": "^4.1.1",
                 "file-type": "^5.2.0",
        @@ -4759,8 +4744,7 @@
                   "version": "5.2.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
                   "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -4769,7 +4753,6 @@
               "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
               "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "file-type": "^3.8.0",
                 "get-stream": "^2.2.0",
        @@ -4781,15 +4764,13 @@
                   "version": "3.9.0",
                   "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
                   "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 },
                 "get-stream": {
                   "version": "2.3.1",
                   "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
                   "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "object-assign": "^4.0.1",
                     "pinkie-promise": "^2.0.0"
        @@ -4896,8 +4877,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
               "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "delimiter-regex": {
               "version": "2.0.0",
        @@ -5117,8 +5097,7 @@
               "version": "0.1.4",
               "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
               "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "duplexify": {
               "version": "3.6.0",
        @@ -5745,7 +5724,6 @@
               "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
               "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "cross-spawn": "^5.0.1",
                 "get-stream": "^3.0.0",
        @@ -6040,7 +6018,6 @@
               "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
               "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "mime-db": "^1.28.0"
               }
        @@ -6050,7 +6027,6 @@
               "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
               "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "ext-list": "^2.0.0",
                 "sort-keys-length": "^1.0.0"
        @@ -6496,7 +6472,6 @@
               "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
               "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "pend": "~1.2.0"
               }
        @@ -6611,15 +6586,13 @@
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
               "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "filenamify": {
               "version": "2.1.0",
               "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz",
               "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "filename-reserved-regex": "^2.0.0",
                 "strip-outer": "^1.0.0",
        @@ -6956,7 +6929,6 @@
               "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
               "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "graceful-fs": "^4.1.2",
                 "inherits": "~2.0.0",
        @@ -6981,7 +6953,6 @@
               "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
               "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "aproba": "^1.0.3",
                 "console-control-strings": "^1.0.0",
        @@ -6998,7 +6969,6 @@
                   "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
                   "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "code-point-at": "^1.0.0",
                     "is-fullwidth-code-point": "^1.0.0",
        @@ -7072,7 +7042,6 @@
               "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
               "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "npm-conf": "^1.1.0"
               }
        @@ -7087,8 +7056,7 @@
               "version": "3.0.0",
               "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
               "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "get-value": {
               "version": "2.0.6",
        @@ -7525,8 +7493,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
               "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "gray-matter": {
               "version": "3.1.1",
        @@ -8496,8 +8463,7 @@
               "version": "1.4.2",
               "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
               "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "has-symbols": {
               "version": "1.0.1",
        @@ -8510,7 +8476,6 @@
               "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
               "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "has-symbol-support-x": "^1.4.1"
               }
        @@ -8519,8 +8484,7 @@
               "version": "2.0.1",
               "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
               "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "has-value": {
               "version": "0.3.1",
        @@ -8941,7 +8905,6 @@
                   "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
                   "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "color-convert": "^1.9.0"
                   }
        @@ -8951,7 +8914,6 @@
                   "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
                   "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "ansi-styles": "^3.2.1",
                     "escape-string-regexp": "^1.0.5",
        @@ -8984,8 +8946,7 @@
                   "version": "3.0.0",
                   "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
                   "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 },
                 "is-svg": {
                   "version": "3.0.0",
        @@ -9002,7 +8963,6 @@
                   "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
                   "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "has-flag": "^3.0.0"
                   }
        @@ -9586,8 +9546,7 @@
               "version": "4.0.1",
               "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
               "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-number": {
               "version": "2.1.0",
        @@ -9628,8 +9587,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
               "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-observable": {
               "version": "1.1.0",
        @@ -9697,8 +9655,7 @@
               "version": "1.1.0",
               "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
               "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-plain-object": {
               "version": "2.0.4",
        @@ -9789,8 +9746,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
               "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "is-stream": {
               "version": "1.1.0",
        @@ -9912,7 +9868,6 @@
               "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
               "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "has-to-string-tag-x": "^1.2.0",
                 "is-object": "^1.0.1"
        @@ -11555,8 +11510,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
               "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "lpad-align": {
               "version": "1.1.2",
        @@ -12154,8 +12108,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
               "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "minimatch": {
               "version": "3.0.4",
        @@ -12424,8 +12377,7 @@
               "version": "1.0.5",
               "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
               "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "no-case": {
               "version": "2.3.2",
        @@ -12652,7 +12604,6 @@
               "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
               "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "config-chain": "^1.1.11",
                 "pify": "^3.0.0"
        @@ -12662,8 +12613,7 @@
                   "version": "3.0.0",
                   "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
                   "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
        -          "dev": true,
        -          "optional": true
        +          "dev": true
                 }
               }
             },
        @@ -12672,7 +12622,6 @@
               "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
               "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "path-key": "^2.0.0"
               }
        @@ -12682,7 +12631,6 @@
               "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
               "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "are-we-there-yet": "~1.1.2",
                 "console-control-strings": "~1.1.0",
        @@ -13044,8 +12992,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
               "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "p-is-promise": {
               "version": "1.1.0",
        @@ -13106,7 +13053,6 @@
               "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
               "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "p-finally": "^1.0.0"
               }
        @@ -13276,8 +13222,7 @@
               "version": "2.0.1",
               "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
               "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "path-parse": {
               "version": "1.0.6",
        @@ -13317,8 +13262,7 @@
               "version": "1.2.0",
               "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
               "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "picomatch": {
               "version": "2.2.1",
        @@ -15788,8 +15732,7 @@
               "version": "1.2.4",
               "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
               "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "pseudomap": {
               "version": "1.0.2",
        @@ -16919,7 +16862,6 @@
               "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
               "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "commander": "~2.8.1"
               }
        @@ -17142,8 +17084,7 @@
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
               "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "set-getter": {
               "version": "0.1.0",
        @@ -17431,7 +17372,6 @@
               "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
               "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "is-plain-obj": "^1.0.0"
               }
        @@ -17441,7 +17381,6 @@
               "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
               "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "sort-keys": "^1.0.0"
               }
        @@ -17905,7 +17844,6 @@
               "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
               "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "is-natural-number": "^4.0.1"
               }
        @@ -17914,8 +17852,7 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
               "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "strip-final-newline": {
               "version": "2.0.0",
        @@ -17951,7 +17888,6 @@
               "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
               "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "escape-string-regexp": "^1.0.2"
               }
        @@ -18270,15 +18206,13 @@
               "version": "1.0.0",
               "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz",
               "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "tempfile": {
               "version": "2.0.0",
               "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz",
               "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "temp-dir": "^1.0.0",
                 "uuid": "^3.0.1"
        @@ -18619,8 +18553,7 @@
               "version": "4.0.1",
               "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
               "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "timers-browserify": {
               "version": "2.0.2",
        @@ -18925,7 +18858,6 @@
               "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
               "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "escape-string-regexp": "^1.0.2"
               }
        @@ -19004,7 +18936,6 @@
               "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz",
               "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "buffer": "^5.2.1",
                 "through": "^2.3.8"
        @@ -19015,7 +18946,6 @@
                   "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz",
                   "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==",
                   "dev": true,
        -          "optional": true,
                   "requires": {
                     "base64-js": "^1.0.2",
                     "ieee754": "^1.1.4"
        @@ -19286,8 +19216,7 @@
               "version": "1.0.1",
               "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
               "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
        -      "dev": true,
        -      "optional": true
        +      "dev": true
             },
             "use": {
               "version": "1.1.2",
        @@ -19679,7 +19608,6 @@
               "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
               "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "string-width": "^1.0.2 || 2"
               }
        @@ -19810,7 +19738,6 @@
               "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
               "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
               "dev": true,
        -      "optional": true,
               "requires": {
                 "buffer-crc32": "~0.2.3",
                 "fd-slicer": "~1.1.0"
        diff --git a/src/assets/css/main.css b/src/assets/css/main.css
        index cd732b573a..e18fe7895f 100644
        --- a/src/assets/css/main.css
        +++ b/src/assets/css/main.css
        @@ -87,6 +87,8 @@
           .sidebar-menu a {
             display: block;
             text-align: center;
        +    padding-bottom: 0.11em;
        +    border-bottom: 0.11em dashed transparent;
           }
         
           .sidebar-menu-icon {
        @@ -224,6 +226,7 @@
           padding: 0.4em;
           margin: 0 1.75em 0 0;
           width: 18.65em;
        +  float: left;
           color: #333 !important;
           height: 7.45em;
           position: relative;
        @@ -438,6 +441,14 @@ div.reference-subgroup {
           margin: 1em 0 0 0;
         }
         
        +#item ul {
        +  margin-top: 0.5em;
        +}
        +
        +#item li {
        +  margin-bottom: 1em;
        +}
        +
         .description {
           clear: both;
           display: block;
        @@ -452,7 +463,8 @@ div.reference-subgroup {
         
         .paramname {
           display: inline-block;
        -  width: 8em;
        +  min-width: 25%;
        +  margin-right: 1%;
           font-size: 1.2em;
         }
         
        @@ -464,10 +476,18 @@ div.reference-subgroup {
         .paramtype {
           display: inline-block;
           font-size: 1.2em;
        -  width: 20em;
        +  width: 73%;
           vertical-align: top;
         }
         
        +#library-page .group-name{
        +  display: inline-block;
        +}
        +
        +#library-page .group-name:hover  {
        +  color: #ED225D;
        +}
        +
         
         /* EXAMPLES IN REF */
         
        @@ -908,6 +928,10 @@ h3.contribute-title {
           position: relative;
         }
         
        +.label .nounderline img{
        +  margin: .5em 0 0 0
        +}
        +
         .label h3 {
           color: white;
           position: absolute;
        @@ -1224,6 +1248,14 @@ img.gallery-img {
           transition: all 0.3s;
         }
         
        +@media (max-width: 500px) {	
        +  #showcase-page .nominate a,
        +  #showcase-page .nominate a:visited {
        +    padding: 0.4em 0.3em;
        +    font: 1.3rem "Montserrat", sans-serif;
        +  }	
        +}
        +
         #showcase-page .nominate a:hover {
           top: 4px;
           left: 4px;
        @@ -1702,6 +1734,10 @@ ul {
           list-style: none;
         }
         
        +ol {
        +  font-size: 1.2em;
        +}
        +
         li {
           margin: 0;
           padding: 0;
        @@ -1715,6 +1751,10 @@ ul.list_view {
           font-size: 1.2em;
         }
         
        +ol ul.list_view {
        +  font-size: 1em;
        +}
        +
         ul.inside {
           margin: 0 0 0 2em;
           padding: 0;
        @@ -2099,9 +2139,7 @@ footer {
           .column.group-name {
             margin-bottom: 1em;
           }
        -  #library-page .group-name:hover {
        -    color: #ED225D;
        -  }
        +
           #library-page .group-name {
             margin: 2em 0 0.5em 0;
           }
        @@ -2238,6 +2276,9 @@ footer {
           footer {
             font-size: 0.5em;
           }
        +  .paramtype {
        +    width: 96%;
        +  }
         }
         
         @media (max-width:400px) {
        @@ -2385,15 +2426,15 @@ iframe {
         
         #get-started-page #asterisk-design-element,
         #community-page #asterisk-design-element {
        -  top: -30%;
        -  right: -40%;
        -  height: 44em;
        -  width: 44em;
        -  -webkit-transform: rotate(9deg);
        -  -moz-transform: rotate(9deg);
        -  -ms-transform: rotate(9deg);
        -  -o-transform: rotate(9deg);
        -  transform: rotate(9deg);
        +  top: 10%;
        +  right: -20%;
        +  height: 30em;
        +  width: 30em;
        +  -webkit-transform: rotate(2deg);
        +  -moz-transform: rotate(2deg);
        +  -ms-transform: rotate(2deg);
        +  -o-transform: rotate(2deg);
        +  transform: rotate(2deg);
         }
         
         #reference-page #asterisk-design-element,
        @@ -2420,10 +2461,26 @@ iframe {
           transition: border-bottom 30ms linear;
           width: 13em;
         }
        -.email-octopus-form-row-subscribe button, .email-octopus-form-row-hp {
        +
        +.email-octopus-form-row-hp {
           position: absolute;
           left: -5000px;
         }
        +
        +.email-octopus-form-row button {
        +  border: 1px solid #ED225D;
        +  color: #ED225D;
        +  padding: 0.4em 0.6em;
        +  margin: 1em 0 0 0;
        +  font-family: "Montserrat", sans-serif;
        +  display: block;
        +}
        +
        +.email-octopus-form-row button:hover {
        +  background-color: #ED225D;
        +  color: white;
        +}
        +
         .email-octopus-email-address::-webkit-input-placeholder { color:#ABABAB; }
         .email-octopus-email-address::-moz-placeholder { color:#ABABAB; }
         .email-octopus-email-address:-moz-placeholder { color:#ABABAB; }
        @@ -2431,7 +2488,12 @@ iframe {
         
         @media (min-width: 720px) {
           .email-octopus-email-address {
        -    width: 20em;
        +    width: 16em;
           }
         
        +  .email-octopus-form-row button {
        +    margin: 0;
        +    margin-left: 0.5em;
        +    display: inline;
        +  }
         }
        diff --git a/src/assets/img/books/generative_design.jpg b/src/assets/img/books/generative_design.jpg
        new file mode 100644
        index 0000000000000000000000000000000000000000..deaf9a20b113bede59c4b00c58faea6267875769
        GIT binary patch
        literal 138449
        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
        
        literal 0
        HcmV?d00001
        
        diff --git a/src/assets/img/books/generative_gestaltung.jpg b/src/assets/img/books/generative_gestaltung.jpg
        new file mode 100644
        index 0000000000000000000000000000000000000000..433843daa6880e18aa9733f3478eb233b14c5c55
        GIT binary patch
        literal 88666
        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%0Aju>7_
        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
        
        literal 0
        HcmV?d00001
        
        diff --git a/src/assets/img/books/learn_javascript.jpg b/src/assets/img/books/learn_javascript.jpg
        new file mode 100644
        index 0000000000000000000000000000000000000000..d786444e2e86843d4753b56b5bf82538692e25e1
        GIT binary patch
        literal 55524
        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
        
        literal 0
        HcmV?d00001
        
        diff --git a/src/assets/js/render.js b/src/assets/js/render.js
        index 832e8351c0..8af9c9f8d5 100644
        --- a/src/assets/js/render.js
        +++ b/src/assets/js/render.js
        @@ -152,13 +152,18 @@ var renderCode = function(exampleName) {
                   edit_area.style.display = 'block';
                   edit_area.focus();
                 } else {
        -          $('.example_container').each(function(ind, con) {
        -            $(con).css('opacity', 1.0);
        -            $(con).removeClass('editing');
        -          });
                   edit_button.innerHTML = 'edit';
                   edit_area.style.display = 'none';
                   sketch.textContent = edit_area.value;
        +          $('.example_container').each(function (ind, con) {
        +            $(con).css('opacity', 1.0);
        +            $(con).removeClass('editing');
        +            $this = $(this);
        +            var pre = $this.find('pre')[0];
        +            if (pre) {
        +              $this.height(Math.max($(pre).height(), 100) + 20);
        +            }
        +          });
                   runCode(sketch, true, i);
                 }
               }
        diff --git a/src/assets/learn/curves/bezier/embed.html b/src/assets/learn/curves/bezier/embed.html
        index 56923ac19f..cbbf63fe4a 100644
        --- a/src/assets/learn/curves/bezier/embed.html
        +++ b/src/assets/learn/curves/bezier/embed.html
        @@ -3,7 +3,6 @@
           <title>Curves Example</title>
           <script src="../../../js/p5.min.js"></script>
           <!-- uncomment lines below to include extra p5 libraries -->
        -  <script src="../../../js/p5.dom.min.js"></script>
           <!--<script src="../addons/p5.sound.js"></script>-->
           <script src="sketch.js"></script>
           <!-- this line removes any default padding and style. you might only need one of these values set. -->
        diff --git a/src/assets/learn/curves/curve_ex/embed.html b/src/assets/learn/curves/curve_ex/embed.html
        index 56923ac19f..cbbf63fe4a 100644
        --- a/src/assets/learn/curves/curve_ex/embed.html
        +++ b/src/assets/learn/curves/curve_ex/embed.html
        @@ -3,7 +3,6 @@
           <title>Curves Example</title>
           <script src="../../../js/p5.min.js"></script>
           <!-- uncomment lines below to include extra p5 libraries -->
        -  <script src="../../../js/p5.dom.min.js"></script>
           <!--<script src="../addons/p5.sound.js"></script>-->
           <script src="sketch.js"></script>
           <!-- this line removes any default padding and style. you might only need one of these values set. -->
        diff --git a/src/assets/learn/trigonometry/sincoscurves/embed.html b/src/assets/learn/trigonometry/sincoscurves/embed.html
        index 34e0c18e0f..ce926f1f8b 100755
        --- a/src/assets/learn/trigonometry/sincoscurves/embed.html
        +++ b/src/assets/learn/trigonometry/sincoscurves/embed.html
        @@ -3,7 +3,6 @@
           <title>sin cos curves</title>
           <script src="http://www.courses.tegabrain.com/PVA15/wp-content/uploads/2015/10/p5.min_.js"></script>
           <!-- uncomment lines below to include extra p5 libraries -->
        -  <!--<script src="../addons/p5.dom.js"></script>-->
           <!--<script src="../addons/p5.sound.js"></script>-->
           <script src="http://www.courses.tegabrain.com/PVA15/wp-content/uploads/2015/10/sketch.js"></script>
           <!-- this line removes any default padding and style. you might only need one of these values set. -->
        diff --git a/src/assets/learn/trigonometry/sincoscurves/embed1.html b/src/assets/learn/trigonometry/sincoscurves/embed1.html
        index 6bb0520150..ccd4be44c3 100644
        --- a/src/assets/learn/trigonometry/sincoscurves/embed1.html
        +++ b/src/assets/learn/trigonometry/sincoscurves/embed1.html
        @@ -3,7 +3,6 @@
           <title>sin cos curves</title>
           <script src="http://www.courses.tegabrain.com/PVA15/wp-content/uploads/2015/10/p5min.js"></script>
           <!-- uncomment lines below to include extra p5 libraries -->
        -  <!--<script src="../addons/p5.dom.js"></script>-->
           <!--<script src="../addons/p5.sound.js"></script>-->
           <script src="http://www.courses.tegabrain.com/PVA15/wp-content/uploads/2015/10/sketch.js"></script>
           <!-- this line removes any default padding and style. you might only need one of these values set. -->
        diff --git a/src/assets/learn/trigonometry/unitCircle/embed.html b/src/assets/learn/trigonometry/unitCircle/embed.html
        index 3ff0ae5be6..432db33ba7 100755
        --- a/src/assets/learn/trigonometry/unitCircle/embed.html
        +++ b/src/assets/learn/trigonometry/unitCircle/embed.html
        @@ -3,7 +3,6 @@
           <title>sin cos curves</title>
           <script src="../../../js/p5.min.js"></script>
           <!-- uncomment lines below to include extra p5 libraries -->
        -<script src="../../../js/p5.dom.min.js"></script>
           <!--<script src="../addons/p5.sound.js"></script>-->
           <script src="sketch.js"></script>
           <!-- this line removes any default padding and style. you might only need one of these values set. -->
        diff --git a/src/assets/p5_featured/Tai_PursuingRelief/sketch.js b/src/assets/p5_featured/Tai_PursuingRelief/sketch.js
        index 8e93d68e76..6d96847551 100755
        --- a/src/assets/p5_featured/Tai_PursuingRelief/sketch.js
        +++ b/src/assets/p5_featured/Tai_PursuingRelief/sketch.js
        @@ -46,7 +46,6 @@ var mozzie8;
         var mozzie9;
         
         function preload() {
        -<<<<<<< HEAD
           //can only see 'loadImage' in Firefox 
           img = loadImage("finger01.png");
         }
        @@ -87,52 +86,10 @@ function setup() {
           g8 = 255;
           b8 = 255;
           // MOZZIE #9 :red, green, and blue color values
        -=======
        -	//can only see 'loadImage' in Firefox 
        -	img = loadImage("finger01.png");
        -}
        -
        -function setup() {
        -	createCanvas(windowWidth, windowHeight);
        -// MOZZIE #1 :red, green, and blue color values
        -  r = 255;
        -  g = 255;
        -  b = 255;
        -// MOZZIE #2 :red, green, and blue color values
        -  r2 = 255;
        -  g2 = 255;
        -  b2 = 255;
        - // MOZZIE #3 :red, green, and blue color values
        -  r3 = 255;
        -  g3 = 255;
        -  b3 = 255;
        - // MOZZIE #4 :red, green, and blue color values
        -  r4 = 255;
        -  g4 = 255;
        -  b4 = 255;
        - // MOZZIE #5 :red, green, and blue color values
        -  r5 = 255;
        -  g5 = 255;
        -  b5 = 255;
        - // MOZZIE #6 :red, green, and blue color values
        -  r6 = 255;
        -  g6 = 255;
        -  b6 = 255;
        - // MOZZIE #7 :red, green, and blue color values
        -  r7 = 255;
        -  g7 = 255;
        -  b7 = 255;
        - // MOZZIE #8 :red, green, and blue color values
        -  r8 = 255;
        -  g8 = 255;
        -  b8 = 255;
        - // MOZZIE #9 :red, green, and blue color values
        ->>>>>>> 26af9e9805cff988c47787df67ac9cb5703cda43
           r9 = 255;
           g9 = 255;
           b9 = 255;
         
        -<<<<<<< HEAD
           // MOZZIE #1 
           mozzie = {
             x: (windowWidth/1200)*80,
        @@ -321,202 +278,10 @@ function setup() {
               }
             }
           }
        -=======
        -// MOZZIE #1 
        -mozzie = { 
        -x: 80,
        -y: 300,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r, g-20, b-20);
        -  fill(r, g-20, b-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d = dist(mouseX, mouseY, this.x, this.y);
        -  if (d < 28) {
        -    r = 255; 
        -    g = g-20; 
        -    b = b-20 ;
        -  }
        -}
        -}
        -
        -
        -// MOZZIE #2 - with the new set of variables 
        -mozzie2= { 
        -x: 100,
        -y: 600,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r2, g2-20, b2-20);
        -  fill(r2, g2-20, b2-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d2 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d2 < 28) {
        -    r2 = 255; 
        -    g2 = g2-20;
        -    b2 = b2-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #3 - with the new set of variables 
        -mozzie3= { 
        -x: 360,
        -y: 50,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r3, g3-20, b3-20);
        -  fill(r3, g3-20, b3-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d3 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d3 < 28) {
        -    r3 = 255; 
        -    g3 = g3-20;
        -    b3 = b3-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #4 - with the new set of variables 
        -mozzie4= { 
        -x: 800,
        -y: 400,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r4, g4-20, b4-20);
        -  fill(r4, g4-20, b4-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d4 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d4 < 28) {
        -    r4 = 255; 
        -    g4 = g4-20;
        -    b4 = b4-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #5 - with the new set of variables 
        -mozzie5= { 
        -x: 400,
        -y: 350,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r5, g5-20, b5-20);
        -  fill(r5, g5-20, b5-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d5 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d5 < 28) {
        -    r5 = 255; 
        -    g5 = g5-20;
        -    b5 = b5-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #6 - with the new set of variables 
        -mozzie6= { 
        -x: 1150,
        -y: 300,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r6, g6-20, b6-20);
        -  fill(r6, g6-20, b6-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d6 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d6 < 28) {
        -    r6 = 255; 
        -    g6 = g6-20;
        -    b6 = b6-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #7 - with the new set of variables 
        -mozzie7= { 
        -x: 900,
        -y: 350,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r7, g7-20, b7-20);
        -  fill(r7, g7-20, b7-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d7 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d7 < 28) {
        -    r7 = 255; 
        -    g7 = g7-20;
        -    b7 = b7-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #8 - with the new set of variables 
        -mozzie8= { 
        -x: 890,
        -y: 610,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r8, g8-20, b8-20);
        -  fill(r8, g8-20, b8-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d8 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d8 < 28) {
        -    r8 = 255; 
        -    g8 = g8-20;
        -    b8 = b8-20 ;
        -  }
        -}
        -}
        -
        -// MOZZIE #9 - with the new set of variables 
        -mozzie9= { 
        -x: 880,
        -y: 100,
        -show: function() {
        -  noStroke();
        -  strokeWeight(2);
        -  stroke(r9, g9-20, b9-20);
        -  fill(r9, g9-20, b9-20);
        -  ellipse(this.x, this.y, 50, 50);
        -},
        -mousePressed: function() {
        - var d9 = dist(mouseX, mouseY, this.x, this.y);
        -  if (d9 < 28) {
        -    r9 = 255; 
        -    g9 = g9-20;
        -    b9 = b9-20 ;
        -  }
        -}
        -}
        ->>>>>>> 26af9e9805cff988c47787df67ac9cb5703cda43
         
         }
         
         function draw() {
        -<<<<<<< HEAD
           //FINGER
           // 'aspect' to keep ratio of image
           var aspect = img.height / img.width;
        @@ -787,285 +552,6 @@ function draw() {
           fingerBottomMid.show();
           fingerTopRight.show();
           fingerBottomRight.show();
        -=======
        -//FINGER
        -	// 'aspect' to keep ratio of image
        -	var aspect = img.height / img.width;
        -	var imageWidth = 150;
        -	var imageHeight = imageWidth * aspect; 
        -
        -	background(255, 249, 249); 
        -
        -	fingerTopLeft= { 
        -	x: 200,
        -	y: 110,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(200, 110);
        -	scale(-1,1);
        -  //rotate(radians(frameCount*finger1)
        -  	rotate(radians(finger1));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger1 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger1 < 300) {
        - 	 finger1 = finger1+45;
        - 	 }
        -	}
        -}
        -
        -	/*
        -	//fingerTopLeft
        -	//'push' or 'pop'for isolated behaviours
        -	push ();
        -	// 'imageMode' set pivot point to center of image
        -	imageMode(CORNER);
        -	// 'translate': placing pivot point on X-Y grid
        -	translate(200, 110);
        -	// 'scale' to flip
        -	scale(-1,1);
        -	rotate(radians(frameCount * 1.1));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerBottomLeft= { 
        -	x: 200,
        -	y: 420,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(200, 420);
        -	scale(-1,1);
        -  	rotate(radians(finger2));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger2 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger2 < 300) {
        - 	 finger2 = finger2+45;
        - 	 }
        -	}
        -}
        -	/*
        -	//fingerBottomLeft
        -	push ();
        -	imageMode(CORNER);
        -	translate(200, 420);
        -	//scale(-1,1);
        -	rotate(radians(frameCount * 2));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerTopMid= { 
        -	x: 580,
        -	y: 50,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(580, 50);
        -	scale(-1,1);
        -  	rotate(radians(finger3));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger3 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger3 < 200) {
        - 	 finger3 = finger3+45;
        - 	 }
        -	}
        -}
        -	/*
        -	//fingerTopMid
        -	push ();
        -	imageMode(CORNER);
        -	translate(580, 150);
        -	scale(-1,1);
        -	rotate(radians(frameCount));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerMidMid= { 
        -	x: 700,
        -	y: 320,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(700, 320);
        -	scale(-1,1);
        -  	rotate(radians(finger4));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger4 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger4 < 200) {
        - 	 finger4 = finger4+45;
        - 	 }
        -	}
        -}
        -
        -	/*
        -	//fingerMidMid
        -	push ();
        -	imageMode(CORNER);
        -	translate(680, 350);
        -	scale(-1,1);
        -	rotate(radians(frameCount * 2.5));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerBottomMid= { 
        -	x: 550,
        -	y: 480,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(550, 480);
        -	scale(-1,1);
        -  	rotate(radians(finger5));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger5 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger5 < 300) {
        - 	 finger5 = finger5+45;
        - 	 }
        -	}
        -}
        -
        -	/*
        -	//fingerBottomMid
        -	push ();
        -	imageMode(CORNER);
        -	translate(500, 550);
        -	rotate(radians(frameCount * 3));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerTopRight= { 
        -	x: 1100,
        -	y: 105,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(1100, 105);
        -	scale(-1,1);
        -  	rotate(radians(finger6));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger6 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger6 < 300) {
        - 	 finger6 = finger6+45;
        - 	 }
        -	}
        -}
        -
        -	/*
        -	//fingerTopRight
        -	push ();
        -	imageMode(CORNER);
        -	translate(900, 105);
        -	scale(-1,1);
        -	rotate(radians(frameCount * 2));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -
        -	fingerBottomRight= { 
        -	x: 1000,
        -	y: 450,
        -	aspect: img.height / img.width,
        -	imageWidth: 150,
        -	imageHeight: imageWidth * aspect,
        -    
        -	show: function() {
        -	push ();
        -	imageMode(CORNER);
        -  	translate(1000, 450);
        -	scale(-1,1);
        -  	rotate(radians(finger7));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -
        -	},
        -	mousePressed: function() {
        - 	var dfinger7 = dist(mouseX, mouseY, this.x, this.y);
        - 	 if (dfinger7 < 200) {
        - 	 finger7 = finger7+45;
        - 	 }
        -	}
        -}
        -	/*
        -	//fingerBottomRight
        -	push ();
        -	imageMode(CORNER);
        -	translate(1000, 450);
        -	rotate(radians(frameCount * 1.2));
        -	image(img, 0, 0, imageWidth, imageHeight);
        -	pop ();
        -	*/
        -	
        -mozzie.show();
        -mozzie2.show();
        -mozzie3.show();
        -mozzie4.show();
        -mozzie5.show();
        -mozzie6.show();
        -mozzie7.show();
        -mozzie8.show();
        -mozzie9.show();
        -
        -fingerTopLeft.show();
        -fingerBottomLeft.show();
        -fingerTopMid.show();
        -fingerMidMid.show();
        -fingerBottomMid.show();
        -fingerTopRight.show();
        -fingerBottomRight.show();
        ->>>>>>> 26af9e9805cff988c47787df67ac9cb5703cda43
         }
         
         function mousePressed() {
        @@ -1079,10 +565,6 @@ function mousePressed() {
           mozzie8.mousePressed();
           mozzie9.mousePressed();
         
        -<<<<<<< HEAD
        -=======
        -
        ->>>>>>> 26af9e9805cff988c47787df67ac9cb5703cda43
           fingerTopLeft.mousePressed();
           fingerBottomLeft.mousePressed();
           fingerTopMid.mousePressed();
        @@ -1090,9 +572,4 @@ function mousePressed() {
           fingerBottomMid.mousePressed();
           fingerTopRight.mousePressed();
           fingerBottomRight.mousePressed();
        -<<<<<<< HEAD
         }
        -=======
        -}
        -
        ->>>>>>> 26af9e9805cff988c47787df67ac9cb5703cda43
        diff --git a/src/data/en.yml b/src/data/en.yml
        index 9d3831d5ba..76fe0f66e8 100644
        --- a/src/data/en.yml
        +++ b/src/data/en.yml
        @@ -35,7 +35,7 @@ home:
           p1x1: "p5.js is a JavaScript library for creative coding, with a focus on making coding accessible and inclusive for artists, designers, educators, beginners, and anyone else! p5.js is free and open-source because we believe software, and the tools to learn it, should be accessible to everyone."
           p1x2: "Using the metaphor of a sketch, p5.js has a full set of drawing functionality. However, you’re not limited to your drawing canvas. You can think of your whole browser page as your sketch, including HTML5 objects for text, input, video, webcam, and sound."
           p2xh2: "Community"
        -  p2x1: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
        +  p2x1: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, disability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
           p2x2: "p5.js is an interpretation of "
           p2x3: " for today’s web. We hold events and operate with support from the "
           p2x4: "."
        @@ -473,10 +473,12 @@ community:
           in-times-conflict7: "We are mindful and kind in our interactions."
           in-the-future-title: "In the future:"
           in-the-future1: "The future is now."
        -  sharing-title: "Sharing"
        -  sharing1: "This statement is licensed under a "
        -  sharing2: "Creative Commons license"
        -  sharing3: ". Please feel free to share and remix with attribution."
        +  notes-title: "Notes"
        +  notes1: "Please also see our "
        +  notes2: "p5.js Code of Conduct"
        +  notes3: ". The p5.js Community Statement is licensed under a "
        +  notes4: "Creative Commons license"
        +  notes5: ". Please feel free to share and remix with attribution."
         
           contribute-title: "Contribute"
           contribute1: "Our community is always looking for enthusiasts to help in all different ways."
        @@ -601,6 +603,46 @@ community:
         
         books:
           books-title: "Books"
        +  book-1-title: "Getting Started with p5.js"
        +  book-1-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Illustrations by Taeyoon Choi."
        +  book-1-publisher: "Published October 2015, Maker Media. "
        +  book-1-pages: "246 pages. "
        +  book-1-type: "Paperback."
        +  book-1-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-1-order-a: "Order Print/Ebook from O'Reilly"
        +  book-1-order-b: "Order from Amazon"
        +  book-2-title: "Introduction to p5.js (Spanish Edition)"
        +  book-2-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Translated by Aarón Montoya-Moraga. Ilustraciones de Taeyoon Choi."
        +  book-2-publisher: "Published 2018, Processing Foundation, Inc. "
        +  book-2-pages: "246 pages. "
        +  book-2-type: "Soft cover."
        +  book-2-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-2-order-a: "Order the PDF from The Processing Foundation Press"
        +  book-2-order-b: "Order the physical version from Amazon"
        +  book-3-title: "Generative Design"
        +  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-3-publisher: "Published October 30, 2018, Princeton Architectural Press; Reprint edition. "
        +  book-3-pages: "255 pages. "
        +  book-3-type: "Paperback."
        +  book-3-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-3-order-a: "Order from Princeton Architectural Press"
        +  book-3-order-b: "Order from Amazon"
        +  book-4-title: "Generative Gestaltung (German Edition)"
        +  book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-4-publisher: "Published March 1, 2018, Schmidt Hermann Verlag. "
        +  book-4-pages: "256 pages. "
        +  book-4-type: "Hardcover."
        +  book-4-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-4-order-a: "Order from Verlag Hermann Schmidt"
        +  book-4-order-b: "Order from Amazon"
        +  book-5-title: "Learn JavaScript with p5.js"
        +  book-5-authors: "Engin Arslan."
        +  book-5-publisher: "Published 2018, Apress. "
        +  book-5-pages: "217 pages. "
        +  book-5-type: "Paperback."
        +  book-5-description: "Learn coding from scratch in a highly engaging and visual manner using the vastly popular JavaScript with the programming library p5.js. The skills you will acquire from this book are highly transferable to a myriad of industries and can be used towards building web applications, programmable robots, or generative art. "
        +  book-5-order-a: "Order from Apress"
        +  book-5-order-b: "Order from Amazon"
         
         examples:
           Examples: "Examples"
        diff --git a/src/data/es.yml b/src/data/es.yml
        index ff3a78f283..8c5dfb57f4 100644
        --- a/src/data/es.yml
        +++ b/src/data/es.yml
        @@ -238,7 +238,7 @@ learn:
           using-local-server-title: "Usando un servidor local"
           using-local-server: "Cómo configurar un servidor local en Mac OS X, Windows o Linux."
           p5js-wiki-title: "p5.js wiki"
        -  p5js-wiki: "Additonal documentation and tutorials contributed by the community"
        +  p5js-wiki: "Documentación adicional y tutoriales aportados por la comunidad."
           connecting-p5js-title: "Conectando p5.js"
           creating-libraries-title: "Crear bibliotecas"
           creating-libraries: "Creando bibliotecas adicionales para p5.js."
        @@ -401,7 +401,6 @@ libraries:
           core-libraries: "Bibliotecas principales"
           community-libraries: "Bibliotecas de la comunidad"
           libraries-created-by: "Creada por:"
        -  p5.dom: "p5.dom te permite interactuar con objetos HTML5 más allá del lienzo, incluyendo video, audio, cámara, entrada y texto."
           p5.sound: "p5.sound extiende p5 con funcionalidad de Web Audio, incluyendo entrada de audio, reproducción, análisis y síntesis."
           p5.accessibility: "p5.accessibility permite que el canvas de p5 sea más accesible a personas con discapacidad visual."
           Contributed: "Bibliotecas contribuidas"
        @@ -476,10 +475,12 @@ community:
           in-times-conflict7: "Somos conscientes y amables en nuestras interacciones."
           in-the-future-title: "En el futuro:"
           in-the-future1: "El futuro es ahora."
        -  sharing-title: "Compartir"
        -  sharing1: "Esta declaración está licenciada bajo "
        -  sharing2: "Licencia de Creative Commons"
        -  sharing3: ". Por favor comparte y remezcla con atribución."
        +  notes-title: "Notes"
        +  notes1: "Please also see our "
        +  notes2: "p5.js Code of Conduct"
        +  notes3: ". Esta Declaración de comunidad en torno a p5.js está licenciada bajo "
        +  notes4: "Licencia de Creative Commons"
        +  notes5: ". Por favor comparte y remezcla con atribución."
           contribute-title: "Contribuye"
           contribute1: "Nuestra comunidad siempre está buscando entusiastas para ayudar de diferentes maneras."
           develop-title: "Desarrolla."
        @@ -603,6 +604,46 @@ community:
         
         books:
           books-title: "Libros"
        +  book-1-title: "Getting Started with p5.js"
        +  book-1-authors: "Lauren McCarthy, Casey Reas, y Ben Fry. Illustrations by Taeyoon Choi."
        +  book-1-publisher: "Publicado 2015, Maker Media. "
        +  book-1-pages: "246 páginas. "
        +  book-1-type: "Tapa blanda. "
        +  book-1-description: "Escrito por la desarolladora principal de p5.js y los fundadores de Processing, este libro provee una introducción a las posibilidades creativas de la web actual, usando Javascript y HTML."
        +  book-1-order-a: "Ordena desde O'Reilly"
        +  book-1-order-b: "Ordena desde Amazon"
        +  book-2-title: "Introducción a p5.js (edición en español)"
        +  book-2-authors: "Lauren McCarthy, Casey Reas, y Ben Fry. Traducido por Aarón Montoya-Moraga. Ilustraciones de Taeyoon Choi."
        +  book-2-publisher: "Publicado 2018, Processing Foundation, Inc. "
        +  book-2-pages: "246 páginas. "
        +  book-2-type: "Tapa blanda. "
        +  book-2-description: "Escrito por la desarolladora principal de p5.js y los fundadores de Processing, este libro provee una introducción a las posibilidades creativas de la web actual, usando Javascript y HTML."
        +  book-2-order-a: "Ordena el pdf desde The Processing Foundation Press"
        +  book-2-order-b: "Ordena la versión física desde Amazon"
        +  book-3-title: "Generative Design"
        +  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-3-publisher: "Publicado 2018, Princeton Architectural Press; Reprint edition. "
        +  book-3-pages: "255 páginas. "
        +  book-3-type: "Tapa blanda. "
        +  book-3-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-3-order-a: "Ordena desde Princeton Architectural Press"
        +  book-3-order-b: "Ordena desde Amazon"
        +  book-4-title: "Generative Gestaltung (German Edition)"
        +  book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-4-publisher: "Publicado 2018, Schmidt Hermann Verlag. "
        +  book-4-pages: "256 páginas. "
        +  book-4-type: "Tapa dura. "
        +  book-4-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-4-order-a: "Ordena desde Verlag Hermann Schmidt"
        +  book-4-order-b: "Ordena desde Amazon"
        +  book-5-title: "Learn JavaScript with p5.js"
        +  book-5-authors: "Engin Arslan."
        +  book-5-publisher: "Publicado 2018, Apress. "
        +  book-5-pages: "217 páginas. "
        +  book-5-type: "Tapa blanda. "
        +  book-5-description: "Learn coding from scratch in a highly engaging and visual manner using the vastly popular JavaScript with the programming library p5.js. The skills you will acquire from this book are highly transferable to a myriad of industries and can be used towards building web applications, programmable robots, or generative art. "
        +  book-5-order-a: "Ordena desde Apress"
        +  book-5-order-b: "Ordena desde Amazon"
         
         examples:
           Examples: "Ejemplos"
        @@ -668,4 +709,4 @@ showcase:
           description-casey-louise: "A resource for learning the what, why, and how of using shaders in p5.js."
           project-moon-xin: "Moving Responsive Posters"
           credit-moon-xin: "Moon Jang, Xin Xin, and students"
        -  description-moon-xin: "Browser-based moving posters that use graphical systems, transformation methods, and p5.js to address the connotations of a word less than 8 letters. Designed by students for a graphic design course (Visual Narrative Systems) at the University of Georgia."
        \ No newline at end of file
        +  description-moon-xin: "Browser-based moving posters that use graphical systems, transformation methods, and p5.js to address the connotations of a word less than 8 letters. Designed by students for a graphic design course (Visual Narrative Systems) at the University of Georgia."
        diff --git a/src/data/examples/assets/bubbles.csv b/src/data/examples/assets/bubbles.csv
        new file mode 100644
        index 0000000000..88ac4c1b72
        --- /dev/null
        +++ b/src/data/examples/assets/bubbles.csv
        @@ -0,0 +1,5 @@
        +x,y,diameter,name
        +160,103,43.19838,Happy
        +372,137,52.42526,Sad
        +273,235,61.14072,Joyous
        +121,179,44.758068,Melancholy
        \ No newline at end of file
        diff --git a/src/data/examples/en/16_Dom/03_Input_Button.js b/src/data/examples/en/16_Dom/03_Input_Button.js
        index 5ec69a29ed..d3aaf9cc42 100644
        --- a/src/data/examples/en/16_Dom/03_Input_Button.js
        +++ b/src/data/examples/en/16_Dom/03_Input_Button.js
        @@ -1,9 +1,6 @@
         /*
          * @name Input and Button
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Input text and click the button to see it affect the the canvas.
        + * @description Input text and click the button to see it affect the the canvas.
          */
         let input, button, greeting;
         
        diff --git a/src/data/examples/en/16_Dom/04_Slider.js b/src/data/examples/en/16_Dom/04_Slider.js
        index 0582953c37..6cb48ced1c 100644
        --- a/src/data/examples/en/16_Dom/04_Slider.js
        +++ b/src/data/examples/en/16_Dom/04_Slider.js
        @@ -1,9 +1,6 @@
         /*
          * @name Slider
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Move the sliders to control the R, G, B values of the background.
        + * @description Move the sliders to control the R, G, B values of the background.
          */
         let rSlider, gSlider, bSlider;
         
        diff --git a/src/data/examples/en/16_Dom/07_Modify_DOM.js b/src/data/examples/en/16_Dom/07_Modify_DOM.js
        index c784755f29..9ac89b7595 100644
        --- a/src/data/examples/en/16_Dom/07_Modify_DOM.js
        +++ b/src/data/examples/en/16_Dom/07_Modify_DOM.js
        @@ -1,10 +1,8 @@
         /*
          * @name Modifying the DOM
          * @frame 710,300
        - * @description <p>Create DOM elements and modify their properties every time
        - * draw() is called. You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.</p>
        + * @description Create DOM elements and modify their properties every time
        + * draw() is called.
          */
         let dancingWords = [];
         
        diff --git a/src/data/examples/en/16_Dom/08_Video.js b/src/data/examples/en/16_Dom/08_Video.js
        index 45454f006b..8786bb4cde 100644
        --- a/src/data/examples/en/16_Dom/08_Video.js
        +++ b/src/data/examples/en/16_Dom/08_Video.js
        @@ -1,11 +1,8 @@
         /*
          * @name Video
          * @frame 710,250
        - * @description <p>Load a video with multiple formats and toggle between playing
        + * @description Load a video with multiple formats and toggle between playing
          * and paused with a button press.
        - * <p><em><span class="small"> To run this example locally, you will need at least
        - * one video file, and the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.</span></em></p>
          */
         let playing = false;
         let fingers;
        diff --git a/src/data/examples/en/16_Dom/09_Video_Canvas.js b/src/data/examples/en/16_Dom/09_Video_Canvas.js
        index 8664921d2b..2a59151e06 100644
        --- a/src/data/examples/en/16_Dom/09_Video_Canvas.js
        +++ b/src/data/examples/en/16_Dom/09_Video_Canvas.js
        @@ -1,9 +1,8 @@
         /*
          * @name Video Canvas
        - * @description <p>Load a video with multiple formats and draw it to the canvas.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @description Load a video with multiple formats and draw it to the canvas.
        + * To run this example locally, you will need a running 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/en/16_Dom/10_Video_Pixels.js b/src/data/examples/en/16_Dom/10_Video_Pixels.js
        index ba7dcf0638..9169e37a3d 100644
        --- a/src/data/examples/en/16_Dom/10_Video_Pixels.js
        +++ b/src/data/examples/en/16_Dom/10_Video_Pixels.js
        @@ -1,10 +1,9 @@
         /*
          * @name Video Pixels
          * @frame 320,240
        - * @description <p>Load a video, manipulate its pixels and draw to canvas.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @description Load a video, manipulate its pixels and draw to canvas.
        + * To run this example locally, you will need a running 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/en/16_Dom/11_Capture.js b/src/data/examples/en/16_Dom/11_Capture.js
        index 42733754a3..d11b28df6f 100644
        --- a/src/data/examples/en/16_Dom/11_Capture.js
        +++ b/src/data/examples/en/16_Dom/11_Capture.js
        @@ -1,10 +1,7 @@
         /*
          * @name Video Capture
          * @frame 710,240
        - * @description <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p><br><br>
        - * Capture video from the webcam and display
        + * @description Capture video from the webcam and display
          * on the canvas as well with invert filter. Note that by
          * default the capture feed shows up, too. You can hide the
          * feed by uncommenting the capture.hide() line.
        diff --git a/src/data/examples/en/16_Dom/12_Drop.js b/src/data/examples/en/16_Dom/12_Drop.js
        index 3d42627e50..826d325511 100644
        --- a/src/data/examples/en/16_Dom/12_Drop.js
        +++ b/src/data/examples/en/16_Dom/12_Drop.js
        @@ -1,9 +1,6 @@
         /*
          * @name Drop
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Drag an image file onto the canvas to see it displayed.
        + * @description Drag an image file onto the canvas to see it displayed.
          */
         
         function setup() {
        diff --git a/src/data/examples/en/22_Advanced_Data/01_Load_Saved_Table.js b/src/data/examples/en/22_Advanced_Data/01_Load_Saved_Table.js
        new file mode 100644
        index 0000000000..8536abcccc
        --- /dev/null
        +++ b/src/data/examples/en/22_Advanced_Data/01_Load_Saved_Table.js
        @@ -0,0 +1,110 @@
        +/*
        + * @name Load Saved Table
        + * @description Create a Bubble class, instantiate multiple bubbles using data from
        + * a csv file, and display results on the screen.
        + *  Because the web browsers differ in where they save files, we do not make use of
        + * 
        + * Based on Daniel Shiffman's <a href="https://processing.org/examples/loadsavetable.html">LoadSaveTable Example</a> for Processing.
        + */
        +
        +// Bubble class
        +class Bubble {
        +  constructor(x, y, diameter, name) {
        +    this.x = x;
        +    this.y = y;
        +    this.diameter = diameter;
        +    this.radius = diameter / 2;
        +    this.name = name;
        +
        +    this.over = false;
        +  }
        +
        +  // Check if mouse is over the bubble
        +  rollover(px, py) {
        +    let d = dist(px, py, this.x, this.y);
        +    this.over = d < this.radius;
        +  }
        +
        +  // Display the Bubble
        +  display() {
        +    stroke(0);
        +    strokeWeight(0.8);
        +    noFill();
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +    if (this.over) {
        +      fill(0);
        +      textAlign(CENTER);
        +      text(this.name, this.x, this.y + this.radius + 20);
        +    }
        +  }
        +}
        +
        +let table; // Global object to hold results from the loadTable call
        +let bubbles = []; // Global array to hold all bubble objects
        +
        +// Put any asynchronous data loading in preload to complete before "setup" is run
        +function preload() {
        +  table = loadTable("assets/bubbles.csv", "header");
        +}
        +
        +// Convert saved Bubble data into Bubble Objects
        +function loadData() {
        +  const bubbleData = table.getRows();
        +  // The size of the array of Bubble objects is determined by the total number of rows in the CSV
        +  const length = table.getRowCount();
        +
        +  for (let i = 0; i < length; i++) {
        +    // Get position, diameter, name,
        +    const x = bubbleData[i].getNum("x");
        +    const y = bubbleData[i].getNum("y");
        +    const diameter = bubbleData[i].getNum("diameter");
        +    const name = bubbleData[i].getString("name");
        +
        +    // Put object in array
        +    bubbles.push(new Bubble(x, y, diameter, name));
        +  }
        +}
        +
        +// Create a new Bubble each time the mouse is clicked.
        +function mousePressed() {
        +  // Create a new row
        +  let row = table.addRow();
        +
        +  let name = "New Bubble";
        +  let diameter = random(40, 80);
        +
        +  // Set the values of that row
        +  row.setNum("x", mouseX);
        +  row.setNum("y", mouseY);
        +  row.setNum("diameter", diameter);
        +  row.setString("name", name);
        +
        +  bubbles.push(new Bubble(mouseX, mouseY, diameter, name));
        +
        +  // If the table has more than 10 rows
        +  if (table.getRowCount() > 10) {
        +    // Delete the oldest row
        +    table.removeRow(0);
        +    bubbles.shift();
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  loadData();
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  // Display all bubbles
        +  for (let i = 0; i < bubbles.length; i++) {
        +    bubbles[i].display();
        +    bubbles[i].rollover(mouseX, mouseY);
        +  }
        +
        +  // Label directions at bottom
        +  textAlign(LEFT);
        +  fill(0);
        +  text("Click to add bubbles.", 10, height - 10);
        +}
        diff --git a/src/data/examples/en/90_Hello_P5/02_interactivity.js b/src/data/examples/en/90_Hello_P5/02_interactivity.js
        index 2822149bcf..5bc6687440 100644
        --- a/src/data/examples/en/90_Hello_P5/02_interactivity.js
        +++ b/src/data/examples/en/90_Hello_P5/02_interactivity.js
        @@ -2,9 +2,6 @@
          * @name Interactivity 1
          * @frame 720,425
          * @description The circle changes color when you click on it.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.
        - * </em></p>
          */
         
         // for red, green, and blue color values
        diff --git a/src/data/examples/en/90_Hello_P5/03_interactivity.js b/src/data/examples/en/90_Hello_P5/03_interactivity.js
        index 08af063d3b..6ab965cbe9 100644
        --- a/src/data/examples/en/90_Hello_P5/03_interactivity.js
        +++ b/src/data/examples/en/90_Hello_P5/03_interactivity.js
        @@ -2,9 +2,6 @@
          * @name Interactivity 2
          * @frame 720,425
          * @description The circle changes color when you move the slider.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
          */
         
         // A HTML range slider
        diff --git a/src/data/examples/en/90_Hello_P5/05_weather.js b/src/data/examples/en/90_Hello_P5/05_weather.js
        index 321ce86acb..ddcb10a21a 100644
        --- a/src/data/examples/en/90_Hello_P5/05_weather.js
        +++ b/src/data/examples/en/90_Hello_P5/05_weather.js
        @@ -2,9 +2,6 @@
          * @name Weather
          * @frame 720,280
          * @description This example grabs JSON weather data from apixu.com.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
         */
         
         // A wind direction vector
        diff --git a/src/data/examples/es/08_Math/10_Interpolate.js b/src/data/examples/es/08_Math/10_Interpolate.js
        index 27ec95ef92..58505b4a24 100644
        --- a/src/data/examples/es/08_Math/10_Interpolate.js
        +++ b/src/data/examples/es/08_Math/10_Interpolate.js
        @@ -1,11 +1,11 @@
         /*
        - * @name Linear Interpolation
        + * @name Interpolación Lineal
          * @frame 720, 400
        - * @description Move the mouse across the screen and the symbol will follow.
        - * Between drawing each frame of the animation, the ellipse moves part
        - * of the distance (0.05) from its current position toward the cursor using
        - * the lerp() function.
        - * This is the same as the Easing under input only with lerp() instead..
        + * @description Mueve el ratón a través de la pantalla y el símbolo le seguirá.
        + * Entre cada fotograma de la animación, la elipse se mueve parte
        + * de la distancia (0,05) desde su posición actual hacia el cursor
        + * usando la función lerp().
        + * Esto es equivalente al uso de Easing en la sección Input, sólo que con lerp() en su lugar...
          */
         
         let x = 0;
        @@ -19,12 +19,12 @@ function setup() {
         function draw() {
           background(51);
         
        -  // lerp() calculates a number between two numbers at a specific increment.
        -  // The amt parameter is the amount to interpolate between the two values
        -  // where 0.0 equal to the first point, 0.1 is very near the first point, 0.5
        -  // is half-way in between, etc.
        +  // lerp() calcula un número entre dos números en un incremento específico.
        +  // El parámetro amt (amount) es la cantidad a interpolar entre los dos valores
        +  // donde 0,0 es igual al primer punto, 0,1 está muy cerca del primer punto, 0,5
        +  // está a mitad de camino, etc.
         
        -  // Here we are moving 5% of the way to the mouse location each frame
        +  // Aquí estamos moviendo el 5% del camino hacia la ubicación del ratón en cada fotograma
           x = lerp(x, mouseX, 0.05);
           y = lerp(y, mouseY, 0.05);
         
        diff --git a/src/data/examples/es/08_Math/15_Noise2D.js b/src/data/examples/es/08_Math/15_Noise2D.js
        index 2aec0d5690..9640287af8 100644
        --- a/src/data/examples/es/08_Math/15_Noise2D.js
        +++ b/src/data/examples/es/08_Math/15_Noise2D.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Noise2D
        + * @name Ruido 2D
          * @frame 710,400 (optional)
        - * @description Create a 2D noise with different parameters.
        + * @description Crear un ruido 2D con parámetros diferentes.
          *
          */
         
        @@ -14,27 +14,27 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Draw the left half of image
        +  // Dibujar la mitad izquierda de la imagen
           for (let y = 0; y < height - 30; y++) {
             for (let x = 0; x < width / 2; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // noiceDetail (detalle del ruido) del número de octavas  y valor de caída de los píxeles
               noiseDetail(2, 0.2);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  // Draw the right half of image
        +  // Dibujar la mitad derecha de la imagen
           for (let y = 0; y < height - 30; y++) {
             for (let x = width / 2; x < width; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // noiceDetail (detalle del ruido) del número de octavas  y valor de caída de los píxeles
               noiseDetail(5, 0.5);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  //Show the details of two partitions
        +  //Mostrar los detalles de las dos particiones
           textSize(18);
           fill(255, 255, 255);
           text('Noice2D with 2 octaves and 0.2 falloff', 10, 350);
        diff --git a/src/data/examples/es/08_Math/16_Noise3D.js b/src/data/examples/es/08_Math/16_Noise3D.js
        index 37f35eaf80..9153f0b794 100644
        --- a/src/data/examples/es/08_Math/16_Noise3D.js
        +++ b/src/data/examples/es/08_Math/16_Noise3D.js
        @@ -1,41 +1,41 @@
         /*
        - * @name Noise3D
        + * @name Ruido 3D
          * @frame 710,400 (optional)
        - * @description Using 3D noise to create simple animated texture.
        + * @description Uso de ruido 3D para crear una simple textura animada.
          */
         let noiseVal;
        -//Increment x by 0.01
        +//Incrementar x en 0,01
         let x_increment = 0.01;
        -//Increment z by 0.02 every draw() cycle
        +//Incrementar z en 0.02 cada ciclo de draw()
         let z_increment = 0.02;
         
        -//Offset values
        +//Valores de desviación
         let z_off, y_off, x_off;
         
         function setup() {
        -  //Create the Canvas
        +  //Crear el Lienzo
           createCanvas(640, 360);
        -  //Define frame rate
        +  //Definir la velocidad de cuadro
           frameRate(20);
        -  //Initial value of z_off
        +  //Valor inicial de z_off
           z_off = 0;
         }
         
         function draw() {
           x_off = 0;
           y_off = 0;
        -  //Make the background black
        +  //Hacer que el fondo sea negro
           background(0);
        -  //Adjust the noice detail
        +  //Ajustar el detalle del ruido
           noiseDetail(8, 0.65);
         
        -  //For each x,y calculate noice value
        +  //Para cada x,y calcular el valor del ruido
           for (let y = 0; y < height; y++) {
             x_off += x_increment;
             y_off = 0;
         
             for (let x = 0; x < width; x++) {
        -      //Calculate and Draw each pixel
        +      //Calcular y dibujar cada píxel
               noiseVal = noise(x_off, y_off, z_off);
               stroke(noiseVal * 255);
               y_off += x_increment;
        diff --git a/src/data/examples/es/08_Math/17_Randomchords.js b/src/data/examples/es/08_Math/17_Randomchords.js
        index 7b583bf660..600d27afb5 100644
        --- a/src/data/examples/es/08_Math/17_Randomchords.js
        +++ b/src/data/examples/es/08_Math/17_Randomchords.js
        @@ -1,34 +1,34 @@
         /*
        - * @name Random Chords
        - * @description Accumulates random chords of a circle. Each chord in translucent
        - * so they accumulate to give the illusion of a shaded sphere.
        - * Contributed by Aatish Bhatia, inspired by <a href ="http://inconvergent.net/">Anders Hoff</a>
        + * @name Cuerdas Aleatorias
        + * @description Acumula cuerdas al azar de un círculo. Cada cuerda es translúcida,
        + * de modo que se acumulan para dar la ilusión de una esfera sombreada.
        + * Contribución de Aatish Bhatia, inspirado en <a href ="http://inconvergent.net/">Anders Hoff</a>
          */
         function setup() {
           createCanvas(400, 400);
           background(255, 255, 255);
         
        -  // translucent stroke using alpha value
        +  // trazo translúcido usando el valor alfa
           stroke(0, 0, 0, 15);
         }
         
         function draw() {
        -  // draw two random chords each frame
        +  // trazar dos cuerdas al azar en cada cuadro
           randomChord();
           randomChord();
         }
         
         function randomChord() {
        -  // find a random point on a circle
        +  // encontrar un punto aleatorio en un círculo
           let angle1 = random(0, 2 * PI);
           let xpos1 = 200 + 200 * cos(angle1);
           let ypos1 = 200 + 200 * sin(angle1);
         
        -  // find another random point on the circle
        +  // encontrar otro punto aleatorio en el círculo
           let angle2 = random(0, 2 * PI);
           let xpos2 = 200 + 200 * cos(angle2);
           let ypos2 = 200 + 200 * sin(angle2);
         
        -  // draw a line between them
        +  // trazar una línea entre ellos
           line(xpos1, ypos1, xpos2, ypos2);
         }
        diff --git a/src/data/examples/es/08_Math/18_Map.js b/src/data/examples/es/08_Math/18_Map.js
        index a7b4d86058..f4170bed75 100644
        --- a/src/data/examples/es/08_Math/18_Map.js
        +++ b/src/data/examples/es/08_Math/18_Map.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Map
        - * @description Use the map() function to take any number and scale it to a
        - * new number that is more useful for the project that you are working on.
        - * For example, use the numbers from the mouse position to control the size or color of a shape.
        - * In this example, the mouse’s x-coordinate (numbers between 0 and 360) are scaled to new numbers
        - * to define the color and size of a circle.
        + * @name Mapear
        + * @description Utiliza la función map() para tomar cualquier número y escalarlo a un
        + * nuevo número que sea más útil para el proyecto en el que estés trabajando.
        + * Por ejemplo, usa los números de la posición del ratón para controlar el tamaño o el color de una figura.
        + * En este ejemplo, la coordenada x del ratón (números entre 0 y 360) se escalan a nuevos números
        + * para definir el color y el tamaño de un círculo.
          */
         function setup() {
           createCanvas(640, 400);
        @@ -13,9 +13,9 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Scale the mouseX value from 0 to 640 to a range between 0 and 175
        +  // Escala el valor de mouseX de 0 a 640 a un rango entre 0 y 175
           let c = map(mouseX, 0, width, 0, 175);
        -  // Scale the mouseX value from 0 to 640 to a range between 40 and 300
        +  // Escala el valor de mouseX de 0 a 640 a un rango entre 40 y 300
           let d = map(mouseX, 0, width, 40, 300);
           fill(255, c, 0);
           ellipse(width/2, height/2, d, d);
        diff --git a/src/data/examples/es/08_Math/19_parametricEquation.js b/src/data/examples/es/08_Math/19_parametricEquation.js
        index 83c1a3c336..6470ef5ed1 100644
        --- a/src/data/examples/es/08_Math/19_parametricEquation.js
        +++ b/src/data/examples/es/08_Math/19_parametricEquation.js
        @@ -1,44 +1,45 @@
         /*
        - * @name Parametric Equations
        - * @description A parametric equation is where x and y
        - * coordinates are both written in terms of another letter. This is
        - * called a parameter and is usually given in the letter t or θ.
        - * The inspiration was taken from the YouTube channel of Alexander Miller.
        + * @name Ecuaciones Paramétricas
        + * @description Una ecuación paramétrica es una en la cual las coordenadas x e y
        + * están escritas en términos de otra variable.
        + * Esto se llama un parámetro y se suele dar en la letra t o θ.
        + * La inspiración se tomó del canal de YouTube de Alexander Miller.
          */
         
         function setup(){
           createCanvas(720,400);
         }
         
        -// the parameter at which x and y depends is usually taken as either t or symbol of theta
        +// el parámetro del que dependen x e y
        +// se suele designar con la letra t o el símbolo de theta
         let t = 0;
         function draw(){
           background('#fff');
           translate(width/2,height/2);
           stroke('#0f0f0f');
           strokeWeight(1.5);
        -  //loop for adding 100 lines
        +  //bucle para añadir 100 líneas
           for(let i = 0;i<100;i++){
             line(x1(t+i),y1(t+i),x2(t+i)+20,y2(t+i)+20);
           }
           t+=0.15;
         }
        -// function to change initial x co-ordinate of the line
        +// función para cambiar la coordenada inicial x de la línea
         function x1(t){
           return sin(t/10)*125+sin(t/20)*125+sin(t/30)*125;
         }
         
        -// function to change initial y co-ordinate of the line
        +// función para cambiar la coordenada y inicial de la línea
         function y1(t){
           return cos(t/10)*125+cos(t/20)*125+cos(t/30)*125;
         }
         
        -// function to change final x co-ordinate of the line
        +// función para cambiar la coordenada x final de la línea
         function x2(t){
           return sin(t/15)*125+sin(t/25)*125+sin(t/35)*125;
         }
         
        -// function to change final y co-ordinate of the line
        +// función para cambiar la coordenada final de la línea
         function y2(t){
           return cos(t/15)*125+cos(t/25)*125+cos(t/35)*125;
        -}
        \ No newline at end of file
        +}
        diff --git a/src/data/examples/es/09_Simulate/09_Springs.js b/src/data/examples/es/09_Simulate/09_Springs.js
        index ed0a185a65..3e4d422831 100644
        --- a/src/data/examples/es/09_Simulate/09_Springs.js
        +++ b/src/data/examples/es/09_Simulate/09_Springs.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Springs
        + * @name Resortes
          * @frame 710,400
        - * @description Move the mouse over one of the circles and click to re-position.
        - * When you release the mouse, it will snap back into position.
        - * Each circle has a slightly different behavior.
        - * (ported from https://processing.org/examples/springs.html)
        + * @description Mueve el ratón sobre uno de los círculos y haz clic para reposicionarlo.
        + * Cuando sueltes el ratón, se volverá a colocar en su posición.
        + * Cada círculo tiene un comportamiento ligeramente diferente.
        + * (puerto de https://processing.org/examples/springs.html)
          */
         let num = 3;
         let springs = [];
        @@ -144,4 +144,4 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         		this.rest_posx = this.y_pos;
         		this.rest_posy = this.y_pos;
         	}
        -};
        \ No newline at end of file
        +};
        diff --git a/src/data/examples/es/09_Simulate/11_SmokeParticleSystem.js b/src/data/examples/es/09_Simulate/11_SmokeParticleSystem.js
        index 4db21d4f9a..7c2dbb1b28 100644
        --- a/src/data/examples/es/09_Simulate/11_SmokeParticleSystem.js
        +++ b/src/data/examples/es/09_Simulate/11_SmokeParticleSystem.js
        @@ -1,6 +1,6 @@
         /*
          * @name Partículas de humo
        - * @description un puerto del ejemplo de sistema de partículas de humo de Dan Shiffman, originalmente para Processing. Crea partículas de humo :p
        + * @description Un puerto del ejemplo de sistema de partículas de humo de Dan Shiffman, originalmente para Processing. Crea partículas de humo :p
          */
         
         // textura de la partícula
        diff --git a/src/data/examples/es/09_Simulate/14_SnowflakeParticleSystem.js b/src/data/examples/es/09_Simulate/14_SnowflakeParticleSystem.js
        index 0956a80792..b8c1c7f9e5 100755
        --- a/src/data/examples/es/09_Simulate/14_SnowflakeParticleSystem.js
        +++ b/src/data/examples/es/09_Simulate/14_SnowflakeParticleSystem.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Snowflakes
        - * @description Particle system simulating the motion of falling snowflakes.
        - * Uses an array of objects to hold the snowflake particles.
        - * Contributed by Aatish Bhatia.
        + * @name Copos de Nieve
        + * @description Sistema de partículas que simula el movimiento de copos de nieve cayendo.
        + * Utiliza un arreglo de objetos para almacenar las particulas de copos de nieve.
        + * Contribución de Aatish Bhatia.
          */
         
         let snowflakes = []; // array to hold snowflake objects
        diff --git a/src/data/examples/es/09_Simulate/15_penrose_tiles.js b/src/data/examples/es/09_Simulate/15_penrose_tiles.js
        index 0179261b71..7bd12af7ae 100644
        --- a/src/data/examples/es/09_Simulate/15_penrose_tiles.js
        +++ b/src/data/examples/es/09_Simulate/15_penrose_tiles.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Penrose Tiles
        + * @name Baldosas de Penrose
          * @frame 710,400
        - * @description This is a port by David Blitz of the "Penrose Tile" example from processing.org/examples
        + * @description Este es un puerto de David Blitz del ejemplo "Baldosa de Penrose" de processing.org/examples
          */
         
         let ds;
        @@ -121,5 +121,3 @@ PenroseLSystem.prototype.render = function () {
             }
           }
         }
        -
        -
        diff --git a/src/data/examples/es/09_Simulate/16_Recursive_Tree.js b/src/data/examples/es/09_Simulate/16_Recursive_Tree.js
        index c86a08e6a1..dbdf584a9f 100644
        --- a/src/data/examples/es/09_Simulate/16_Recursive_Tree.js
        +++ b/src/data/examples/es/09_Simulate/16_Recursive_Tree.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Recursive Tree
        - * @description Renders a simple tree-like structure via recursion.
        - * The branching angle is calculated as a function of the horizontal mouse
        - * location. Move the mouse left and right to change the angle.
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/tree.html">Recursive Tree Example</a> for Processing.
        + * @name Árbol Recursivo
        + * @description Representa una estructura simple en forma de árbol a través de la recursión.
        + * El ángulo de ramificación se calcula en función de la posición horizontal del ratón.
        + * Mueve el ratón hacia la izquierda y la derecha para cambiar el ángulo.
        + * Basado en el <a href="https://processing.org/examples/tree.html">Ejemplo de Árbol Recursivo</a> de Daniel Shiffman para Processing.
          */
         let theta;
         
        diff --git a/src/data/examples/es/09_Simulate/18_Koch.js b/src/data/examples/es/09_Simulate/18_Koch.js
        index d8acc9fd55..f09f5d4a8a 100644
        --- a/src/data/examples/es/09_Simulate/18_Koch.js
        +++ b/src/data/examples/es/09_Simulate/18_Koch.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Koch Curve
        - * @description Renders a simple fractal, the Koch snowflake. Each recursive level is drawn in sequence.
        - * By Daniel Shiffman
        + * @name Curva Koch
        + * @description Renderización de un fractal simple: el copo de nieve de Koch. Cada nivel recursivo se dibuja en secuencia.
        + * Por Daniel Shiffman.
          */
         
         let k;
        diff --git a/src/data/examples/es/09_Simulate/19_Bubblesort.js b/src/data/examples/es/09_Simulate/19_Bubblesort.js
        index 85d3402dfb..188b065864 100644
        --- a/src/data/examples/es/09_Simulate/19_Bubblesort.js
        +++ b/src/data/examples/es/09_Simulate/19_Bubblesort.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Bubble Sort
        - * @description Sorts the randomly distributed bars 
        - * according to their height in ascending order
        - * while simulating the whole sorting process.
        - * Took references from Coding Challenge by The Coding Train.
        + * @name Ordenamiento de Burbuja
        + * @description Ordena las barras distribuidas aleatoriamente
        + * según su altura en orden ascendente mientras simula todo el
        + * proceso de clasificación.
        + * Se usaron referencias del 'Coding Challenge' de 'The Coding Train'.
          */
         
         let values = [];
        @@ -31,7 +31,7 @@ function draw() {
         }
         
         // The bubbleSort() function sorts taking 8 elements of the array
        -// per frame. The algorithm behind this function is 
        +// per frame. The algorithm behind this function is
         // bubble sort.
         function bubbleSort() {
           for(let k = 0;k<8;k++){
        @@ -42,7 +42,7 @@ function bubbleSort() {
                 values[j+1] = temp;
               }
               j++;
        -      
        +
               if(j>=values.length-i-1){
                 j = 0;
                 i++;
        @@ -64,4 +64,4 @@ function simulateSorting(){
              fill(50);
              rect(i*8 , height, 8, -values[i],20);
            }
        -}
        \ No newline at end of file
        +}
        diff --git a/src/data/examples/es/09_Simulate/20_SteepingFeet.js b/src/data/examples/es/09_Simulate/20_SteepingFeet.js
        index 6f3d7449eb..fb69758981 100644
        --- a/src/data/examples/es/09_Simulate/20_SteepingFeet.js
        +++ b/src/data/examples/es/09_Simulate/20_SteepingFeet.js
        @@ -1,11 +1,11 @@
         /*
        - * @name Stepping Feet Illusion
        - * @description Stepping feet illusion is a very famous psychological experiment
        - * Both the bricks will appear to move at different speed
        - * even though they are moving at the same speed.
        - * Click the mouse inside Canvas to confirm that
        - * they are moving at the same speed.
        - * Contributed by Sagar Arora.
        + * @name Ilusión de los Pasos
        + * @description La ilusión de los pasos es un experimento
        + * psicológico muy famoso. Ambos bloques parecen moverse
        + * a velocidades diferentes, pero en realidad se mueven
        + * a la misma velocidad. Haz click con el ratón dentro
        + * del lienzo para confirmar que se mueven a la misma velocidad.
        + * Contribución de Sagar Arora.
          */
         
         // this class describes the structure
        @@ -45,7 +45,7 @@ function setup() {
           createP("are moving at same speed or not").style('color','#ffffff');
         }
         
        -// creating two bricks of 
        +// creating two bricks of
         // colors white and black
         let brick1 = new Brick("white",100);
         let brick2 = new Brick("black",250);
        @@ -77,4 +77,4 @@ function createBars() {
             if(i%2 == 0)
             rect(i*len,height,len,-height);
           }
        -}
        \ No newline at end of file
        +}
        diff --git a/src/data/examples/es/09_Simulate/21_Particle.js b/src/data/examples/es/09_Simulate/21_Particle.js
        index 259c67b386..354be961c9 100644
        --- a/src/data/examples/es/09_Simulate/21_Particle.js
        +++ b/src/data/examples/es/09_Simulate/21_Particle.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Particles
        - * @description There is a light-weight JavaScript library named
        - * particle.js which creates a very pleasing particle system.
        - * This is an attempt to recreate that particle system using p5.js.
        - * Inspired by Particle.js, contributed by Sagar Arora.
        + * @name Partículas
        + * @description Hay una biblioteca ligera de JavaScript llamada particle.js
        + * que crea un sistema de partículas muy agradable.
        + * Este es un intento de recrear ese sistema de partículas usando p5.js.
        + * Inspirado en Particle.js, contribuido por Sagar Arora. 
          */
         
         
        @@ -66,4 +66,4 @@ function draw() {
             particles[i].moveParticle();
             particles[i].joinParticles(particles.slice(i));
           }
        -}
        \ No newline at end of file
        +}
        diff --git a/src/data/examples/es/16_Dom/03_Input_Button.js b/src/data/examples/es/16_Dom/03_Input_Button.js
        index 61552cb282..28751d883e 100644
        --- a/src/data/examples/es/16_Dom/03_Input_Button.js
        +++ b/src/data/examples/es/16_Dom/03_Input_Button.js
        @@ -1,9 +1,6 @@
         /*
          * @name Entrada y botón
        - * @description Necesitarás incluir la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - * para que este ejemplo funcione en tu proyecto.<br><br>
        - * Ingresa texto y haz click en el botón para ver cómo afecta al lienzo
        + * @description Ingresa texto y haz click en el botón para ver cómo afecta al lienzo
          */
         let input, button, greeting;
         
        diff --git a/src/data/examples/es/16_Dom/04_Slider.js b/src/data/examples/es/16_Dom/04_Slider.js
        index b4d92ff850..041fedfb73 100644
        --- a/src/data/examples/es/16_Dom/04_Slider.js
        +++ b/src/data/examples/es/16_Dom/04_Slider.js
        @@ -1,9 +1,6 @@
         /*
          * @name Barra deslizante
        - * @description Necesitarás incluir la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - * para que este ejemplo funcione en tu propio proyecto.<br><br>
        - * Mueve las barras deslizantes para controlar los valores de color RGB del fondo.
        + * @description Mueve las barras deslizantes para controlar los valores de color RGB del fondo.
          */
         let rSlider, gSlider, bSlider;
         
        diff --git a/src/data/examples/es/16_Dom/07_Modify_DOM.js b/src/data/examples/es/16_Dom/07_Modify_DOM.js
        index 1dd8ec2c6b..f4728582a9 100644
        --- a/src/data/examples/es/16_Dom/07_Modify_DOM.js
        +++ b/src/data/examples/es/16_Dom/07_Modify_DOM.js
        @@ -1,10 +1,7 @@
         /*
          * @name Modificar el DOM
          * @frame 710,300
        - * @description <p>Crea elementos DOM y modifica sus propiedades cada vez que draw() es llamado
        - * Necesitarás incluir la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - * para que este ejemplo funcione en tu proyecto. </p>
        + * @description Crea elementos DOM y modifica sus propiedades cada vez que draw() es llamado
          */
         let dancingWords = [];
         
        diff --git a/src/data/examples/es/16_Dom/08_Video.js b/src/data/examples/es/16_Dom/08_Video.js
        index d96f6cf84e..59dd800156 100644
        --- a/src/data/examples/es/16_Dom/08_Video.js
        +++ b/src/data/examples/es/16_Dom/08_Video.js
        @@ -1,10 +1,7 @@
         /*
          * @name Video
          * @frame 710,250
        - * @description <p>Carga un video con múltiples formatos y alterna entre reproducir y pausar al presionar un botón.
        - * <p><em><span class="small"> Para correr este ejemplo localmente, necesitarás al menos
        - * un archivo de video y la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>.</span></em></p>
        + * @description Carga un video con múltiples formatos y alterna entre reproducir y pausar al presionar un botón.
          */
         let playing = false;
         let fingers;
        diff --git a/src/data/examples/es/16_Dom/09_Video_Canvas.js b/src/data/examples/es/16_Dom/09_Video_Canvas.js
        index 7e333bc60e..684d8dfcd6 100644
        --- a/src/data/examples/es/16_Dom/09_Video_Canvas.js
        +++ b/src/data/examples/es/16_Dom/09_Video_Canvas.js
        @@ -1,9 +1,8 @@
         /*
          * @name Lienzo y video
        - * @description <p> Cargar un video en múltiples formatos y dibújalo en el lienzo.</p>
        - * <p><em><span class="small"> Para correr este ejemplo localmente, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - *, al menos un archivo de video y correr un <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.</span></em></p>
        + * @description Cargar un video en múltiples formatos y dibújalo en el lienzo.
        + * Para correr este ejemplo localmente, necesitarás correr un 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/es/16_Dom/10_Video_Pixels.js b/src/data/examples/es/16_Dom/10_Video_Pixels.js
        index dd320c8a5d..f722ee9ef4 100644
        --- a/src/data/examples/es/16_Dom/10_Video_Pixels.js
        +++ b/src/data/examples/es/16_Dom/10_Video_Pixels.js
        @@ -1,10 +1,9 @@
         /*
          * @name Pixeles de video
          * @frame 320,240
        - * @description <p> Cargar un video, manipula sus pixeles y dibújalo en el lienzo.
        - * <p><em><span class="small"> Para correr este ejemplo localmente, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - *, al menos un archivo de video y correr un <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.</span></em></p>
        + * @description Cargar un video, manipula sus pixeles y dibújalo en el lienzo.
        + * Para correr este ejemplo localmente, necesitarás correr un 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/es/16_Dom/11_Capture.js b/src/data/examples/es/16_Dom/11_Capture.js
        index d6b2b07d66..1ce429c057 100644
        --- a/src/data/examples/es/16_Dom/11_Capture.js
        +++ b/src/data/examples/es/16_Dom/11_Capture.js
        @@ -2,13 +2,11 @@
          * @name Captura de video
          * @frame 710,240
          * @description Captura video desde la webcam, muéstralo
        -
          * en el lienzo con un filtro de inversión. Fíjate que por defecto la
          * captura también aparece. Puedes esconderla
          * si quitas el comentario a la línea de código capture.hide().
        - * <p><em><span class="small"> Para correr este ejemplo localmente, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - *, al menos un archivo de video y correr un <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.</span></em></p>
        + * Para correr este ejemplo localmente, necesitarás correr un 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">servidor local</a>.
          */
         let capture;
         
        diff --git a/src/data/examples/es/16_Dom/12_Drop.js b/src/data/examples/es/16_Dom/12_Drop.js
        index c9ef53018c..ac8c66455b 100644
        --- a/src/data/examples/es/16_Dom/12_Drop.js
        +++ b/src/data/examples/es/16_Dom/12_Drop.js
        @@ -1,9 +1,6 @@
         /*
          * @name Arrojar
        - * @description  Toma un archivo de imagen y arrójalo sobre el lienzo para mostrarlo.
        - * <p><em><span class="small"> Para correr este ejemplo localmente, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
        - *, al menos un archivo de imagen.</span></em></p>
        + * @description Toma un archivo de imagen y arrójalo sobre el lienzo para mostrarlo.
          */
         
         function setup() {
        diff --git a/src/data/examples/es/22_Advanced_Data/01_Load_Saved_Table.js b/src/data/examples/es/22_Advanced_Data/01_Load_Saved_Table.js
        new file mode 100644
        index 0000000000..8536abcccc
        --- /dev/null
        +++ b/src/data/examples/es/22_Advanced_Data/01_Load_Saved_Table.js
        @@ -0,0 +1,110 @@
        +/*
        + * @name Load Saved Table
        + * @description Create a Bubble class, instantiate multiple bubbles using data from
        + * a csv file, and display results on the screen.
        + *  Because the web browsers differ in where they save files, we do not make use of
        + * 
        + * Based on Daniel Shiffman's <a href="https://processing.org/examples/loadsavetable.html">LoadSaveTable Example</a> for Processing.
        + */
        +
        +// Bubble class
        +class Bubble {
        +  constructor(x, y, diameter, name) {
        +    this.x = x;
        +    this.y = y;
        +    this.diameter = diameter;
        +    this.radius = diameter / 2;
        +    this.name = name;
        +
        +    this.over = false;
        +  }
        +
        +  // Check if mouse is over the bubble
        +  rollover(px, py) {
        +    let d = dist(px, py, this.x, this.y);
        +    this.over = d < this.radius;
        +  }
        +
        +  // Display the Bubble
        +  display() {
        +    stroke(0);
        +    strokeWeight(0.8);
        +    noFill();
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +    if (this.over) {
        +      fill(0);
        +      textAlign(CENTER);
        +      text(this.name, this.x, this.y + this.radius + 20);
        +    }
        +  }
        +}
        +
        +let table; // Global object to hold results from the loadTable call
        +let bubbles = []; // Global array to hold all bubble objects
        +
        +// Put any asynchronous data loading in preload to complete before "setup" is run
        +function preload() {
        +  table = loadTable("assets/bubbles.csv", "header");
        +}
        +
        +// Convert saved Bubble data into Bubble Objects
        +function loadData() {
        +  const bubbleData = table.getRows();
        +  // The size of the array of Bubble objects is determined by the total number of rows in the CSV
        +  const length = table.getRowCount();
        +
        +  for (let i = 0; i < length; i++) {
        +    // Get position, diameter, name,
        +    const x = bubbleData[i].getNum("x");
        +    const y = bubbleData[i].getNum("y");
        +    const diameter = bubbleData[i].getNum("diameter");
        +    const name = bubbleData[i].getString("name");
        +
        +    // Put object in array
        +    bubbles.push(new Bubble(x, y, diameter, name));
        +  }
        +}
        +
        +// Create a new Bubble each time the mouse is clicked.
        +function mousePressed() {
        +  // Create a new row
        +  let row = table.addRow();
        +
        +  let name = "New Bubble";
        +  let diameter = random(40, 80);
        +
        +  // Set the values of that row
        +  row.setNum("x", mouseX);
        +  row.setNum("y", mouseY);
        +  row.setNum("diameter", diameter);
        +  row.setString("name", name);
        +
        +  bubbles.push(new Bubble(mouseX, mouseY, diameter, name));
        +
        +  // If the table has more than 10 rows
        +  if (table.getRowCount() > 10) {
        +    // Delete the oldest row
        +    table.removeRow(0);
        +    bubbles.shift();
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  loadData();
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  // Display all bubbles
        +  for (let i = 0; i < bubbles.length; i++) {
        +    bubbles[i].display();
        +    bubbles[i].rollover(mouseX, mouseY);
        +  }
        +
        +  // Label directions at bottom
        +  textAlign(LEFT);
        +  fill(0);
        +  text("Click to add bubbles.", 10, height - 10);
        +}
        diff --git a/src/data/examples/es/90_Hello_P5/02_interactivity.js b/src/data/examples/es/90_Hello_P5/02_interactivity.js
        index 86b134a5a1..24bdb12b30 100644
        --- a/src/data/examples/es/90_Hello_P5/02_interactivity.js
        +++ b/src/data/examples/es/90_Hello_P5/02_interactivity.js
        @@ -2,9 +2,6 @@
          * @name Interactividad 1
          * @frame 720,425
          * @description El círculo cambia de color cuando ahces click en él.
        - * <p><em><span class="small"> Para correr este ejemplo de manera local, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom"> biblioteca p5.dom</a>.
        - * </em></p>
          */
         
         // variables para los valores de rojo, verde y azul (r, g, b)
        diff --git a/src/data/examples/es/90_Hello_P5/03_interactivity.js b/src/data/examples/es/90_Hello_P5/03_interactivity.js
        index 02064f076d..4fa554c275 100644
        --- a/src/data/examples/es/90_Hello_P5/03_interactivity.js
        +++ b/src/data/examples/es/90_Hello_P5/03_interactivity.js
        @@ -2,8 +2,6 @@
          * @name Interactividad 2
          * @frame 720,425
          * @description El círculo cambia de color cuando mueves la barra deslizante.
        - * Para correr este ejemplo de manera local, necesitarás la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">biblioteca p5.dom</a>
          */
         
         // Una barra deslizante de rango HTML
        diff --git a/src/data/examples/es/90_Hello_P5/05_weather.js b/src/data/examples/es/90_Hello_P5/05_weather.js
        index 279e87851d..e07a391450 100644
        --- a/src/data/examples/es/90_Hello_P5/05_weather.js
        +++ b/src/data/examples/es/90_Hello_P5/05_weather.js
        @@ -2,9 +2,6 @@
          * @name Clima
          * @frame 720,280
          * @description Este ejemplo usa datos de clima en formato JSON desde apixu.com.
        - * Necesitarás incluir la
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom"> biblioteca p5.dom</a>
        - * a este ejemplo para que corra en tu máquina.
         */
         
         // un vector de dirección de viento
        diff --git a/src/data/examples/ko/00_Structure/00_Coordinates.js b/src/data/examples/ko/00_Structure/00_Coordinates.js
        index b783e1c093..b7a9e4091b 100644
        --- a/src/data/examples/ko/00_Structure/00_Coordinates.js
        +++ b/src/data/examples/ko/00_Structure/00_Coordinates.js
        @@ -1,39 +1,34 @@
         /*
        - * @name Coordinates
        - * @description All shapes drawn to the screen have a position that is
        - * specified as a coordinate. All coordinates are measured as the distance from
        - * the origin in units of pixels. The origin [0, 0] is the coordinate in the
        - * upper left of the window and the coordinate in the lower right is [width-1,
        - * height-1].
        + * @name 좌표
        + * @description 모든 도형들은 좌표값으로 지정된 화면 위치에 나타납니다.
        + * 픽셀 단위를 기준으로 원점(0,0)으로부터의 거리 
        + * 모든 좌표값은 원점으로부터의 거리를 픽셀 단위로 측정합니다.
        + * 원점 [0,0]는 화면 좌측 상단의 좌표이며, 우측 하단의 좌표는 [너비-1, 높이-1]에 해당합니다.
          */
         function setup() {
        -  // Sets the screen to be 720 pixels wide and 400 pixels high
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
           createCanvas(720, 400);
         }
         
         function draw() {
        -  // Set the background to black and turn off the fill color
        +  // 배경색을 검정색(0)으로 지정, noFill()로 면채우기 기능 해제
           background(0);
           noFill();
        -
        -  // The two parameters of the point() method each specify
        -  // coordinates.
        -  // The first parameter is the x-coordinate and the second is the Y
        +    
        +  // point()의 괄호 안 두 인수로 좌표값 지정
        +  // 첫번째 인수는 x값을, 두번째 인수는 y값 의미
           stroke(255);
           point(width * 0.5, height * 0.5);
           point(width * 0.5, height * 0.25);
         
        -  // Coordinates are used for drawing all shapes, not just points.
        -  // Parameters for different functions are used for different
        -  // purposes. For example, the first two parameters to line()
        -  // specify the coordinates of the first endpoint and the second
        -  // two parameters specify the second endpoint
        +  // 좌표를 활용해 점 뿐 아니라 모든 도형을 그릴 수 있습니다.
        +  // 각 함수별 괄호에 적힌 매개 변수들은 각기 다른 목적을 위해 사용됩니다.
        +  // 예를들어 line()함수에 쓰인 처음 두 매개 변수들은 각각 첫번째 그리고 두번째 끝점을 지정합니다.
           stroke(0, 153, 255);
           line(0, height * 0.33, width, height * 0.33);
         
        -  // By default, the first two parameters to rect() are the
        -  // coordinates of the upper-left corner and the second pair
        -  // is the width and height
        +  // rect()함수의 처음 두 매개 변수는 상단 모서리의 좌표값을 의미하고,
        +  // 그 다음 두 매개 변수는 너비와 높이를 지정합니다.
           stroke(255, 153, 0);
           rect(width * 0.25, height * 0.1, width * 0.5, height * 0.8);
         }
        diff --git a/src/data/examples/ko/00_Structure/01_Width_and_Height.js b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        index 2c98de592e..933addbe47 100644
        --- a/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        +++ b/src/data/examples/ko/00_Structure/01_Width_and_Height.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Width and Height
        - * @description The 'width' and 'height' variables contain the
        - * width and height of the display window as defined in the createCanvas()
        - * function.
        + * @name 너비와 높이
        + * @description '너비(width)'와 '높이(height)' 변수들은 createCanvas() 함수에 따라
        + * 정의된, 윈도우 화면의 너비 및 높이 값을 포함합니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        index 4f20978143..b5517e7754 100644
        --- a/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        +++ b/src/data/examples/ko/00_Structure/02_Setup_and_Draw.js
        @@ -1,24 +1,22 @@
         /*
        - * @name Setup and Draw
        - * @description The code inside the draw() function runs continuously from top
        - * to bottom until the program is stopped.
        + * @name 설정하고 그리기
        + * @description draw()함수 안에의 코드는 위에서 아래 방향으로
        + * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
          */
         let y = 100;
         
        -// The statements in the setup() function
        -// execute once when the program begins
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
         function setup() {
        -  // createCanvas must be the first statement
        +  // createCanvas가 그 첫 선언문입니다. 
           createCanvas(720, 400);
        -  stroke(255); // Set line drawing color to white
        +  stroke(255); // 선색을 흰색(255)으로 지정
           frameRate(30);
         }
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        +// draw()함 수 안 선언문은 프로그램이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
        -  background(0); // Set the background to black
        +  background(0); // 배경색을 검정색(0)으로 지정
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/03_No_Loop.js b/src/data/examples/ko/00_Structure/03_No_Loop.js
        index 063073be5e..107d2edf8b 100644
        --- a/src/data/examples/ko/00_Structure/03_No_Loop.js
        +++ b/src/data/examples/ko/00_Structure/03_No_Loop.js
        @@ -1,27 +1,25 @@
         /*
        - * @name No Loop
        - * @description The noLoop() function causes draw() to only execute once.
        - * Without calling noLoop(), the code inside draw() is run continually.
        + * @name 루프 해제
        + * @description noLoop()함수는 draw()함수가 반복없이 단 한번만 실행되게 합니다.
        + * noLoop()를 호출하지 않는다면 draw()함수는 계속해서 반복 실행될 것입니다.
          */
         let y;
         
        -// The statements in the setup() function
        -// execute once when the program begins
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
         function setup() {
        -  // createCanvas should be the first statement
        +  // createCanvas가 그 첫 선언문입니다.
           createCanvas(720, 400);
        -  stroke(255); // Set line drawing color to white
        +  stroke(255); // 선색을 흰색(255)으로 지정
           noLoop();
         
           y = height * 0.5;
         }
         
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
        -  background(0); // Set the background to black
        +  background(0); // 배경색을 검정색(0)으로 지정
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/04_Loop.js b/src/data/examples/ko/00_Structure/04_Loop.js
        index bc79823793..058a1d55a4 100644
        --- a/src/data/examples/ko/00_Structure/04_Loop.js
        +++ b/src/data/examples/ko/00_Structure/04_Loop.js
        @@ -1,23 +1,21 @@
         /*
        - * @name Loop
        - * @description The code inside the draw() function runs continuously from top
        - * to bottom until the program is stopped.
        + * @name 루프
        + * @description draw()함수 안에의 코드는 위에서 아래 방향으로
        + * 실행되며, 이는 프로그램이 멈출 때까지 계속해서 반복됩니다.
          */
         let y = 100;
         
        -// The statements in the setup() function
        -// execute once when the program begins
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
         function setup() {
        -  createCanvas(720, 400); // Size must be the first statement
        -  stroke(255); // Set line drawing color to white
        +  createCanvas(720, 400); // 캔버스 크기 지정이 그 첫 선언문입니다.
        +  stroke(255); // 선색을 흰색(255)로 지정
           frameRate(30);
         }
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
        -  background(0); // Set the background to black
        +  background(0); // 배경색을 검정색(0)으로 지정
           y = y - 1;
           if (y < 0) {
             y = height;
        diff --git a/src/data/examples/ko/00_Structure/05_Redraw.js b/src/data/examples/ko/00_Structure/05_Redraw.js
        index 0d23d6bfb8..b4895ea150 100644
        --- a/src/data/examples/ko/00_Structure/05_Redraw.js
        +++ b/src/data/examples/ko/00_Structure/05_Redraw.js
        @@ -1,13 +1,12 @@
         /*
        - * @name Redraw
        - * @description The redraw() function makes draw() execute once. In this example,
        - * draw() is executed once every time the mouse is clicked.
        + * @name 다시 그리기
        + * @description redraw()함수는 draw()함수를 다시 한번 실행합니다.
        + * 이 예제에서 draw()는 마우스가 클릭될 때마다 매번 재실행됩니다.
          */
         
         let y;
         
        -// The statements in the setup() function
        -// execute once when the program begins
        +// setup()함수 속 선언문은 프로그램 시작 시 한번 실행됩니다.
         function setup() {
           createCanvas(720, 400);
           stroke(255);
        @@ -15,10 +14,9 @@ function setup() {
           y = height * 0.5;
         }
         
        -// The statements in draw() are executed until the
        -// program is stopped. Each statement is executed in
        -// sequence and after the last line is read, the first
        -// line is executed again.
        +// 아래의 draw()함수에 포함된 선언문들은 프로그램 실행이 멈출 때까지 계속해서 실행됩니다.
        +// 각 선언문은 위에서 아래 방향으로 순차적으로 실행되며,
        +// 마지막 선언문 실행을 마친 뒤에는 상단의 첫 선언문으로 되돌아갑니다.
         function draw() {
           background(0);
           y = y - 4;
        diff --git a/src/data/examples/ko/00_Structure/06_Functions.js b/src/data/examples/ko/00_Structure/06_Functions.js
        index 24422e123b..47f31593aa 100644
        --- a/src/data/examples/ko/00_Structure/06_Functions.js
        +++ b/src/data/examples/ko/00_Structure/06_Functions.js
        @@ -1,8 +1,7 @@
         /*
        - *@name Functions
        - *@description The drawTarget() function makes it easy to draw many distinct
        - *targets. Each call to drawTarget() specifies the position, size, and number of
        - *rings for each target.
        + *@name 그 외 함수들
        + *@description 각 drawTarget()함수로 과녁판 형상의 도형 여러개를 쉽게 만들 수 있습니다.
        + *호출된 drawTarget()함수들은 각기 다른 과녁판 도형의 위치, 크기 그리고 고리 개수를 지정합니다.
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/00_Structure/07_Recursion.js b/src/data/examples/ko/00_Structure/07_Recursion.js
        index 61935af193..9833a01bae 100644
        --- a/src/data/examples/ko/00_Structure/07_Recursion.js
        +++ b/src/data/examples/ko/00_Structure/07_Recursion.js
        @@ -1,8 +1,8 @@
         /*
        - *@name Recursion
        - *@description A demonstration of recursion, which means functions call themselves.
        - * Notice how the drawCircle() function calls itself at the end of its block.
        - * It continues to do this until the variable "level" is equal to 1.
        + *@name 재귀 함수
        + *@description 재귀 함수는 자기 자신을 다시 호출하는 함수를 말합니다.
        + * drawCircle()함수가 블록 말미에 그 자신을 다시 호출하는 것을 볼 수 있습니다.
        + * 이 경우, drawCircle()함수의 변수인 "level"의 값이 1과 같아질 때까지 계속해서 재호출됩니다.
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/00_Structure/08_Create_Graphics.js b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        index 763c899cf2..5af2a082bf 100644
        --- a/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        +++ b/src/data/examples/ko/00_Structure/08_Create_Graphics.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Create Graphics
        - * @description Creates and returns a new p5.Renderer object. Use this
        - * class if you need to draw into an off-screen graphics buffer. The two parameters
        - * define the width and height in pixels.
        + * @name 그래픽 만들기
        + * @description 새로운 p5.Renderer 오브젝트를 만들고 반환합니다.
        + * 아래의 클래스는 특정 사각 스크린의 바깥 영역에 그래픽 버퍼를 만드는 데에 사용됩니다.
        + * 두 인수들은 사각 스크린의 너비와 높이값을 픽셀 단위로 각각 지정합니다.
          */
         
         let pg;
        @@ -24,6 +24,6 @@ function draw() {
           pg.stroke(255);
           pg.ellipse(mouseX - 150, mouseY - 75, 60, 60);
         
        -  //Draw the offscreen buffer to the screen with image()
        +  //image() 선언문으로 사각 스크린 바깥에 위치한 그래픽 버퍼를 그립니다.
           image(pg, 150, 75);
         }
        diff --git a/src/data/examples/ko/01_Form/00_Points_and_Lines.js b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        index 6871e34110..a7e1028623 100644
        --- a/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        +++ b/src/data/examples/ko/01_Form/00_Points_and_Lines.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Points and Lines
        - * @description Points and lines can be used to draw basic geometry.
        - * Change the value of the variable 'd' to scale the form. The four
        - * variables set the positions based on the value of 'd'.
        + * @name 점과 선
        + * @description 점과 선을 활용하여 기본적인 기하 형태를 그릴 수 있습니다.
        + * 도형의 크기 조정을 위해 변수인 'd'값을 바꿔보세요.
        + * 4개의 변수들은 d값을 기준으로 위치값을 설정합니다.
          */
         function setup() {
           let d = 70;
        @@ -11,21 +11,21 @@ function setup() {
           let p3 = p2 + d;
           let p4 = p3 + d;
         
        -  // Sets the screen to be 720 pixels wide and 400 pixels high
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
           createCanvas(720, 400);
           background(0);
           noSmooth();
         
           translate(140, 0);
         
        -  // Draw gray box
        +  // 회색의 사각형 그리기
           stroke(153);
           line(p3, p3, p2, p3);
           line(p2, p3, p2, p2);
           line(p2, p2, p3, p2);
           line(p3, p2, p3, p3);
         
        -  // Draw white points
        +  // 흰색 점들 그리기
           stroke(255);
           point(p1, p1);
           point(p1, p3);
        diff --git a/src/data/examples/ko/01_Form/01_Shape_Primitives.js b/src/data/examples/ko/01_Form/01_Shape_Primitives.js
        index 728236f9f1..f6d56c4fcd 100644
        --- a/src/data/examples/ko/01_Form/01_Shape_Primitives.js
        +++ b/src/data/examples/ko/01_Form/01_Shape_Primitives.js
        @@ -1,4 +1,14 @@
         /*
        +<<<<<<< HEAD
        + * @name 기본 조형
        + * @description 기본 조형을 그리는 함수로는 triangle(),
        + * rect(), quad(), ellipse(), 그리고 arc()가 있습니다. 사각형은 rect()로,
        + * 원형은 ellipse()로 만들 수 있습니다. 도형의 위치와 크기 조정을 위해
        + * 각 함수들의 괄호 안 인수들을 반드시 지정해야합니다.
        + */
        +function setup() {
        +  // 캔버스 크기를 너비 720픽셀, 높이 720픽셀로 설정
        +=======
          * @name Shape Primitives
          * @description The basic shape primitive functions are triangle(),
          * rect(), quad(), ellipse(), and arc(). Squares are made with rect()
        @@ -7,6 +17,7 @@
          */
         function setup() {
           // Sets the screen to be 720 pixels wide and 400 pixels high
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           createCanvas(720, 400);
           background(0);
           noStroke();
        diff --git a/src/data/examples/ko/01_Form/02_Pie_Chart.js b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        index 9e5a538d42..248006533f 100644
        --- a/src/data/examples/ko/01_Form/02_Pie_Chart.js
        +++ b/src/data/examples/ko/01_Form/02_Pie_Chart.js
        @@ -1,14 +1,13 @@
         /*
        - * @name Pie Chart
        - * @description Uses the arc() function to generate a pie chart from the data
        - * stored in an array.
        + * @name 파이형 차트
        + * @description arc()함수를 사용하여 배열에 저장된 데이터로 파이형 차트를 생성해보세요.
          */
         let angles = [30, 10, 45, 35, 60, 38, 75, 67];
         
         function setup() {
           createCanvas(720, 400);
           noStroke();
        -  noLoop(); // Run once and stop
        +  noLoop(); // 프로그램 시작시 한 번 실행 뒤 멈추기
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/01_Form/03_Regular_Polygon.js b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        index b282c64494..0fd70871c0 100644
        --- a/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        +++ b/src/data/examples/ko/01_Form/03_Regular_Polygon.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Regular Polygon
        - * @description What is your favorite? Pentagon? Hexagon? Heptagon? No?
        - * What about the icosagon? The polygon() function created for this example is
        - * capable of drawing any regular polygon. Try placing different numbers into
        - * the polygon() function calls within draw() to explore.
        + * @name 정다각형
        + * @description 가장 좋아하는 정다각형이 있나요? 오각형? 육각형? 칠각형? 아니면, 이십각형은요?
        + * 이 예제에서 소개하는 polygon()함수는 그 어떠한 정다각형도 그릴 수 있습니다.
        + * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/04_Star.js b/src/data/examples/ko/01_Form/04_Star.js
        index f546a5b0d2..7e98f1d2b4 100644
        --- a/src/data/examples/ko/01_Form/04_Star.js
        +++ b/src/data/examples/ko/01_Form/04_Star.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Star
        - * @description The star() function created for this example is capable of
        - * drawing a wide range of different forms. Try placing different numbers
        - * into the star() function calls within draw() to explore.
        + * @name 별모양
        + * @description 이 예제에서 소개하는 star()함수는 여러가지 다양한 모양을 그립니다. 
        + * draw()함수 내에 호출된 polygon() 안에 다양한 숫자를 넣어 탐구해보세요.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/05_Triangle_Strip.js b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        index 3d7ed3622b..62308eea3d 100644
        --- a/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        +++ b/src/data/examples/ko/01_Form/05_Triangle_Strip.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Triangle Strip
        - * @description Example by Ira Greenberg. Generate a closed ring using the
        - * vertex() function and beginShape(TRIANGLE_STRIP) mode. The outsideRadius
        - * and insideRadius variables control ring's radii respectively.
        + * @name 삼각형 고리
        + * @description 이라 그린버그(Ira Greenberg) 제작 예제. vertex()함수와
        + * beginShape(TRIANGLE_STRIP) 모드를 이용하여 닫힌 고리를 하나 생성하세요. 
        + * outsideRadius와 insideRadius 변수를 이용하여 각 고리의 지름(radius)을 조정할 수 있습니다.
          */
         let x;
         let y;
        diff --git a/src/data/examples/ko/01_Form/06_Bezier.js b/src/data/examples/ko/01_Form/06_Bezier.js
        index 40325a9858..8e779bb045 100644
        --- a/src/data/examples/ko/01_Form/06_Bezier.js
        +++ b/src/data/examples/ko/01_Form/06_Bezier.js
        @@ -1,9 +1,7 @@
         /*
        - * @name Bezier
        - * @description The first two parameters for the bezier() function specify the
        - * first point in the curve and the last two parameters specify the last point.
        - * The middle parameters set the control points that define the shape of the
        - * curve.
        + * @name 베지어 곡선
        + * @description bezier()함수의 처음 두 매개변수들은 각각 곡선의 시작점과 끝점을 지정합니다.
        + * 중간의 인수들은 곡선의 모양을 조정하는 '조정점(control point)'들입니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/01_Form/07_3D_Primitives.js b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        index bf925b71ee..4c6245d0e6 100644
        --- a/src/data/examples/ko/01_Form/07_3D_Primitives.js
        +++ b/src/data/examples/ko/01_Form/07_3D_Primitives.js
        @@ -1,9 +1,9 @@
         /*
        - * @name 3D Primitives
        + * @name 3D 기본 조형
          * @frame 720,400 (optional)
        - * @description Placing mathematically 3D objects in synthetic space.
        - * The box() and sphere() functions take at least one parameter to specify their
        - * size. These shapes are positioned using the translate() function.
        + * @description 3D 객체를 합성 공간 속에 수학적으로 배치하기.
        + * box()와 sphere()함수는 최소 한 개의 매개변수를 사용하여 그 크기를 조정할 수 있습니다.
        + * 도형의 위치는 translate()함수를 통해 조정할 수 있습니다.
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/02_Data/00_Variables.js b/src/data/examples/ko/02_Data/00_Variables.js
        index d30fbd12d5..115ee139d5 100644
        --- a/src/data/examples/ko/02_Data/00_Variables.js
        +++ b/src/data/examples/ko/02_Data/00_Variables.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Variables
        - * @description Variables are used for storing values. In this example, change
        - * the values of variables to affect the composition.
        + * @name 변수
        + * @description 변수는 값을 저장하기 위해 사용됩니다. 예제의 변수값을 바꿔 구성을 변형해보세요.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/02_Data/01_True_and_False.js b/src/data/examples/ko/02_Data/01_True_and_False.js
        index ca32f3c0cf..4ebc9f2224 100644
        --- a/src/data/examples/ko/02_Data/01_True_and_False.js
        +++ b/src/data/examples/ko/02_Data/01_True_and_False.js
        @@ -1,10 +1,9 @@
         /*
        - * @name True and False
        - * @description A Boolean variable has only two possible values: true or false.
        - * It is common to use Booleans with control statements to determine the flow
        - * of a program. In this example, when the boolean value "b" is true, vertical
        - * lines are drawn and when the boolean value "b" is false, horizontal
        - * lines are drawn.
        + * @name 참과 거짓
        + * @description 불리언(Boolean) 변수는 오직 'true(참)'과 'false(거짓)'이라는 두 개의 값만 갖습니다.
        + * 불리언과 함께 제어문을 사용하여 프로그램의 흐름을 조정하는 것이 일반적인 방식입니다. 
        + * 이 예제에서는, b값이 'true(참)'일 때 세로선들이 그려지고
        + * b값이 'false(거짓)'일 때 가로선들이 그려집니다.
          */
         function setup() {
           createCanvas(720, 400);
        @@ -19,12 +18,12 @@ function setup() {
             b = i < middle;
         
             if (b === true) {
        -      // Vertical line
        +      // 세로선
               line(i, d, i, height - d);
             }
         
             if (b === false) {
        -      // Horizontal line
        +      // 가로선
               line(middle, i - middle + d, width - d, i - middle + d);
             }
           }
        diff --git a/src/data/examples/ko/02_Data/03_Variable_Scope.js b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        index a9e262c39e..92b74cc6fe 100644
        --- a/src/data/examples/ko/02_Data/03_Variable_Scope.js
        +++ b/src/data/examples/ko/02_Data/03_Variable_Scope.js
        @@ -1,14 +1,12 @@
         /*
        - * @name Variable Scope
        - * @description Variables have a global or function "scope". For example,
        - * variables declared within either the setup() or draw() functions may be
        - * only used in these functions. Global variables, variables declared outside
        - * of setup() and draw(), may be used anywhere within the program. If a function
        - * variable is declared with the same name as a global variable, the program
        - * will use the function variable to make its calculations within the current
        - * scope.
        + * @name 변수 범위
        + * @description 변수는 '전역(global) 변수'로서 선언되거나, 그 범위를 조정하여 '지역(local) 변수'로 사용할 수 있습니다.
        + * 예를 들어, setup() 및 draw()함수 안에 선언된 변수들은 해당 함수들의 범위 내에서만 사용되는 '지역 변수'가 됩니다.
        + * '전역 변수'의 경우, setup() 및 draw()함수 범위 외에서 사용 가능합니다.
        + * 어떤 함수의 '지역 변수'가 '전역 변수'와 동일한 이름으로 선언된 경우,
        + * 이 변수는 해당 함수에 한해 지역 변수로서 처리됩니다.
          */
        -let a = 80; // Create a global variable "a"
        +let a = 80; // 전역 변수 "a" 생성하기
         
         function setup() {
           createCanvas(720, 400);
        @@ -18,31 +16,30 @@ function setup() {
         }
         
         function draw() {
        -  // Draw a line using the global variable "a"
        +  // 전역 변수 a를 사용하여 선 그리기
           line(a, 0, a, height);
         
        -  // Use a local variable a in for loop
        +  // 반복문 안에 지역 변수 a를 사용하기
           for (let a = 120; a < 200; a += 3) {
             line(a, 0, a, height);
           }
         
        -  // Make a call to the custom function drawAnotherLine()
        +  // 사용자가 만든 함수 drawAnotherLine() 호출하기
           drawAnotherLine();
         
        -  // Make a call to the custom function drawYetAnotherLine()
        +  // 사용자가 만든 함수 drawYetAnotherLine() 호출하기
           drawYetAnotherLine();
         }
         
         function drawAnotherLine() {
        -  // Create a new variable "a" local to this function
        +  // 이 함수에 대한 지역 변수로서 새로운 a 선언하기
           let a = 320;
        -  // Draw a line using the local variable "a"
        +  // 지역 변수 a를 사용하여 선 그리기  line(a, 0, a, height);
           line(a, 0, a, height);
         }
         
         function drawYetAnotherLine() {
        -  // Because no new local variable "a" is set,
        -  // this line draws using the original global
        -  // variable "a" which is set to the value 20.
        +  // 새로운 지역 변수 a를 선언하지 않았으므로,
        +  // 이 선은 위에서 선언된 전역 변수 a(값 80)를 사용하여 그려집니다.
           line(a + 3, 0, a + 3, height);
         }
        diff --git a/src/data/examples/ko/02_Data/04_Numbers.js b/src/data/examples/ko/02_Data/04_Numbers.js
        index de4d0ea147..56dd62c09e 100644
        --- a/src/data/examples/ko/02_Data/04_Numbers.js
        +++ b/src/data/examples/ko/02_Data/04_Numbers.js
        @@ -1,13 +1,12 @@
         /*
        - * @name Numbers
        + * @name 숫자값
          * @frame 720,400
        - * @description Numbers can be written with or without decimals. An integer
        - * (more commonly called an int) is a number without a decimal point. A float
        - * is a floating-point number, which means it is a number that has a decimal
        - * place.
        + * @description 숫자값은 소수점과 함께, 또는 없이 사용할 수 있습니다.
        + * 보통 "int"라 불리는 정수(integer)는 소수점이 없는 숫자를 말합니다.
        + * 실수(float)는 소수점 이하 자릿수를 갖는 부동소수점 숫자를 말합니다.
          */
        -let a = 0; // Create a global variable "a" of type Number
        -let b = 0; // Create a global variable "b" of type Number
        +let a = 0; // "a"를 숫자형 전역 변수로 선언
        +let b = 0; // "b"를 숫자형 전역 변수로 선언
         
         function setup() {
           createCanvas(720, 400);
        @@ -17,8 +16,8 @@ function setup() {
         function draw() {
           background(0);
         
        -  a = a + 1; // Increment a with an integer
        -  b = b + 0.2; //Increment b with a float
        +  a = a + 1; // a를 정수 단위로 증가
        +  b = b + 0.2; // b를 실수 단위로 증가
           line(a, 0, a, height / 2);
           line(b, height / 2, b, height);
         
        diff --git a/src/data/examples/ko/03_Arrays/00_Array.js b/src/data/examples/ko/03_Arrays/00_Array.js
        index cfee6876d5..4f624aaaa8 100644
        --- a/src/data/examples/ko/03_Arrays/00_Array.js
        +++ b/src/data/examples/ko/03_Arrays/00_Array.js
        @@ -1,12 +1,10 @@
         /*
        - * @name Array
        - * @description An array is a list of data. Each piece of data in an array
        - * is identified by an index number representing its position in
        - * the array. Arrays are zero based, which means that the first
        - * element in the array is [0], the second element is [1], and so on.
        - * In this example, an array named "coswave" is created and
        - * filled with the cosine values. This data is displayed three
        - * separate ways on the screen.
        + * @name 배열
        + * @description 배열은 데이터의 리스트를 말합니다. 배열 속 각 데이터는 
        + * 배열에서의 위치를 나타내는 색인(index) 번호로 식별됩니다. 배열의 시작은 0을 기준으로 합니다.
        + * 따라서, 배열의 첫 번째 데이터는 [0]이고 두 번째 데이터는 [1]로 식별됩니다.
        + * 이 예제에서는 "coswave"라는 배열을 만들고, 이를 코사인 값으로 채웁니다.
        + * 데이터는 실행 화면상 세 가지의 다른 방법으로 표현됩니다.
          */
         let coswave = [];
         
        diff --git a/src/data/examples/ko/03_Arrays/01_Array_2d.js b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        index 87809b11ab..47da9cc5f1 100644
        --- a/src/data/examples/ko/03_Arrays/01_Array_2d.js
        +++ b/src/data/examples/ko/03_Arrays/01_Array_2d.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Array 2D
        - * @description Demonstrates the syntax for creating a two-dimensional (2D)
        - * array. Values in a 2D array are accessed through two index values.
        - * 2D arrays are useful for storing images. In this example, each dot
        - * is colored in relation to its distance from the center of the image.
        + * @name 2D 배열
        + * @description 2차원(2D) 배열 작성을 위한 구문입니다.
        + * 2D 배열의 값은 두 개의 색인(index)값을 통해 가져올 수 있습니다.
        + * 2D 배열은 이미지를 저장하는 데에 유용합니다. 
        + * 이 예제에서 각 점의 색상은 이미지 중심으로부터의 거리에 따라 지정됩니다.
          */
         let distances = [];
         let maxDistance;
        @@ -13,22 +13,21 @@ function setup() {
           createCanvas(720, 360);
           maxDistance = dist(width / 2, height / 2, width, height);
           for (let x = 0; x < width; x++) {
        -    distances[x] = []; // create nested array
        +    distances[x] = []; // 중첩 배열 만들기
             for (let y = 0; y < height; y++) {
               let distance = dist(width / 2, height / 2, x, y);
               distances[x][y] = (distance / maxDistance) * 255;
             }
           }
           spacer = 10;
        -  noLoop(); // Run once and stop
        +  noLoop(); // 한번 실행 후 멈추기
         }
         
         function draw() {
           background(0);
        -  // This embedded loop skips over values in the arrays based on
        -  // the spacer variable, so there are more values in the array
        -  // than are drawn here. Change the value of the spacer variable
        -  // to change the density of the points
        +  // 이 함수에 내장된 반복문은 앞서 선언된 spacer변수에 따라 배열값 사이의 간격을 생성하게 됩니다.
        +  // 따라서, 이 함수로 그려진 것보다 더 많은 값이 배열에 있는 셈입니다.
        +  // spacer 변수의 값을 변경하여 점들 간의 밀도를 조정해보세요.
           for (let x = 0; x < width; x += spacer) {
             for (let y = 0; y < height; y += spacer) {
               stroke(distances[x][y]);
        diff --git a/src/data/examples/ko/03_Arrays/02_Array_Objects.js b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        index 417b5c49a7..8379a2066e 100644
        --- a/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        +++ b/src/data/examples/ko/03_Arrays/02_Array_Objects.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Array Objects
        - * @description Demonstrates the syntax for creating an array of custom objects.
        + * @name 객체 배열
        + * @description 사용자가 정의한 객체 배열을 만듭니다.
          */
         
         class Module {
        @@ -15,7 +15,7 @@ class Module {
             this.yDir = 1;
           }
         
        -  // Custom method for updating the variables
        +  // 사용자 정의한 메소드를 통해 변수들을 업데이트합니다.
           update() {
             this.x = this.x + this.speed * this.xDir;
             if (this.x >= this.unit || this.x <= 0) {
        @@ -29,7 +29,7 @@ class Module {
             }
           }
         
        -  // Custom method for drawing the object
        +  // 사용자가 정의한 메소드를 통해 오브젝트를 그립니다.
           draw() {
             fill(255);
             ellipse(this.xOff + this.x, this.yOff + this.y, 6, 6);
        diff --git a/src/data/examples/ko/04_Control/00_Iteration.js b/src/data/examples/ko/04_Control/00_Iteration.js
        index 6d940fbb85..5bfeee8b68 100644
        --- a/src/data/examples/ko/04_Control/00_Iteration.js
        +++ b/src/data/examples/ko/04_Control/00_Iteration.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Iteration
        - * @description Iteration with a "for" structure to construct repetitive forms.
        + * @name for 반복문
        + * @description "for"구조를 사용하여 반복 형식을 만듭니다.
          */
         let y;
         let num = 14;
        @@ -10,7 +10,7 @@ function setup() {
           background(102);
           noStroke();
         
        -  // Draw white bars
        +  // 흰색 막대기들 그리기
           fill(255);
           y = 60;
           for (let i = 0; i < num / 3; i++) {
        @@ -18,7 +18,7 @@ function setup() {
             y += 20;
           }
         
        -  // Gray bars
        +  // 회색 막대기들
           fill(51);
           y = 40;
           for (let i = 0; i < num; i++) {
        @@ -31,7 +31,7 @@ function setup() {
             y += 20;
           }
         
        -  // Thin lines
        +  // 얇은 선들
           y = 45;
           fill(0);
           for (let i = 0; i < num - 1; i++) {
        diff --git a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        index 58163705a6..33c571bb01 100644
        --- a/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        +++ b/src/data/examples/ko/04_Control/01_Embedded_Iteration.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Embedded Iteration
        - * @description Embedding "for" structures allows repetition in two dimensions.
        + * @name for 내장 반복문
        + * @description "for" 반복문 구조를 이중 사용하여 2차원 도형을 반복할 수 있습니다.
          */
         function setup() {
           createCanvas(720, 360);
        diff --git a/src/data/examples/ko/04_Control/02_Conditionals_1.js b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        index 935bbbc919..3d809536b0 100644
        --- a/src/data/examples/ko/04_Control/02_Conditionals_1.js
        +++ b/src/data/examples/ko/04_Control/02_Conditionals_1.js
        @@ -1,20 +1,18 @@
         /*
        - * @name Conditionals 1
        - * @description Conditions are like questions.
        - * They allow a program to decide to take one action if
        - * the answer to a question is true or to do another action
        - * if the answer to the question is false.
        - * The questions asked within a program are always logical
        - * or relational statements. For example, if the variable 'i' is
        - * equal to zero then draw a line.
        + * @name 조건문 1
        + * @description 조건문은 마치 질문과도 같습니다.
        + * 프로그램은 조건문이 던지는 질문이 참인지 거짓인지에 따라
        + * 특정 선언문을 실행할 지 여부를 결정합니다.
        + * 조건문으로 던지는 질문들은 언제나 논리 또는 관계 선언문의 형식을 갖습니다. 
        + * 이 예제의 경우, 변수 i가 0이라는 조건이 충족될 시 선이 그려집니다.
          */
         function setup() {
           createCanvas(720, 360);
           background(0);
         
           for (let i = 10; i < width; i += 10) {
        -    // If 'i' divides by 20 with no remainder draw the first line
        -    // else draw the second line
        +    // i가 20으로 나누어 떨어진다면, 첫번째 선을 그린다.
        +    // 그렇지 않을 경우, 두번째 선을 그린다.
             if (i % 20 === 0) {
               stroke(255);
               line(i, 80, i, height / 2);
        diff --git a/src/data/examples/ko/04_Control/03_Conditionals_2.js b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        index 71487dc708..bde90ef016 100644
        --- a/src/data/examples/ko/04_Control/03_Conditionals_2.js
        +++ b/src/data/examples/ko/04_Control/03_Conditionals_2.js
        @@ -1,25 +1,24 @@
         /*
        - * @name Conditionals 2
        - * @description We extend the language of conditionals from the previous
        - * example by adding the keyword "else". This allows conditionals
        - * to ask two or more sequential questions, each with a different
        - * action.
        + * @name 조건문 2
        + * @description 조건문 1 예제에 "else"라는 키워드를 더해 조건문의 문법을 확장해봅시다.
        + * "else"를 사용하면 연속하여 2개 이상의 질문을 던질 수 있습니다.
        + * 이 때, 각각의 질문은 서로 다른 행위를 요청할 수 있습니다.
          */
         function setup() {
           createCanvas(720, 360);
           background(0);
         
           for (let i = 2; i < width - 2; i += 4) {
        -    // If 'i' divides by 20 with no remainder
        +    // i가 20으로 나누어 떨어질 경우
             if (i % 20 === 0) {
               stroke(255);
               line(i, 80, i, height / 2);
        -      // If 'i' divides by 10 with no remainder
        +      // i가 10으로 나누어 떨어질 경우
             } else if (i % 10 === 0) {
               stroke(153);
               line(i, 20, i, 180);
        -      // If neither of the above two conditions are met
        -      // then draw this line
        +      // 위의 두 조건 모두 충족하지 않을 경우
        +      // 이 선을 그린다.
             } else {
               stroke(102);
               line(i, height / 2, i, height - 20);
        diff --git a/src/data/examples/ko/04_Control/04_Logical_Operators.js b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        index aef6f2f0ff..4f3436dce7 100644
        --- a/src/data/examples/ko/04_Control/04_Logical_Operators.js
        +++ b/src/data/examples/ko/04_Control/04_Logical_Operators.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Logical Operators
        - * @description The logical operators for AND (&&) and OR (||) are used to
        - * combine simple relational statements into more complex expressions.
        - * The NOT (!) operator is used to negate a boolean statement.
        + * @name 논리적 연산자
        + * @description 논리 연산자인 AND (&&) 와 OR (||) 는 
        + * 간단한 관계 선언문에 좀 더 복잡한 조건을 더할 때 쓰입니다.
        + * NOT (!) 연산자는 불리언 선언문을 부정할 때 쓰입니다.
          */
         let test = false;
         
        @@ -11,29 +11,29 @@ function setup() {
           background(126);
         
           for (let i = 5; i <= height; i += 5) {
        -    // Logical AND
        +    // 논리적 연산자 AND
             stroke(0);
             if (i > 35 && i < 100) {
               line(width / 4, i, width / 2, i);
               test = false;
             }
         
        -    // Logical OR
        +    // 논리적 연산자 OR
             stroke(76);
             if (i <= 35 || i >= 100) {
               line(width / 2, i, width, i);
               test = true;
             }
         
        -    // Testing if a boolean value is "true"
        -    // The expression "if(test)" is equivalent to "if(test == true)"
        +    // 불리언 값이 참(true)인지 여부를 테스트
        +    // "if(test)"이 "if(test == true)"와 동일한지 여부를 확인
             if (test) {
               stroke(0);
               point(width / 3, i);
             }
         
        -    // Testing if a boolean value is "false"
        -    // The expression "if(!test)" is equivalent to "if(test == false)"
        +    // 불리언 값이 거짓(false)인지 여부를 테스트
        +    // "if(!test)"이 "if(test == false)"와 동일한지 여부를 확인
             if (!test) {
               stroke(255);
               point(width / 4, i);
        diff --git a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        index 9824b68d46..5111273db6 100644
        --- a/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        +++ b/src/data/examples/ko/05_Image/00_Load_and_Display_Image.js
        @@ -1,22 +1,19 @@
         /*
        - * @name Load and Display Image
        - * @description Images can be loaded and displayed to the screen at their
        - * actual size or any other size.
        - * <p><em><span class="small"> To run this example locally, you will need an 
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        -
        + * @name 이미지 불러오기 및 보이기
        + * @description 이미지를 실제 또는 다른 크기로 지정하여 화면상 불러오고 보이게 할 수 있습니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
        -let img; // Declare variable 'img'.
        +let img; // 변수 'img' 선언
         
         function setup() {
           createCanvas(720, 400);
        -  img = loadImage('assets/moonwalk.jpg'); // Load the image
        +  img = loadImage('assets/moonwalk.jpg'); // 이미지 불러오기
         }
         
         function draw() {
        -  // Displays the image at its actual size at point (0,0)
        +  // 이미지를 화면상 좌표 (0,0) 위치에 실제 크기로 보이게 한다.
           image(img, 0, 0);
        -  // Displays the image at point (0, height/2) at half size
        +  // 이미지를 화면상 좌표 (0,높이/2) 위치에 절반 크기로 보이게 한다.
           image(img, 0, height / 2, img.width / 2, img.height / 2);
         }
        diff --git a/src/data/examples/ko/05_Image/01_Background_Image.js b/src/data/examples/ko/05_Image/01_Background_Image.js
        index 80a63e461a..2dd361abad 100644
        --- a/src/data/examples/ko/05_Image/01_Background_Image.js
        +++ b/src/data/examples/ko/05_Image/01_Background_Image.js
        @@ -1,19 +1,18 @@
         /*
        - * @name Background Image
        - * @description This example presents the fastest way to load a
        - * background image. To load an image as the background,
        - * it must be the same width and height as the program.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 배경 이미지
        + * @description 이 예제는 배경 이미지를 불러오는 가장 빠른 방법을 소개합니다. This example presents the fastest way to load a
        + * 이미지 파일을 배경으로 쓰기 위해선, 이미지의 너비와 높이를 
        + * 프로그램 화면 크기와 동일하게 맞추면 됩니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
         let bg;
         let y = 0;
         
         function setup() {
        -  // The background image must be the same size as the parameters
        -  // into the createCanvas() method. In this program, the size of
        -  // the image is 720x400 pixels.
        +  // 이미지 파일을 배경으로 쓰기 위해, createCanvas() 메소드의 인수에
        +  // 이미지 크기와 동일한 사이즈를 기입하면 됩니다.
        +  // 이 예제의 경우, 이미지 크기는 720x400 픽셀입니다.
           bg = loadImage('assets/moonwalk.jpg');
           createCanvas(720, 400);
         }
        diff --git a/src/data/examples/ko/05_Image/02_Transparency.js b/src/data/examples/ko/05_Image/02_Transparency.js
        index 39cb96bb6a..dd608742d3 100644
        --- a/src/data/examples/ko/05_Image/02_Transparency.js
        +++ b/src/data/examples/ko/05_Image/02_Transparency.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Transparency
        - * @description Move the pointer left and right across the image to change its
        - * position. This program overlays one image over another by modifying the
        - * alpha value of the image with the tint() function.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 투명도
        + * @description 마우스 포인터를 좌우로 움직혀 이미지의 위치를 옮겨보세요.
        + * 이 예제의 경우, tint()함수로 알파값이 수정된 이미지를 원본 이미지에 위에 겹쳐 보여줍니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
         let img;
         let offset = 0;
        @@ -13,13 +11,13 @@ let easing = 0.05;
         
         function setup() {
           createCanvas(720, 400);
        -  img = loadImage('assets/moonwalk.jpg'); // Load an image into the program
        +  img = loadImage('assets/moonwalk.jpg'); // 프로그램상 이미지 불러오기
         }
         
         function draw() {
        -  image(img, 0, 0); // Display at full opacity
        +  image(img, 0, 0); // 이미지를 투명도 100%로 보이게하기
           let dx = mouseX - img.width / 2 - offset;
           offset += dx * easing;
        -  tint(255, 127); // Display at half opacity
        +  tint(255, 127); // 이미지를 투명도 50%로 보이게하기
           image(img, offset, 0);
         }
        diff --git a/src/data/examples/ko/05_Image/03_Alpha_Mask.js b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        index 0e57e3533c..ad500307c6 100644
        --- a/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        +++ b/src/data/examples/ko/05_Image/03_Alpha_Mask.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Alpha Mask
        - * @description Loads a "mask" for an image to specify the transparency in
        - * different parts of the image. The two images are blended together using
        - * the mask() method of p5.Image.
        - * <p><em><span class="small"> To run this example locally, you will need two
        - * image files, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 알파 마스크
        + * @description 이미지 일부의 투명도를 설정하기 위해 마스크를 불러옵니다.
        + * 이미지와 마스크는 p5.Image의 mask() 메소드를 통해 합쳐집니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
         let img;
         let imgMask;
        diff --git a/src/data/examples/ko/05_Image/04_Create_Image.js b/src/data/examples/ko/05_Image/04_Create_Image.js
        index 481f4b0ce4..a051fcb02e 100644
        --- a/src/data/examples/ko/05_Image/04_Create_Image.js
        +++ b/src/data/examples/ko/05_Image/04_Create_Image.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Create Image
        - * @description The createImage() function provides a fresh buffer of pixels to
        - * play with. This example creates an image gradient.
        + * @name 이미지 만들기
        + * @description createImage() 함수로 재밌는 픽셀 버퍼를 만들 수 있습니다.
        + * 이 예제는 그래디언트 이미지를 만듭니다.
          */
        -let img; // Declare variable 'img'.
        +let img; // 'img' 변수 선언하기
         
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/05_Image/05_Pointillism.js b/src/data/examples/ko/05_Image/05_Pointillism.js
        index e256756c9e..04a9391294 100644
        --- a/src/data/examples/ko/05_Image/05_Pointillism.js
        +++ b/src/data/examples/ko/05_Image/05_Pointillism.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Pointillism
        - * @description By Dan Shiffman. Mouse horizontal location controls size of
        - * dots. Creates a simple pointillist effect using ellipses colored according
        - * to pixels in an image.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 점묘법
        + * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스의 가로 위치는 점의 크기를 조정합니다. 
        + * 픽셀에 따라 색칠된 원형(ellipse)으로 간단한 점묘법 효과를 만듭니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
         let img;
         let smallPoint, largePoint;
        diff --git a/src/data/examples/ko/07_Color/00_Hue.js b/src/data/examples/ko/07_Color/00_Hue.js
        index bb1e02ed95..3719823704 100644
        --- a/src/data/examples/ko/07_Color/00_Hue.js
        +++ b/src/data/examples/ko/07_Color/00_Hue.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Hue
        - * @description Hue is the color reflected from or transmitted through an
        - * object and is typically referred to as the name of the color (red, blue,
        - * yellow, etc.) Move the cursor vertically over each bar to alter its hue.
        + * @name 색조
        + * @description 색조는 오브젝트에 반사되거나 이를 통해 전달된 색상을 말하며,
        + * 일반적으로 색상명(빨강, 파랑, 노랑 등)으로 불립니다.
        + * 마우스 커서를 세로축으로 움직여 막대기의 색조를 변경해 보세요.
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/ko/07_Color/01_Saturation.js b/src/data/examples/ko/07_Color/01_Saturation.js
        index 7394cf7dbf..0e9cb3fff6 100644
        --- a/src/data/examples/ko/07_Color/01_Saturation.js
        +++ b/src/data/examples/ko/07_Color/01_Saturation.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Saturation
        - * @description Saturation is the strength or purity of the color and
        - * represents the amount of gray in proportion to the hue. A "saturated"
        - * color is pure and an "unsaturated" color has a large percentage of gray.
        - * Move the cursor vertically over each bar to alter its saturation.
        + * @name 채도
        + * @description 채도는 회색이 차지하는 비율에 따른, 색조의 짙음 또는 맑음 정도를 말합니다.
        + * 포화된 색은 맑고, 불포화된 색은 높은 비율의 회색조를 갖습니다.
        + * 마우스 커서를 세로축으로 움직여 막대기의 채도를 변경해 보세요.
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/ko/07_Color/02_Brightness.js b/src/data/examples/ko/07_Color/02_Brightness.js
        index 17f29af7f2..46352ed4bb 100644
        --- a/src/data/examples/ko/07_Color/02_Brightness.js
        +++ b/src/data/examples/ko/07_Color/02_Brightness.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Brightness
        - * @description By Dan Shiffman. This program adjusts the brightness of a part
        - * of the image by calculating the distance of each pixel to the mouse.
        - * <p><em><span class="small"> To run this example locally, you will need
        - * at least an image file and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 밝기
        + * @description 다니엘 쉬프만(Dan Shiffman) 제작. 마우스와 각 픽셀 간의 거리값을 
        + * 계산하여 이미지 일부의 밝기를 조정합니다. 
        + * <p><em><span class="small"> 로컬 컴퓨터에서 이 예제를 실행하려면, 이미지 파일을 준비하시고
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시키세요.</span></em></p>
          */
         let img;
         
        @@ -21,19 +21,19 @@ function setup() {
         function draw() {
           for (let x = 0; x < img.width; x++) {
             for (let y = 0; y < img.height; y++) {
        -      // Calculate the 1D location from a 2D grid
        +      // 2D 그리드로부터 1차원 위치 계산
               let loc = (x + y * img.width) * 4;
        -      // Get the R,G,B values from image
        +      // 이미지에서 R,G,B값 받기
               let r, g, b;
               r = img.pixels[loc];
        -      // Calculate an amount to change brightness based on proximity to the mouse
        +      // 마우스와의 거리에 따라 변경할 밝기 계산
               let maxdist = 50;
               let d = dist(x, y, mouseX, mouseY);
               let adjustbrightness = (255 * (maxdist - d)) / maxdist;
               r += adjustbrightness;
        -      // Constrain RGB to make sure they are within 0-255 color range
        +      // RGB의 색상 범위가 0-255에 국한되도록 설정
               r = constrain(r, 0, 255);
        -      // Make a new color and set pixel in the window
        +      // 새로운 색상 생성 후 화면에 픽셀 위치 고정
               //color c = color(r, g, b);
               let pixloc = (y * width + x) * 4;
               pixels[pixloc] = r;
        diff --git a/src/data/examples/ko/07_Color/03_Color_Variables.js b/src/data/examples/ko/07_Color/03_Color_Variables.js
        index 2151681561..5c3aa3d911 100644
        --- a/src/data/examples/ko/07_Color/03_Color_Variables.js
        +++ b/src/data/examples/ko/07_Color/03_Color_Variables.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Color Variables
        - * @description (Homage to Albers.) This example creates variables for colors
        - * that may be referred to in the program by a name, rather than a number.
        + * @name 색상 변수
        + * @description (Albers에게 바칩니다.) 이 예제는 색상 조정을 위한 변수 생성 방법을 다룹니다.
        + * 이 때, 변수들은 숫자가 아닌 특정 명칭으로 지정됩니다.
          */
         function setup() {
           createCanvas(710, 400);
        @@ -12,8 +12,8 @@ function setup() {
           let middle = color(204, 153, 0);
           let outside = color(153, 51, 0);
         
        -  // These statements are equivalent to the statements above.
        -  // Programmers may use the format they prefer.
        +  // 아래의 변수 선언문은 위의 선언문들과 동일합니다.
        +  // 둘 중 원하는 형식을 사용하면 됩니다.
           //let inside = color('#CC6600');
           //let middle = color('#CC9900');
           //let outside = color('#993300');
        diff --git a/src/data/examples/ko/07_Color/04_Relativity.js b/src/data/examples/ko/07_Color/04_Relativity.js
        index 010ef7489f..f54aef95d9 100644
        --- a/src/data/examples/ko/07_Color/04_Relativity.js
        +++ b/src/data/examples/ko/07_Color/04_Relativity.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Relativity
        - * @description Each color is perceived in relation to other colors. The top
        - * and bottom bars each contain the same component colors, but a different
        - * display order causes individual colors to appear differently.
        + * @name 상대성
        + * @description 각 색상은 다른 색상과의 관계 속에서 인식됩니다. 
        + * 상단과 하단의 막대기들은 둘 다 동일한 색상 요소들을 갖지만,
        + * 색상 요소들의 배열에 따라 마치 다른 색조를 갖는 듯 보입니다.
          */
         let a, b, c, d, e;
         
        @@ -14,7 +14,7 @@ function setup() {
           c = color(42, 106, 105);
           d = color(165, 89, 20);
           e = color(146, 150, 127);
        -  noLoop(); // Draw only one time
        +  noLoop(); // 반복없이 한번만 그리기
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/07_Color/05_Linear_Gradient.js b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        index a99dcbbdf7..95c2feb2ca 100644
        --- a/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        +++ b/src/data/examples/ko/07_Color/05_Linear_Gradient.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Linear Gradient
        - * @description The lerpColor() function is useful for interpolating between
        - * two colors.
        + * @name 선형 그래디언트
        + * @description lerpColor() 함수는 두 가지 색상을 보간하는 데에 쓰입니다.
          */
        -// Constants
        +// 상수
         const Y_AXIS = 1;
         const X_AXIS = 2;
         let b1, b2, c1, c2;
        @@ -11,7 +10,7 @@ let b1, b2, c1, c2;
         function setup() {
           createCanvas(710, 400);
         
        -  // Define colors
        +  // 색상 정의하기
           b1 = color(255);
           b2 = color(0);
           c1 = color(204, 102, 0);
        @@ -21,10 +20,10 @@ function setup() {
         }
         
         function draw() {
        -  // Background
        +  // 배경
           setGradient(0, 0, width / 2, height, b1, b2, X_AXIS);
           setGradient(width / 2, 0, width / 2, height, b2, b1, X_AXIS);
        -  // Foreground
        +  // 전경
           setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
           setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
         }
        @@ -33,7 +32,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
           noFill();
         
           if (axis === Y_AXIS) {
        -    // Top to bottom gradient
        +    // 위에서 아래 방향 그래디언트
             for (let i = y; i <= y + h; i++) {
               let inter = map(i, y, y + h, 0, 1);
               let c = lerpColor(c1, c2, inter);
        @@ -41,7 +40,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
               line(x, i, x + w, i);
             }
           } else if (axis === X_AXIS) {
        -    // Left to right gradient
        +    // 왼쪽에서 오른쪽 방향 그래디언트
             for (let i = x; i <= x + w; i++) {
               let inter = map(i, x, x + w, 0, 1);
               let c = lerpColor(c1, c2, inter);
        diff --git a/src/data/examples/ko/07_Color/06_Radial_Gradient.js b/src/data/examples/ko/07_Color/06_Radial_Gradient.js
        index 51e1f37404..e360963b2b 100644
        --- a/src/data/examples/ko/07_Color/06_Radial_Gradient.js
        +++ b/src/data/examples/ko/07_Color/06_Radial_Gradient.js
        @@ -1,7 +1,12 @@
         /*
        +<<<<<<< HEAD
        + * @name 방사형 그래디언트
        + * @description 동심원을 그려 한 색상이 다른 색상으로 퍼지는 듯한 효과를 만듭니다.
        +=======
          * @name Radial Gradient
          * @description Draws a series of concentric circles to create a gradient
          * from one color to another.
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let dim;
         
        diff --git a/src/data/examples/ko/07_Color/07_Lerp_Color.js b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        index 471a2df17e..0c1324183f 100644
        --- a/src/data/examples/ko/07_Color/07_Lerp_Color.js
        +++ b/src/data/examples/ko/07_Color/07_Lerp_Color.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Lerp Color
        - * @description Loop random shapes,
        - * lerp color from red to blue.
        + * @name 선형 보간(lerp) 색상
        + * @description 무작위의 도형을 반복하고,
        + * 빨강색과 파란색을 선형적으로 보간합니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/08_Math/00_incrementdecrement.js b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        index 0b3d64d6e6..2fa2db7120 100644
        --- a/src/data/examples/ko/08_Math/00_incrementdecrement.js
        +++ b/src/data/examples/ko/08_Math/00_incrementdecrement.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Increment Decrement
        - * @description Writing "a++" is equivalent to "a = a + 1".
        - * Writing "a--" is equivalent to "a = a - 1".
        + * @name 증가와 감소
        + * @description "a++"는 "a = a + 1"와 같은 표현입니다.
        + * "a--"는 "a = a - 1"과 같은 표현입니다.
          */
         let a;
         let b;
        diff --git a/src/data/examples/ko/08_Math/01_operatorprecedence.js b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        index 175054f692..16ce85b29b 100644
        --- a/src/data/examples/ko/08_Math/01_operatorprecedence.js
        +++ b/src/data/examples/ko/08_Math/01_operatorprecedence.js
        @@ -1,24 +1,21 @@
         /*
        - * @name Operator Precedence
        - * @description If you don't explicitly state the order in which an
        - * expression is evaluated, they are evaluated based on the operator
        - * precedence. For example, in the statement "4+2*8", the 2 will
        - * first be multiplied by 8 and then the result will be added to 4.
        - * This is because the "*" has a higher precedence than the "+". To avoid
        - * ambiguity in reading the program, it is recommended that is statement
        - * is written as "4+(2*8)". The order of evaluation can be controlled
        - * through placement of parenthesis in the code. A table of operator
        - * precedence follows below.
        + * @name 연산자 우선 순위
        + * @description 연산자의 실행 순서를 명시하는 경우를 제하고, 모든 선언문은 연산자 우선 순위에 따라
        + * 처리됩니다. 예를 들어, "4+2*8"에서 2는 가장 먼저 8에 곱해지고, 그 결과값이 4에 더해집니다.
        + * 이는 "*"이 "+"보다 높은 우선 순위를 갖기 때문입니다.
        + * 혼동 방지를 위해 "4+(2*8)"라 쓰는 것이 권장되기도 합니다.
        + * 이처럼, 코드 내에 괄호를 사용하여 처리 순서를 명시할 수 있습니다.
        + * 연산자 우선 순위는 다음과 같습니다.
          */
        -// The highest precedence is at the top of the list and
        -// the lowest is at the bottom.
        -// Multiplicative: * / %
        -// Additive: + -
        -// Relational: < > <= >=
        -// Equality: == !=
        -// Logical AND: &&
        -// Logical OR: ||
        -// Assignment: = += -= *= /= %=
        +// 처리 순위가 높은 연산자는 목록 상단에, 
        +// 가장 낲은 연산자는 목록 하단에 적힙니다.
        +// 곱하기 연산자: * / %
        +// 증감 연산자: + -
        +// 비교 연산자: < > <= >=
        +// 등호 연산자: == !=
        +// 논리 연산자 AND: &&
        +// 논리 연산자 OR: ||
        +// 할당 연산자: = += -= *= /= %=
         function setup() {
           createCanvas(710, 400);
           background(51);
        @@ -27,25 +24,25 @@ function setup() {
         
           stroke(204);
           for (let i = 0; i < width - 20; i += 4) {
        -    // The 30 is added to 70 and then evaluated
        -    // if it is greater than the current value of "i"
        -    // For clarity, write as "if (i > (30 + 70)) {"
        +    // 70이 30을 더한 결과값이
        +    // 현재 "i"값보다 큰 지의 여부를 평가
        +    // 처리 순서를 명확히하고자 "if (i > (30 + 70)) {"로 작성
             if (i > 30 + 70) {
               line(i, 0, i, 50);
             }
           }
         
           stroke(255);
        -  // The 2 is multiplied by the 8 and the result is added to the 4
        -  // For clarity, write as "rect(5 + (2 * 8), 0, 90, 20);"
        +  // 2와 8을 곱한 뒤, 그 결과값에 4를 더함
        +  // 처리 순서를 명확히하고자, "rect(5 + (2 * 8), 0, 90, 20);"로 작성
           rect(4 + 2 * 8, 52, 290, 48);
           rect((4 + 2) * 8, 100, 290, 49);
         
           stroke(153);
        -  for (let i = 0; i < width; i += 2) {
        -    // The relational statements are evaluated
        -    // first, and then the logical AND statements and
        -    // finally the logical OR. For clarity, write as:
        +  for (let i = 0; i < width; i += 2) {<<<<<<< HEAD
        +    // 비교 선언문을 가장 먼저 처리한 뒤,
        +    // 다음으로 논리 연산자 AND, 마지막으로 논리 연산자 OR 순으로 처리.
        +    // 처리 순서를 명확히하고자 다음과 같이 작성:
             // "if(((i > 20) && (i < 50)) || ((i > 100) && (i < width-20))) {"
             if ((i > 20 && i < 50) || (i > 100 && i < width - 20)) {
               line(i, 151, i, height - 1);
        diff --git a/src/data/examples/ko/08_Math/02_distance1d.js b/src/data/examples/ko/08_Math/02_distance1d.js
        index 7005d3a17b..36e93c6904 100644
        --- a/src/data/examples/ko/08_Math/02_distance1d.js
        +++ b/src/data/examples/ko/08_Math/02_distance1d.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Distance 1D
        - * @description Move the mouse left and right to control
        - * the speed and direction of the moving shapes.
        + * @name 1D 거리
        + * @description 마우스를 좌우로 움직여, 화면 속 도형의 움직임 속도와 방향을 조정해보세요.
          */
         let xpos1;
         let xpos2;
        diff --git a/src/data/examples/ko/08_Math/03_distance2d.js b/src/data/examples/ko/08_Math/03_distance2d.js
        index 22bfcc1853..3fa5d7efa0 100644
        --- a/src/data/examples/ko/08_Math/03_distance2d.js
        +++ b/src/data/examples/ko/08_Math/03_distance2d.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Distance 2D
        - * @description Move the mouse across the image to obscure
        - * and reveal the matrix. Measures the distance from the mouse
        - * to each circle and sets the size proportionally.
        + * @name 2D 거리
        + * @description 이미지 위로 마우스를 움직여, 매트릭스를 흐리게 또는 뚜렷하게 만들어보세요.
        + * 각 타원과 마우스 간의 거리에 비례하여 원형의 크기가 조정됩니다.
          */
         let max_distance;
         
        diff --git a/src/data/examples/ko/08_Math/04_sine.js b/src/data/examples/ko/08_Math/04_sine.js
        index 810d8a27be..566b2faa99 100644
        --- a/src/data/examples/ko/08_Math/04_sine.js
        +++ b/src/data/examples/ko/08_Math/04_sine.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Sine
        - * @description Smoothly scaling size with the sin() function.
        + * @name 싸인
        + * @description sin() 함수로 도형의 크기를 부드럽게 조정합니다.
          */
         let diameter;
         let angle = 0;
        diff --git a/src/data/examples/ko/08_Math/05_sincosine.js b/src/data/examples/ko/08_Math/05_sincosine.js
        index 82e9e42cf7..dbb6fd2b42 100644
        --- a/src/data/examples/ko/08_Math/05_sincosine.js
        +++ b/src/data/examples/ko/08_Math/05_sincosine.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Sine Cosine
        - * @description Linear movement with sin() and cos().
        - * Numbers between 0 and PI*2 (TWO_PI which angles roughly 6.28)
        - * are put into these functions and numbers between -1 and 1 are returned.
        - * These values are then scaled to produce larger movements.
        + * @name 싸인 코싸인
        + * @description sin()와 cos() 함수를 이용한 선형적 움직임.
        + * 0과 PI*2 사이의 숫자(TWO_PI의 경우, 약 6.28)를 위의 함수에 넣으면
        + * -1과 1 사이의 값이 반환됩니다.
        + * 이러한 반환값은 더 큰 움직임을 만드는 척도로서 쓰입니다.
          */
         let angle1 = 0;
         let angle2 = 0;
        diff --git a/src/data/examples/ko/08_Math/06_sinewave.js b/src/data/examples/ko/08_Math/06_sinewave.js
        index f52d7b1368..46ca3fe589 100644
        --- a/src/data/examples/ko/08_Math/06_sinewave.js
        +++ b/src/data/examples/ko/08_Math/06_sinewave.js
        @@ -1,16 +1,16 @@
         /*
        - * @name Sine Wave
        - * @description Render a simple sine wave.
        - * Original by Daniel Shiffman.
        + * @name 싸인파
        + * @description 간단한 싸인파를 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman)이 원본 제작.
          */
         
        -let xspacing = 16; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let theta = 0.0; // Start angle at 0
        -let amplitude = 75.0; // Height of wave
        -let period = 500.0; // How many pixels before the wave repeats
        -let dx; // Value for incrementing x
        -let yvalues; // Using an array to store height values for the wave
        +let xspacing = 16; // 각 도형들 간의 가로 거리
        +let w; // 전체 파형의 너비
        +let theta = 0.0; // 시작 각도 0
        +let amplitude = 75.0; // 파형의 높이
        +let period = 500.0; // 파형이 반복되기 전까지 생성되는 픽셀 갯수
        +let dx; // x 증가값
        +let yvalues; // 파형의 최고 높이를 저장하기 위한 배열
         
         function setup() {
           createCanvas(710, 400);
        @@ -26,11 +26,10 @@ function draw() {
         }
         
         function calcWave() {
        -  // Increment theta (try different values for
        -  // 'angular velocity' here)
        +  // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
           theta += 0.02;
         
        -  // For every x value, calculate a y value with sine function
        +  // 매 x값마다 싸인 함수를 이용해 y값을 계산
           let x = theta;
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = sin(x) * amplitude;
        @@ -41,7 +40,7 @@ function calcWave() {
         function renderWave() {
           noStroke();
           fill(255);
        -  // A simple way to draw the wave with an ellipse at each location
        +  // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
           for (let x = 0; x < yvalues.length; x++) {
             ellipse(x * xspacing, height / 2 + yvalues[x], 16, 16);
           }
        diff --git a/src/data/examples/ko/08_Math/07_additivewave.js b/src/data/examples/ko/08_Math/07_additivewave.js
        index ade6a96075..46694c8c10 100644
        --- a/src/data/examples/ko/08_Math/07_additivewave.js
        +++ b/src/data/examples/ko/08_Math/07_additivewave.js
        @@ -1,19 +1,17 @@
         /*
        - * @name Additive Wave
        - * @description Create a more complex wave by adding two waves together.
        - * Original by Daniel Shiffman
        + * @name 파형 추가
        + * @description 두 개의 파형을 합쳐 좀 더 복잡한 파도 모양을 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
          */
        -let xspacing = 8; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let maxwaves = 4; // total # of waves to add together
        +let xspacing = 8; // 각 타원 간 가로 거리
        +let w; // 전체 파형의 너비
        +let maxwaves = 4; // 더해진 파형들의 전체 갯수
         
         let theta = 0.0;
        -let amplitude = new Array(maxwaves); // Height of wave
        -// Value for incrementing X, to be calculated
        -// as a function of period and xspacing
        +let amplitude = new Array(maxwaves); // 파형의 높이
        +// X를 증가하는 값으로, period와 xspacing로 계산됨
         let dx = new Array(maxwaves);
        -// Using an array to store height values
        -// for the wave (not entirely necessary)
        +// 파형의 최고 높이를 저장하기 위한 배열 (반드시 필요한 건 아님)
         let yvalues;
         
         function setup() {
        @@ -24,7 +22,7 @@ function setup() {
         
           for (let i = 0; i < maxwaves; i++) {
             amplitude[i] = random(10, 30);
        -    let period = random(100, 300); // Num pixels before wave repeats
        +    let period = random(100, 300); // 파형이 반복되기 전까지 생성되는 픽셀 갯수
             dx[i] = (TWO_PI / period) * xspacing;
           }
         
        @@ -38,20 +36,19 @@ function draw() {
         }
         
         function calcWave() {
        -  // Increment theta (try different values
        -  // for 'angular velocity' here
        +  // 세타값(theta) 증가 (다른 값을 넣어 각속도를 조정해보세요)
           theta += 0.02;
         
        -  // Set all height values to zero
        +  // 모든 높이값을 0으로 설정
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = 0;
           }
         
        -  // Accumulate wave height values
        +  // 파형 높이값 축적하기
           for (let j = 0; j < maxwaves; j++) {
             let x = theta;
             for (let i = 0; i < yvalues.length; i++) {
        -      // Every other wave is cosine instead of sine
        +      // 매번 모든 파형들은 싸인 대신 코싸인으로 처리
               if (j % 2 == 0) yvalues[i] += sin(x) * amplitude[j];
               else yvalues[i] += cos(x) * amplitude[j];
               x += dx[j];
        @@ -60,7 +57,7 @@ function calcWave() {
         }
         
         function renderWave() {
        -  // A simple way to draw the wave with an ellipse at each location
        +  // 각 위치에 지정된 타원형으로 파형을 그릴 수 있는 간단한 방법
           noStroke();
           fill(255, 50);
           ellipseMode(CENTER);
        diff --git a/src/data/examples/ko/08_Math/08_polartocartesian.js b/src/data/examples/ko/08_Math/08_polartocartesian.js
        index c1be3f305d..16907e4cfd 100644
        --- a/src/data/examples/ko/08_Math/08_polartocartesian.js
        +++ b/src/data/examples/ko/08_Math/08_polartocartesian.js
        @@ -1,12 +1,12 @@
         /*
        - * @name PolarToCartesian
        - * @description Convert a polar coordinate (r,theta)
        - * to cartesian (x,y): x = rcos(theta) y = rsin(theta)
        - * Original by Daniel Shiffman.
        + * @name 극좌표를 직교 좌표로
        + * @description 극좌표(지름 r, 세타 theta)를 직교 좌표(x,y)로 변환
        + * : x = rcos(theta) y = rsin(theta)
        + * 다니엘 쉬프만(Daniel Shiffman)이 원본 제작.
          */
         let r;
         
        -// Angle and angular velocity, accleration
        +// 각도, 각속도, 가속
         let theta;
         let theta_vel;
         let theta_acc;
        @@ -14,7 +14,7 @@ let theta_acc;
         function setup() {
           createCanvas(710, 400);
         
        -  // Initialize all values
        +  // 모든값 초기화
           r = height * 0.45;
           theta = 0;
           theta_vel = 0;
        @@ -24,21 +24,21 @@ function setup() {
         function draw() {
           background(0);
         
        -  // Translate the origin point to the center of the screen
        +  // 원점을 화면 중간 위치에 해당하는 좌표값으로 설정
           translate(width / 2, height / 2);
         
        -  // Convert polar to cartesian
        +  // 극좌표를 직교 좌표로 변환
           let x = r * cos(theta);
           let y = r * sin(theta);
         
        -  // Draw the ellipse at the cartesian coordinate
        +  // 직교 좌표에서 타원 그리기
           ellipseMode(CENTER);
           noStroke();
           fill(200);
           ellipse(x, y, 32, 32);
         
        -  // Apply acceleration and velocity to angle
        -  // (r remains static in this example)
        +  // 가속도와 속도를 각도에 적용하기
        +  // (이 예제에서 r은 고정됩니다.)
           theta_vel += theta_acc;
           theta += theta_vel;
         }
        diff --git a/src/data/examples/ko/08_Math/09_arctangent.js b/src/data/examples/ko/08_Math/09_arctangent.js
        index cc90d4499b..21c053b7fd 100644
        --- a/src/data/examples/ko/08_Math/09_arctangent.js
        +++ b/src/data/examples/ko/08_Math/09_arctangent.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Arctangent
        - * @description Move the mouse to change the direction of the eyes.<br>The atan2() function computes the angle from each eye to the cursor.
        + * @name 아크탄젠트
        + * @description 마우스를 움직여 눈의 방향을 바꿔보세요. <br>atan2()함수는 마우스 커서와 눈의 각도를 계산합니다.
          */
         let e1, e2, e3;
         
        diff --git a/src/data/examples/ko/08_Math/10_Interpolate.js b/src/data/examples/ko/08_Math/10_Interpolate.js
        index 27ec95ef92..eff9e09115 100644
        --- a/src/data/examples/ko/08_Math/10_Interpolate.js
        +++ b/src/data/examples/ko/08_Math/10_Interpolate.js
        @@ -1,11 +1,10 @@
         /*
        - * @name Linear Interpolation
        + * @name 선형 보간법
          * @frame 720, 400
        - * @description Move the mouse across the screen and the symbol will follow.
        - * Between drawing each frame of the animation, the ellipse moves part
        - * of the distance (0.05) from its current position toward the cursor using
        - * the lerp() function.
        - * This is the same as the Easing under input only with lerp() instead..
        + * @description 화면 위로 마우스를 움직이면 타원이 따라옵니다.
        + * 애니메이션의 매 프레임 사이에, 타원은 현재 위치에서 커서를 향해 지정된 거리(0.05)의 일부만큼 움직입니다.
        + * 이는 lerp() 함수를 사용하여 구현된 것입니다.
        + * 이 예제는 인풋>이징(Easing) 예제와 동일한 효과를 만들지만, lerp()만으로 구현한다는 점에서 다릅니다.
          */
         
         let x = 0;
        @@ -19,12 +18,11 @@ function setup() {
         function draw() {
           background(51);
         
        -  // lerp() calculates a number between two numbers at a specific increment.
        -  // The amt parameter is the amount to interpolate between the two values
        -  // where 0.0 equal to the first point, 0.1 is very near the first point, 0.5
        -  // is half-way in between, etc.
        +  // lerp()는 특정 값만큼 증가하는 두 개의 숫자로부터 결과값을 계산합니다.
        +  // amt인수는 이 두 개의 숫자를 선형적으로 결정하는데,
        +  // 0.0은 처음 위치, 0.1은 첫번째 점과 아주 가까운 위치, 0.5는 앞의 두 점의 중간 위치인 식입니다.
         
        -  // Here we are moving 5% of the way to the mouse location each frame
        +  // 매 프레임마다 마우스 위치를 향해 5%의 거리를 움직이도록 합니다.
           x = lerp(x, mouseX, 0.05);
           y = lerp(y, mouseY, 0.05);
         
        diff --git a/src/data/examples/ko/08_Math/11_doubleRandom.js b/src/data/examples/ko/08_Math/11_doubleRandom.js
        index 5abd9f7b01..de03e23121 100644
        --- a/src/data/examples/ko/08_Math/11_doubleRandom.js
        +++ b/src/data/examples/ko/08_Math/11_doubleRandom.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Double Random
        + * @name 이중 랜덤
          * @frame 720,400 (optional)
        - * @description Using two random() calls and the point()
        - * function to create an irregular sawtooth line.
        - * Original by by Ira Greenberg.
        + * @description random() 호출과 point()함수를 이중으로 사용하여 
        + * 불규칙한 톱니 모양의 선을 만듭니다.
        + * 원본 제작: 이라 그린버그(Ira Greenberg)
          */
         let totalPts = 300;
         let steps = totalPts + 1;
        diff --git a/src/data/examples/ko/08_Math/12_random.js b/src/data/examples/ko/08_Math/12_random.js
        index 6475297be5..558f3beebf 100644
        --- a/src/data/examples/ko/08_Math/12_random.js
        +++ b/src/data/examples/ko/08_Math/12_random.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Random
        - * @description Random numbers create the basis of this image.
        - * Each time the program is loaded the result is different.
        + * @name 랜덤
        + * @description 난수(random number)에 근간을 둔 이미지입니다.
        + * 프로그램이 불러오기될 때마다 결과가 달라집니다.
          */
         function setup() {
           createCanvas(710, 400);
        diff --git a/src/data/examples/ko/08_Math/13_noise1D.js b/src/data/examples/ko/08_Math/13_noise1D.js
        index a9704cd9fe..6d9fb9ca69 100644
        --- a/src/data/examples/ko/08_Math/13_noise1D.js
        +++ b/src/data/examples/ko/08_Math/13_noise1D.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Noise1D
        - * @description Using 1D Perlin Noise to assign location.
        + * @name 1D 노이즈
        + * @description 1차원 펄린 노이즈를 사용해 위치를 지정합니다.
          */
         let xoff = 0.0;
         let xincrement = 0.01;
        @@ -12,20 +12,20 @@ function setup() {
         }
         
         function draw() {
        -  // Create an alpha blended background
        +  // 알파값이 섞인 배경 생성
           fill(0, 10);
           rect(0, 0, width, height);
         
        -  //let n = random(0,width);  // Try this line instead of noise
        +  //let n = random(0,width);  // 노이즈 대신 이 줄을 사용할 수 있습니다.
         
        -  // Get a noise value based on xoff and scale
        -  // it according to the window's width
        +  // xoff로 노이즈값을 지정하고
        +  // 화면의 너비에 따라 크기 조정
           let n = noise(xoff) * width;
         
        -  // With each cycle, increment xoff
        +  // 매 사이클마다 xoff만큼 증가
           xoff += xincrement;
         
        -  // Draw the ellipse at the value produced by perlin noise
        +  // 펄린 노이즈가 생성한 값으로 타원 그리기
           fill(200);
           ellipse(n, height / 2, 64, 64);
         }
        diff --git a/src/data/examples/ko/08_Math/14_noisewave.js b/src/data/examples/ko/08_Math/14_noisewave.js
        index df1b1e0a24..ca8d2ad731 100644
        --- a/src/data/examples/ko/08_Math/14_noisewave.js
        +++ b/src/data/examples/ko/08_Math/14_noisewave.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Noise Wave
        - * @description Using Perlin Noise to generate a wave-like pattern.
        - * Original by Daniel Shiffman.
        + * @name 노이즈 파형
        + * @description 펄린 노이즈를 사용하여 파도같은 패턴을 만듭니다.
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
          */
        -let yoff = 0.0; // 2nd dimension of perlin noise
        +let yoff = 0.0; // 펄린 노이즈의 2차원
         
         function setup() {
           createCanvas(710, 400);
        @@ -13,28 +13,28 @@ function draw() {
           background(51);
         
           fill(255);
        -  // We are going to draw a polygon out of the wave points
        +  // 파형의 점들을 이용한 다각형 그리기
           beginShape();
         
        -  let xoff = 0; // Option #1: 2D Noise
        -  // let xoff = yoff; // Option #2: 1D Noise
        +  let xoff = 0; // 옵션 #1: 2D 노이즈
        +  // let xoff = yoff; // 옵션 #2: 1D 노이즈
         
        -  // Iterate over horizontal pixels
        +  // 가로 픽셀들에 반복
           for (let x = 0; x <= width; x += 10) {
        -    // Calculate a y value according to noise, map to
        +    // y값을 노이즈에 따라 계산, 다음에 맵핑(map)하기
         
        -    // Option #1: 2D Noise
        +    // 옵션 #1: 2D 노이즈
             let y = map(noise(xoff, yoff), 0, 1, 200, 300);
         
        -    // Option #2: 1D Noise
        +    // 옵션 #2: 1D 노이즈
             // let y = map(noise(xoff), 0, 1, 200,300);
         
        -    // Set the vertex
        +    // 버텍스 설정하기
             vertex(x, y);
        -    // Increment x dimension for noise
        +    // 노이즈의 x차원 증가하기
             xoff += 0.05;
           }
        -  // increment y dimension for noise
        +  // 노이즈의 y차원 증가하기
           yoff += 0.01;
           vertex(width, height);
           vertex(0, height);
        diff --git a/src/data/examples/ko/08_Math/15_Noise2D.js b/src/data/examples/ko/08_Math/15_Noise2D.js
        index 2aec0d5690..16091565b7 100644
        --- a/src/data/examples/ko/08_Math/15_Noise2D.js
        +++ b/src/data/examples/ko/08_Math/15_Noise2D.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Noise2D
        + * @name 2D 노이즈
          * @frame 710,400 (optional)
        - * @description Create a 2D noise with different parameters.
        + * @description 여러 인수를 사용하여 2D 노이즈를 만들어보세요.
          *
          */
         
        @@ -14,29 +14,29 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Draw the left half of image
        +  // 이미지의 좌측 절반 그리기
           for (let y = 0; y < height - 30; y++) {
             for (let x = 0; x < width / 2; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // noiceDetail, 픽셀 옥타브와 번짐 정도
               noiseDetail(2, 0.2);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  // Draw the right half of image
        +  // 이미지의 우측 절반 그리기
           for (let y = 0; y < height - 30; y++) {
             for (let x = width / 2; x < width; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // noiceDetail, 픽셀 옥타브와 번짐 정도
               noiseDetail(5, 0.5);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  //Show the details of two partitions
        +  //두 화면의 디테일 구성하기
           textSize(18);
           fill(255, 255, 255);
        -  text('Noice2D with 2 octaves and 0.2 falloff', 10, 350);
        -  text('Noice2D with 1 octaves and 0.7 falloff', 330, 350);
        +  text('2옥타브와 0.2 번짐 정도의 2D 노이즈', 10, 350);
        +  text('1옥타브와 0.7 번짐 정도의 2D 노이즈', 330, 350);
         }
        diff --git a/src/data/examples/ko/08_Math/16_Noise3D.js b/src/data/examples/ko/08_Math/16_Noise3D.js
        index 94bd75841d..907a90cfb1 100644
        --- a/src/data/examples/ko/08_Math/16_Noise3D.js
        +++ b/src/data/examples/ko/08_Math/16_Noise3D.js
        @@ -1,42 +1,42 @@
         /*
        - * @name Noise3D
        + * @name 3D 노이즈
          * @frame 710,400 (optional)
        - * @description Using 3D noise to create simple animated texture.
        + * @description 3D 노이즈를 사용하여 간단한 동적 텍스쳐를 만듭니다.
          */
         
         let noiseVal;
        -//Increment x by 0.01
        +//x를 0.01씩 증가
         let x_increment = 0.01;
        -//Increment z by 0.02 every draw() cycle
        +//draw()함수 사이클 마다 z를 0.02씩 증가
         let z_increment = 0.02;
         
         //Offset values
         let z_off, y_off, x_off;
         
         function setup() {
        -  //Create the Canvas
        +  //캔버스 만들기
           createCanvas(640, 360);
        -  //Define frame rate
        +  //프레임 속도 조정
           frameRate(20);
        -  //Initial value of z_off
        +  //z_off의 초기값
           z_off = 0;
         }
         
         function draw() {
           x_off = 0;
           y_off = 0;
        -  //Make the background black
        +  //배경을 검정색으로 설정
           background(0);
        -  //Adjust the noice detail
        +  //노이즈 디테일 조정
           noiseDetail(8, 0.65);
         
        -  //For each x,y calculate noice value
        +  //매 x,y마다 노이즈값 계산
           for (let y = 0; y < height; y++) {
             x_off += x_increment;
             y_off = 0;
         
             for (let x = 0; x < width; x++) {
        -      //Calculate and Draw each pixel
        +      //각 픽셀을 계산하고 그리기
               noiseVal = noise(x_off, y_off, z_off);
               stroke(noiseVal * 255);
               y_off += x_increment;
        diff --git a/src/data/examples/ko/08_Math/17_Randomchords.js b/src/data/examples/ko/08_Math/17_Randomchords.js
        index 709a148655..a5a69dddb4 100644
        --- a/src/data/examples/ko/08_Math/17_Randomchords.js
        +++ b/src/data/examples/ko/08_Math/17_Randomchords.js
        @@ -1,35 +1,35 @@
         /*
        - * @name Random Chords
        - * @description Accumulates random chords of a circle. Each chord in translucent
        - * so they accumulate to give the illusion of a shaded sphere.
        - * Contributed by Aatish Bhatia, inspired by <a href ="http://inconvergent.net/">Anders Hoff</a>
        + * @name 랜덤 선들
        + * @description 원형을 그리는 무작위의 선들을 축적합니다.
        + * 불투명하게 처리된 선들이 축적될수록 마치 명암이 적용된 구처럼 보입니다.
        + * 애티쉬 바티아(Aatish Bhatia) 기여, <a href ="http://inconvergent.net/">앤더스 호프(Anders Hoff)</a>로부터 영감을 받음.
          */
         
         function setup() {
           createCanvas(400, 400);
           background(255, 255, 255);
         
        -  // translucent stroke using alpha value
        +  // 알파값을 활용하여 선의 불투명도 조정
           stroke(0, 0, 0, 15);
         }
         
         function draw() {
        -  // draw two random chords each frame
        +  // 매 프레임마다 두 개의 선을 무작위로 그린다
           randomChord();
           randomChord();
         }
         
         function randomChord() {
        -  // find a random point on a circle
        +  // 원형 위 점 하나를 무작위로 찾는다
           let angle1 = random(0, 2 * PI);
           let xpos1 = 200 + 200 * cos(angle1);
           let ypos1 = 200 + 200 * sin(angle1);
         
        -  // find another random point on the circle
        +  // 원형 위 또다른 점 하나를 무작위로 찾는다
           let angle2 = random(0, 2 * PI);
           let xpos2 = 200 + 200 * cos(angle2);
           let ypos2 = 200 + 200 * sin(angle2);
         
        -  // draw a line between them
        +  // 둘 사이에 선을 긋는다
           line(xpos1, ypos1, xpos2, ypos2);
         }
        diff --git a/src/data/examples/ko/08_Math/18_Map.js b/src/data/examples/ko/08_Math/18_Map.js
        index a7b4d86058..43f81c9bdd 100644
        --- a/src/data/examples/ko/08_Math/18_Map.js
        +++ b/src/data/examples/ko/08_Math/18_Map.js
        @@ -1,10 +1,9 @@
         /*
        - * @name Map
        - * @description Use the map() function to take any number and scale it to a
        - * new number that is more useful for the project that you are working on.
        - * For example, use the numbers from the mouse position to control the size or color of a shape.
        - * In this example, the mouse’s x-coordinate (numbers between 0 and 360) are scaled to new numbers
        - * to define the color and size of a circle.
        + * @name 매핑(map)
        + * @description map()함수 사용하면 그 어떠한 숫자든 여러분의 프로젝트에 더 많은 도움이 될
        + * 숫자로 매핑됩니다.
        + * 예를 들어, 마우스 위치값을 사용하여 도형의 크기와 색상을 조정할 수 있습니다.
        + * 이 예제에서는 마우스의 x 좌표(0과 360사이의 숫자)가 원형의 색상과 크기를 정의하는 새로운 숫자들로 처리됩니다.
          */
         function setup() {
           createCanvas(640, 400);
        @@ -13,9 +12,9 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Scale the mouseX value from 0 to 640 to a range between 0 and 175
        +  // 0부터 640에 이르는 mouseX 값을 0부터 175의 범위로 조정
           let c = map(mouseX, 0, width, 0, 175);
        -  // Scale the mouseX value from 0 to 640 to a range between 40 and 300
        +  // 0부터 640에 이르는 mouseX 값을 40부터 300의 범위로 조정
           let d = map(mouseX, 0, width, 40, 300);
           fill(255, c, 0);
           ellipse(width/2, height/2, d, d);
        diff --git a/src/data/examples/ko/09_Simulate/00_Forces.js b/src/data/examples/ko/09_Simulate/00_Forces.js
        index 653c3992a1..ee8b1df54a 100644
        --- a/src/data/examples/ko/09_Simulate/00_Forces.js
        +++ b/src/data/examples/ko/09_Simulate/00_Forces.js
        @@ -1,14 +1,13 @@
         /*
        - * @name Forces
        - * @description Demonstration of multiple force acting on bodies
        + * @name 힘
        + * @description 바디 객체에 작용하는 여러가지 물리학적 힘
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
        -// Demonstration of multiple force acting on
        -// bodies (Mover class)
        -// Bodies experience gravity continuously
        -// Bodies experience fluid resistance when in "water"
        +// 바디에 적용되는 여러가지 물리학적 힘(Mover 클래스)
        +// 바디는 중력을 끊임없이 경험합니다.
        +// 바디는 물 속에서 유체 저항을 경험합니다.
         
        -// Five moving bodies
        +// 5개의 움직이는 형체
         let movers = [];
         
         // Liquid
        @@ -17,32 +16,32 @@ let liquid;
         function setup() {
           createCanvas(640, 360);
           reset();
        -  // Create liquid object
        +  // liquid(액체) 객체 생성
           liquid = new Liquid(0, height / 2, width, height / 2, 0.1);
         }
         
         function draw() {
           background(127);
         
        -  // Draw water
        +  // 물 그리기
           liquid.display();
         
           for (let i = 0; i < movers.length; i++) {
         
        -    // Is the Mover in the liquid?
        +    // Mover가 액체인가요?
             if (liquid.contains(movers[i])) {
        -      // Calculate drag force
        +      // 항력 계산하기
               let dragForce = liquid.calculateDrag(movers[i]);
        -      // Apply drag force to Mover
        +      // Mover에 항력 적용하기
               movers[i].applyForce(dragForce);
             }
         
        -    // Gravity is scaled by mass here!
        +    // 중력은 여기서 mass(질량)에 따라 결정됩니다!
             let gravity = createVector(0, 0.1 * movers[i].mass);
        -    // Apply gravity
        +    // 중력 적용하기
             movers[i].applyForce(gravity);
         
        -    // Update and display
        +    // 업데이트하고 화면에 보이기(display)
             movers[i].update();
             movers[i].display();
             movers[i].checkEdges();
        @@ -55,7 +54,7 @@ function mousePressed() {
           reset();
         }
         
        -// Restart all the Mover objects randomly
        +// 모든 Mover 오브젝트들을 무작위로 재시작하기
         function reset() {
           for (let i = 0; i < 9; i++) {
             movers[i] = new Mover(random(0.5, 3), 40 + i * 70, 0);
        @@ -70,24 +69,24 @@ let Liquid = function(x, y, w, h, c) {
           this.c = c;
         };
         
        -// Is the Mover in the Liquid?
        +// Mover가 액체인가요?
         Liquid.prototype.contains = function(m) {
           let l = m.position;
           return l.x > this.x && l.x < this.x + this.w &&
                  l.y > this.y && l.y < this.y + this.h;
         };
         
        -// Calculate drag force
        +// 항력 계산하기
         Liquid.prototype.calculateDrag = function(m) {
        -  // Magnitude is coefficient * speed squared
        +  // Magnitue(크기) = 계수 * speed(속도)의 제곱
           let speed = m.velocity.mag();
           let dragMagnitude = this.c * speed * speed;
         
        -  // Direction is inverse of velocity
        +  // 방향은 속도와 반대쪽으로
           let dragForce = m.velocity.copy();
           dragForce.mult(-1);
         
        -  // Scale according to magnitude
        +  // 힘의 크기에 따라 조정하기
           // dragForce.setMag(dragMagnitude);
           dragForce.normalize();
           dragForce.mult(dragMagnitude);
        @@ -107,19 +106,19 @@ function Mover(m, x, y) {
           this.acceleration = createVector(0, 0);
         }
         
        -// Newton's 2nd law: F = M * A
        -// or A = F / M
        +// 뉴턴(Newton)의 두번째 법칙: F = M * A
        +// 또는 A = F / M
         Mover.prototype.applyForce = function(force) {
           let f = p5.Vector.div(force, this.mass);
           this.acceleration.add(f);
         };
         
         Mover.prototype.update = function() {
        -  // Velocity changes according to acceleration
        +  // 가속도에 따라 변하는 속도
           this.velocity.add(this.acceleration);
        -  // position changes by velocity
        +  // 속도에 따라 변하는 위치
           this.position.add(this.velocity);
        -  // We must clear acceleration each frame
        +  // 매 프레임마다 가속도 초기화
           this.acceleration.mult(0);
         };
         
        @@ -130,10 +129,10 @@ Mover.prototype.display = function() {
           ellipse(this.position.x, this.position.y, this.mass * 16, this.mass * 16);
         };
         
        -// Bounce off bottom of window
        +// 바닥면에서 튀어오르기
         Mover.prototype.checkEdges = function() {
           if (this.position.y > (height - this.mass * 8)) {
        -    // A little dampening when hitting the bottom
        +    // 바닥면에 닿을 때 약간의 완충 현상 발생
             this.velocity.y *= -0.9;
             this.position.y = (height - this.mass * 8);
           }
        diff --git a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        index a026e4623c..81ea5dd585 100644
        --- a/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/01_ParticleSystem.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Particle System
        - * @description This is a basic Particle System
        + * @name 파티클 시스템
        + * @description 이 예제는 기초적인 파티클 시스템을 다룹니다.
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         let system;
        @@ -16,7 +16,7 @@ function draw() {
           system.run();
         }
         
        -// A simple Particle class
        +// 간단한 파티클 클래스
         let Particle = function(position) {
           this.acceleration = createVector(0, 0.05);
           this.velocity = createVector(random(-1, 1), random(-1, 0));
        @@ -29,14 +29,14 @@ Particle.prototype.run = function() {
           this.display();
         };
         
        -// Method to update position
        +// 위치 업데이트를 위한 메소드
         Particle.prototype.update = function(){
           this.velocity.add(this.acceleration);
           this.position.add(this.velocity);
           this.lifespan -= 2;
         };
         
        -// Method to display
        +// 화면에 보이기 위한 메소드
         Particle.prototype.display = function() {
           stroke(200, this.lifespan);
           strokeWeight(2);
        @@ -44,7 +44,7 @@ Particle.prototype.display = function() {
           ellipse(this.position.x, this.position.y, 12, 12);
         };
         
        -// Is the particle still useful?
        +// 파티클이 여전히 쓸만한가요?
         Particle.prototype.isDead = function(){
           return this.lifespan < 0;
         };
        diff --git a/src/data/examples/ko/09_Simulate/02_Flocking.js b/src/data/examples/ko/09_Simulate/02_Flocking.js
        index 345a22721d..55fa0b262b 100644
        --- a/src/data/examples/ko/09_Simulate/02_Flocking.js
        +++ b/src/data/examples/ko/09_Simulate/02_Flocking.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Flocking
        - * @description Demonstration of Craig Reynolds' "Flocking" behavior.
        - * See: http://www.red3d.com/cwr/
        - * Rules: Cohesion, Separation, Alignment
        - * (from <a href="http://natureofcode.com">natureofcode.com</a>).
        - *  Drag mouse to add boids into the system.
        + * @name 플로킹
        + * @description 크레이그 레이놀즈(Craig Reynolds)의 "군집(Flocking)" 행위를 묘사합니다.
        + * 참고: http://www.red3d.com/cwr/
        + * 규칙: 응집, 분리, 정렬
        + * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
        + * 마우스를 드래그하여 시스템에 개체(boid)를 더해보세요.
          */
         
         
        @@ -15,7 +15,7 @@ function setup() {
           createP("Drag the mouse to generate new boids.");
         
           flock = new Flock();
        -  // Add an initial set of boids into the system
        +  // 시스템에 초기 개체(boid) 더하기
           for (let i = 0; i < 100; i++) {
             let b = new Boid(width / 2,height / 2);
             flock.addBoid(b);
        @@ -27,26 +27,26 @@ function draw() {
           flock.run();
         }
         
        -// Add a new boid into the System
        +// 시스템에 새로운 개체 더하기
         function mouseDragged() {
           flock.addBoid(new Boid(mouseX, mouseY));
         }
         
         // The Nature of Code
        -// Daniel Shiffman
        +// 다니엘 쉬프만(Daniel Shiffman)
         // http://natureofcode.com
         
        -// Flock object
        -// Does very little, simply manages the array of all the boids
        +// Flock 객체는
        +// 모든 개체(boid)의 배열을 관리하는, 간단한 작업을 수행합니다.
         
         function Flock() {
        -  // An array for all the boids
        -  this.boids = []; // Initialize the array
        +  // 모든 개체의 배열
        +  this.boids = []; // 배열 초기화
         }
         
         Flock.prototype.run = function() {
           for (let i = 0; i < this.boids.length; i++) {
        -    this.boids[i].run(this.boids);  // Passing the entire list of boids to each boid individually
        +    this.boids[i].run(this.boids);  // 전체 보이즈 개체 목록을 각 개체에 보내기
           }
         }
         
        @@ -55,19 +55,19 @@ Flock.prototype.addBoid = function(b) {
         }
         
         // The Nature of Code
        -// Daniel Shiffman
        +// 다니엘 쉬프만(Daniel Shiffman)
         // http://natureofcode.com
         
        -// Boid class
        -// Methods for Separation, Cohesion, Alignment added
        +// Boid(개체) 클래스
        +// 응집(cohesion), 분리(seperation), 정렬(alignment)을 위한 메소드 추가
         
         function Boid(x, y) {
           this.acceleration = createVector(0, 0);
           this.velocity = createVector(random(-1, 1), random(-1, 1));
           this.position = createVector(x, y);
           this.r = 3.0;
        -  this.maxspeed = 3;    // Maximum speed
        -  this.maxforce = 0.05; // Maximum steering force
        +  this.maxspeed = 3;    // 최대 속도
        +  this.maxforce = 0.05; // 최대 조타력
         }
         
         Boid.prototype.run = function(boids) {
        @@ -78,51 +78,51 @@ Boid.prototype.run = function(boids) {
         }
         
         Boid.prototype.applyForce = function(force) {
        -  // We could add mass here if we want A = F / M
        +  // A = F / M 으로 계산하고 싶다면, 여기에 질량을 더하면 됩니다. 
           this.acceleration.add(force);
         }
         
        -// We accumulate a new acceleration each time based on three rules
        +// 3가지 규칙에 따라 매번 새로운 가속도를 만듭니다.
         Boid.prototype.flock = function(boids) {
        -  let sep = this.separate(boids);   // Separation
        -  let ali = this.align(boids);      // Alignment
        -  let coh = this.cohesion(boids);   // Cohesion
        -  // Arbitrarily weight these forces
        +  let sep = this.separate(boids);   // 분리
        +  let ali = this.align(boids);      // 정렬
        +  let coh = this.cohesion(boids);   // 응집
        +  // 세 힘들을 임의로 가중하기
           sep.mult(1.5);
           ali.mult(1.0);
           coh.mult(1.0);
        -  // Add the force vectors to acceleration
        +  // 가속도에 force 벡터 더하기
           this.applyForce(sep);
           this.applyForce(ali);
           this.applyForce(coh);
         }
         
        -// Method to update location
        +// 위치 업데이트를 위한 메소드
         Boid.prototype.update = function() {
        -  // Update velocity
        +  // 속도 업데이트
           this.velocity.add(this.acceleration);
        -  // Limit speed
        +  // 속도 제한
           this.velocity.limit(this.maxspeed);
           this.position.add(this.velocity);
        -  // Reset accelertion to 0 each cycle
        +  // 매 사이클마다 가속도를 0으로 리셋
           this.acceleration.mult(0);
         }
         
        -// A method that calculates and applies a steering force towards a target
        -// STEER = DESIRED MINUS VELOCITY
        +// 특정 목표점을 향한 조타력을 계산하고 적용하는 메소드
        +// STEER(조타력) = DESIRED(목표점) - VELOCITY(속도)
         Boid.prototype.seek = function(target) {
        -  let desired = p5.Vector.sub(target,this.position);  // A vector pointing from the location to the target
        -  // Normalize desired and scale to maximum speed
        +  let desired = p5.Vector.sub(target,this.position);  // 현위치에서 목표점을 가리키는 벡터
        +  // desired를 표준화하고 최대 속도로 조정
           desired.normalize();
           desired.mult(this.maxspeed);
           // Steering = Desired minus Velocity
           let steer = p5.Vector.sub(desired,this.velocity);
        -  steer.limit(this.maxforce);  // Limit to maximum steering force
        +  steer.limit(this.maxforce);  // 최대 조타력으로 제한
           return steer;
         }
         
         Boid.prototype.render = function() {
        -  // Draw a triangle rotated in the direction of velocity
        +  // 속도의 방향에 따라 회전하는 삼각형 그리기
           let theta = this.velocity.heading() + radians(90);
           fill(127);
           stroke(200);
        @@ -145,33 +145,33 @@ Boid.prototype.borders = function() {
           if (this.position.y > height + this.r) this.position.y = -this.r;
         }
         
        -// Separation
        -// Method checks for nearby boids and steers away
        +// 분리 Seperation
        +// 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
         Boid.prototype.separate = function(boids) {
           let desiredseparation = 25.0;
           let steer = createVector(0, 0);
           let count = 0;
        -  // For every boid in the system, check if it's too close
        +  // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
           for (let i = 0; i < boids.length; i++) {
             let d = p5.Vector.dist(this.position,boids[i].position);
        -    // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
        +    // 만약 그 거리가 0보다 크고 임의의 값보다 작다면(0은 개체의 현위치)
             if ((d > 0) && (d < desiredseparation)) {
        -      // Calculate vector pointing away from neighbor
        +      // 인근의 개체로부터 떨어진 지점을 향하는 벡터 계산
               let diff = p5.Vector.sub(this.position, boids[i].position);
               diff.normalize();
        -      diff.div(d);        // Weight by distance
        +      diff.div(d);        // 거리에 따른 가중
               steer.add(diff);
        -      count++;            // Keep track of how many
        +      count++;            // 개체수 카운트
             }
           }
        -  // Average -- divide by how many
        +  // 평균 -- 얼마로 나눌 것인가
           if (count > 0) {
             steer.div(count);
           }
         
        -  // As long as the vector is greater than 0
        +  // 벡터가 0보다 크다면,
           if (steer.mag() > 0) {
        -    // Implement Reynolds: Steering = Desired - Velocity
        +    // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
             steer.normalize();
             steer.mult(this.maxspeed);
             steer.sub(this.velocity);
        @@ -180,8 +180,8 @@ Boid.prototype.separate = function(boids) {
           return steer;
         }
         
        -// Alignment
        -// For every nearby boid in the system, calculate the average velocity
        +// 배열 Alignment
        +// 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
         Boid.prototype.align = function(boids) {
           let neighbordist = 50;
           let sum = createVector(0,0);
        @@ -205,22 +205,22 @@ Boid.prototype.align = function(boids) {
           }
         }
         
        -// Cohesion
        -// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
        +// 응집 Cohesion
        +// 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
         Boid.prototype.cohesion = function(boids) {
           let neighbordist = 50;
        -  let sum = createVector(0, 0);   // Start with empty vector to accumulate all locations
        +  let sum = createVector(0, 0);   // 빈 벡터값으로 시작하여 모든 위치들을 축적
           let count = 0;
           for (let i = 0; i < boids.length; i++) {
             let d = p5.Vector.dist(this.position,boids[i].position);
             if ((d > 0) && (d < neighbordist)) {
        -      sum.add(boids[i].position); // Add location
        +      sum.add(boids[i].position); // 위치 추가
               count++;
             }
           }
           if (count > 0) {
             sum.div(count);
        -    return this.seek(sum);  // Steer towards the location
        +    return this.seek(sum);  // 해당 위치를 향해 조타
           } else {
             return createVector(0, 0);
           }
        diff --git a/src/data/examples/ko/09_Simulate/03_WolframCA.js b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        index 06b9bc5765..6472f7d97f 100644
        --- a/src/data/examples/ko/09_Simulate/03_WolframCA.js
        +++ b/src/data/examples/ko/09_Simulate/03_WolframCA.js
        @@ -1,17 +1,17 @@
         /*
        - * @name Wolfram CA
        - * @description Simple demonstration of a Wolfram 1-dimensional cellular automata
        + * @name 울프램 셀룰러 오토마타
        + * @description 1차원 셀룰러 오토마타(cellular automata) 간단하게 구현하기.
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         
         let w = 10;
        -// An array of 0s and 1s
        +// 0과 1들의 배열
         let cells;
         
        - // We arbitrarily start with just the middle cell having a state of "1"
        + // "1"의 상태를 갖는 중간 셀과 함께 시작합니다.
         let generation = 0;
         
        -// An array to store the ruleset, for example {0,1,1,0,1,1,0,1}
        +// {0,1,1,0,1,1,0,1}과 같은 규칙 묶음(ruleset)을 저장하는 배열
         let ruleset = [0, 1, 0, 1, 1, 0, 1, 0];
         
         function setup() {
        @@ -39,26 +39,26 @@ function draw() {
           }
         }
         
        -// The process of creating the new generation
        +// 새로운 세대(generation) 생성 과정
         function generate() {
        -  // First we create an empty array for the new values
        +  // 먼저, 새로운 값을 위한 빈 배열을 만듭니다.
           let nextgen = Array(cells.length);
        -  // For every spot, determine new state by examing current state, and neighbor states
        -  // Ignore edges that only have one neighor
        +  // 매 셀마다 현재 상태를 확인하여 새로운 상태를 결정하고 이 둘을 이웃하게 만듭니다.
        +  // 모서리에 위치하여 한 개의 이웃만을 가진 상태는 무시합니다.
           for (let i = 1; i < cells.length-1; i++) {
        -    let left   = cells[i-1];   // Left neighbor state
        -    let me     = cells[i];     // Current state
        -    let right  = cells[i+1];   // Right neighbor state
        -    nextgen[i] = rules(left, me, right); // Compute next generation state based on ruleset
        +    let left   = cells[i-1];   // 좌측 이웃 상태
        +    let me     = cells[i];     // 현재 상태
        +    let right  = cells[i+1];   // 우측 이웃 상태
        +    nextgen[i] = rules(left, me, right); // 다음 세대 상태를 규칙 묶음(ruleset)에 의거하여 계산
           }
        -  // The current generation is the new generation
        +  // 현재 상태가 새로운 세대가 됩니다.
           cells = nextgen;
           generation++;
         }
         
         
        -// Implementing the Wolfram rules
        -// Could be improved and made more concise, but here we can explicitly see what is going on for each case
        +// 울프램 규칙 구현하기
        +// 더 향상되거나 간결해질 수도 있지만, 여기서 각 사례별로 어떤 일이 일어나는지 명확히 볼 수 있습니다.
         function rules(a, b, c) {
           if (a == 1 && b == 1 && c == 1) return ruleset[0];
           if (a == 1 && b == 1 && c == 0) return ruleset[1];
        diff --git a/src/data/examples/ko/09_Simulate/04_GameOfLife.js b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        index 81d5be870f..d203b1a791 100644
        --- a/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        +++ b/src/data/examples/ko/09_Simulate/04_GameOfLife.js
        @@ -1,6 +1,7 @@
         /*
        - * @name Game of Life
        - * @description A basic implementation of John Conway's Game of Life CA
        + * @name 라이프 게임
        + * @description 존 콘웨이(John Conway)의 라이프 게임 셀룰러 오토마타
        + * (Game of Life Cellular Automata)의 기초적 구현
          * (<a href="http://natureofcode.com">natureofcode.com</a>)
          */
         
        @@ -13,15 +14,15 @@ let next;
         function setup() {
           createCanvas(720, 400);
           w = 20;
        -  // Calculate columns and rows
        +  // 행렬 계산하기
           columns = floor(width / w);
           rows = floor(height / w);
        -  // Wacky way to make a 2D array is JS
        +  // JS를 사용하여 요상한 2D 배열 만들기
           board = new Array(columns);
           for (let i = 0; i < columns; i++) {
             board[i] = new Array(rows);
           }
        -  // Going to use multiple 2D arrays and swap them
        +  // 복수의 2D 배열을 만들고 바꾸기
           next = new Array(columns);
           for (i = 0; i < columns; i++) {
             next[i] = new Array(rows);
        @@ -43,31 +44,31 @@ function draw() {
         
         }
         
        -// reset board when mouse is pressed
        +// 마우스 버튼 클릭시 보드 리셋하기
         function mousePressed() {
           init();
         }
         
        -// Fill board randomly
        +// 무작위로 보드 채우기
         function init() {
           for (let i = 0; i < columns; i++) {
             for (let j = 0; j < rows; j++) {
        -      // Lining the edges with 0s
        +      // 0으로 모서리 테두리 그리기
               if (i == 0 || j == 0 || i == columns-1 || j == rows-1) board[i][j] = 0;
        -      // Filling the rest randomly
        +      // 나머지는 무작위로 채우기
               else board[i][j] = floor(random(2));
               next[i][j] = 0;
             }
           }
         }
         
        -// The process of creating the new generation
        +// 새로운 세대 생성하는 과정
         function generate() {
         
        -  // Loop through every spot in our 2D array and check spots neighbors
        +  // 2D 배열 상 모든 셀들을 걸쳐 반복하며 각 셀별 이웃 확인하기
           for (let x = 1; x < columns - 1; x++) {
             for (let y = 1; y < rows - 1; y++) {
        -      // Add up all the states in a 3x3 surrounding grid
        +      // 3x3의 주변 그리드에 모든 상태들을 더하여 넣기
               let neighbors = 0;
               for (let i = -1; i <= 1; i++) {
                 for (let j = -1; j <= 1; j++) {
        @@ -75,18 +76,18 @@ function generate() {
                 }
               }
         
        -      // A little trick to subtract the current cell's state since
        -      // we added it in the above loop
        +      // 위의 반복을 통해 모든 셀들의 현재 상태를 계산해 넣었으므로,
        +      // 이 계산을 빼주는 요령
               neighbors -= board[x][y];
        -      // Rules of Life
        -      if      ((board[x][y] == 1) && (neighbors <  2)) next[x][y] = 0;           // Loneliness
        -      else if ((board[x][y] == 1) && (neighbors >  3)) next[x][y] = 0;           // Overpopulation
        -      else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1;           // Reproduction
        -      else                                             next[x][y] = board[x][y]; // Stasis
        +      // 라이프 규칙
        +      if      ((board[x][y] == 1) && (neighbors <  2)) next[x][y] = 0;           // 외로움
        +      else if ((board[x][y] == 1) && (neighbors >  3)) next[x][y] = 0;           // 인구과잉
        +      else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1;           // 재생산
        +      else                                             next[x][y] = board[x][y]; // 균형
             }
           }
         
        -  // Swap!
        +  // 바꾸기!
           let temp = board;
           board = next;
           next = temp;
        diff --git a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        index afd65424c1..90e91091c0 100644
        --- a/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        +++ b/src/data/examples/ko/09_Simulate/05_MultipleParticleSystems.js
        @@ -1,7 +1,8 @@
         /*
        - * @name Multiple Particle Systems
        - * @description Click the mouse to generate a burst of particles at mouse location.<br>Each burst is one instance of a particle system with Particles and CrazyParticles (a subclass of Particle).<br>Note use of Inheritance and Polymorphism here.<br>
        - * Original by Daniel Shiffman.
        + * @name 멀티플 파티클 시스템
        + * @description 마우스를 클릭한 위치에서 파티클이 폭발적으로 생성되도록 만들어보세요. <br> 매 폭발은 Particle 클래스의 하위 클래스인 Particles와 CrazyParticles
        + * 의 한 인스턴스에 해당합니다. <br> 클래스 상속과 다형 사용에 대한 방법을 확인해보세요. <br>
        + * 다니엘 쉬프만(Daniel Shiffman) 원본 제작.
          */
         let systems;
         
        @@ -30,7 +31,7 @@ function mousePressed() {
           systems.push(p);
         }
         
        -// A simple Particle class
        +// 간단한 파티클 클래스
         let Particle = function(position) {
           this.acceleration = createVector(0, 0.05);
           this.velocity = createVector(random(-1, 1), random(-1, 0));
        @@ -43,14 +44,14 @@ Particle.prototype.run = function() {
           this.display();
         };
         
        -// Method to update position
        +// 위치 업데이트를 위한 메소드
         Particle.prototype.update = function(){
           this.velocity.add(this.acceleration);
           this.position.add(this.velocity);
           this.lifespan -= 2;
         };
         
        -// Method to display
        +// 화면에 보이기 위한 메소드
         Particle.prototype.display = function () {
           stroke(200, this.lifespan);
           strokeWeight(2);
        @@ -58,7 +59,8 @@ Particle.prototype.display = function () {
           ellipse(this.position.x, this.position.y, 12, 12);
         };
         
        -// Is the particle still useful?
        +// 파티클이 여전히 쓸만한가요?
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
         Particle.prototype.isDead = function () {
           if (this.lifespan < 0) {
             return true;
        @@ -73,7 +75,7 @@ let ParticleSystem = function (position) {
         };
         
         ParticleSystem.prototype.addParticle = function () {
        -  // Add either a Particle or CrazyParticle to the system
        +  // Particle 또는 CrazyParticle을 시스템에 더하기
           if (int(random(0, 2)) == 0) {
             p = new Particle(this.origin);
           }
        @@ -93,42 +95,40 @@ ParticleSystem.prototype.run = function () {
           }
         };
         
        -// A subclass of Particle
        +// Particle의 하위 클래스
         
         function CrazyParticle(origin) {
        -  // Call the parent constructor, making sure (using Function#call)
        -  // that "this" is set correctly during the call
        +  // 부모 생성자(constructor) 만들기
        +  // 이 때, Function#call을 사용하여 "this"가 올바르게 설정되었는지 확인합니다.
           Particle.call(this, origin);
         
        -  // Initialize our added properties
        +  // 더해진 속성들 초기화하기
           this.theta = 0.0;
         };
         
        -// Create a Crazy.prototype object that inherits from Particle.prototype.
        -// Note: A common error here is to use "new Particle()" to create the
        -// Crazy.prototype. That's incorrect for several reasons, not least
        -// that we don't have anything to give Particle for the "origin"
        -// argument. The correct place to call Particle is above, where we call
        -// it from Crazy.
        -CrazyParticle.prototype = Object.create(Particle.prototype); // See note below
        +// Particle.prototype을 상속하는 Crazy.prototype 오브젝트 만들기
        +// 주의: 여기서 자주 발생하는 실수는, Crazy.prototype을 만들기 위해 새로운 "particle()"함수를 쓰는 것입니다.
        +// 이는 여러가지 이유로 적당하지 않은데, 특히 Particle에 "origin" 인수를 제공할 게 없다는 점에서 그렇습니다.
        +// Particle은 위와 같이 Crazy에서 호출하면 됩니다.
        +CrazyParticle.prototype = Object.create(Particle.prototype); // 아래의 주석을 보세요.
         
        -// Set the "constructor" property to refer to CrazyParticle
        +// "constructor(생성자)" 속성이 CrazyParticle을 참조하게 설정하기
         CrazyParticle.prototype.constructor = CrazyParticle;
         
        -// Notice we don't have the method run() here; it is inherited from Particle
        +// 여기서 우리는 run()메소드를 쓰지 않습니다. Particle로부터 상속되었기 때문입니다.
         
        -// This update() method overrides the parent class update() method
        +// 이 update() 메소드는 부모 클래스의 update() 메소드를 오버라이드합니다.
         CrazyParticle.prototype.update=function() {
           Particle.prototype.update.call(this);
        -  // Increment rotation based on horizontal velocity
        +  // 가로 속도에 따라 회전값 증가하기
           this.theta += (this.velocity.x * this.velocity.mag()) / 10.0;
         }
         
        -// This display() method overrides the parent class display() method
        +// 이 display() 메소드는 부모 클래스의 display() 메소드를 오버라이드합니다.
         CrazyParticle.prototype.display=function() {
        -  // Render the ellipse just like in a regular particle
        +  // 타원형을 일반적인 파티클처럼 렌더링하기
           Particle.prototype.display.call(this);
        -  // Then add a rotating line
        +  // 그 다음, 회전하는 선들 더하기
           push();
           translate(this.position.x, this.position.y);
           rotate(this.theta);
        diff --git a/src/data/examples/ko/09_Simulate/06_Spirograph.js b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        index d1f711ab30..bdbb38b12e 100644
        --- a/src/data/examples/ko/09_Simulate/06_Spirograph.js
        +++ b/src/data/examples/ko/09_Simulate/06_Spirograph.js
        @@ -1,67 +1,67 @@
         
         /*
        - * @name Spirograph
        - * @description This sketch uses simple transformations to create a
        - * Spirograph-like effect with interlocking circles (called sines).
        - * Press the spacebar to switch between tracing and showing the underlying geometry.<br>
        - * Example created by <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>.<br>
        + * @name 스피로그래프
        + * @description 일명 싸인이라 불리는 서로 맞물린 원형들을 이용하여,
        + * 스피로그래프와 같은 효과를 만드는 간단한 변형 예제를 소개합니다.
        + * 스페이스바를 눌러 스피로그래프 화면이나, 이것의 기하 궤도 추적 화면으로 전환해보세요.<br>
        + * 이 예제는 <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>가 제작하였습니다.<br>
          * <a href='http://en.wikipedia.org/wiki/Spirograph'>http://en.wikipedia.org/wiki/Spirograph</a>
          */
        -let NUMSINES = 20; // how many of these things can we do at once?
        -let sines = new Array(NUMSINES); // an array to hold all the current angles
        -let rad; // an initial radius value for the central sine
        -let i; // a counter variable
        +let NUMSINES = 20; // 얼마나 싸인을 많은 동시에 그릴 건가요?
        +let sines = new Array(NUMSINES); // 현재 각도들을 모두 저장하는 배열
        +let rad; // 중심 싸인의 초기 반지름값
        +let i; // 카운터 변수
         
        -// play with these to get a sense of what's going on:
        -let fund = 0.005; // the speed of the central sine
        -let ratio = 1; // what multiplier for speed is each additional sine?
        -let alpha = 50; // how opaque is the tracing system
        +// 아래의 값들을 갖고 놀며 어떤 일이 일어나는 건지 감잡아 보세요!
        +let fund = 0.005; // 중심 싸인의 속도
        +let ratio = 1; // 더해진 각 싸인은 속도에 몇을 곱하나요?
        +let alpha = 50; // 궤도 추적 시스템의 투명도
         
        -let trace = false; // are we tracing?
        +let trace = false; // 추적 중인가요?
         
         function setup() {
           createCanvas(710, 400);
         
        -  rad = height / 4; // compute radius for central circle
        -  background(204); // clear the screen
        +  rad = height / 4; // 중심 원의 반지름 계산
        +  background(204); // 화면 비우기
         
           for (let i = 0; i<sines.length; i++) {
        -    sines[i] = PI; // start EVERYBODY facing NORTH
        +    sines[i] = PI; // 모든 원들이 북쪽을 향해 시작하도록 설정
           }
         }
         
         function draw() {
           if (!trace) {
        -    background(204); // clear screen if showing geometry
        -    stroke(0, 255); // black pen
        -    noFill(); // don't fill
        +    background(204); // 기하 형상이 보일 경우 스크린 비우기
        +    stroke(0, 255); // 검정색 펜
        +    noFill(); // 면채우기 없음
           }
         
        -  // MAIN ACTION
        -  push(); // start a transformation matrix
        -  translate(width / 2, height / 2); // move to middle of screen
        +  // 주요 행위
        +  push(); // 변형 매트릭스 시작하기
        +  translate(width / 2, height / 2); // 화면 중앙으로 이동하기
         
           for (let i = 0; i < sines.length; i++) {
        -    let erad = 0; // radius for small "point" within circle... this is the 'pen' when tracing
        -    // setup for tracing
        +    let erad = 0; // 원형 내 작은 "점"의 반지름. 추적 화면에선 이것이 펜으로 쓰입니다.
        +    // 추적을 위한 설정
             if (trace) {
        -      stroke(0, 0, 255 * (float(i) / sines.length), alpha); // blue
        -      fill(0, 0, 255, alpha / 2); // also, um, blue
        -      erad = 5.0 * (1.0 - float(i) / sines.length); // pen width will be related to which sine
        +      stroke(0, 0, 255 * (float(i) / sines.length), alpha); // 파랑
        +      fill(0, 0, 255, alpha / 2); // 음... 또, 파랑!
        +      erad = 5.0 * (1.0 - float(i) / sines.length); // 펜의 너비가 어떤 싸인과 관계할 지
             }
        -    let radius = rad / (i + 1); // radius for circle itself
        -    rotate(sines[i]); // rotate circle
        -    if (!trace) ellipse(0, 0, radius * 2, radius * 2); // if we're simulating, draw the sine
        -    push(); // go up one level
        -    translate(0, radius); // move to sine edge
        -    if (!trace) ellipse(0, 0, 5, 5); // draw a little circle
        -    if (trace) ellipse(0, 0, erad, erad); // draw with erad if tracing
        -    pop(); // go down one level
        -    translate(0, radius); // move into position for next sine
        -    sines[i] = (sines[i] + (fund + (fund * i * ratio))) % TWO_PI; // update angle based on fundamental
        +    let radius = rad / (i + 1); // 원 그 자체의 반지름
        +    rotate(sines[i]); // 원 회전시키기
        +    if (!trace) ellipse(0, 0, radius * 2, radius * 2); // 우리가 시뮬레이션 중이라면, 싸인을 그리세요.
        +    push(); // 레벨 1 업
        +    translate(0, radius); // 싸인 모서리로 이동하기
        +    if (!trace) ellipse(0, 0, 5, 5); // 작은 원 그리기
        +    if (trace) ellipse(0, 0, erad, erad); // 만약 추적 중이라면 erad로 그리기
        +    pop(); // 레벨 1 다운
        +    translate(0, radius); // 다음 싸인을 위한 위치로 이동하기
        +    sines[i] = (sines[i] + (fund + (fund * i * ratio))) % TWO_PI; // fund에 따라 각도 업데이트하기
           }
         
        -  pop(); // pop down final transformation
        +  pop(); // 마지막 변형에 다다르면 레벨 1 다운
         
         }
         
        diff --git a/src/data/examples/ko/09_Simulate/07_LSystems.js b/src/data/examples/ko/09_Simulate/07_LSystems.js
        index ad4fe98162..6fcd73cc69 100644
        --- a/src/data/examples/ko/09_Simulate/07_LSystems.js
        +++ b/src/data/examples/ko/09_Simulate/07_LSystems.js
        @@ -1,36 +1,35 @@
         /*
        - * @name L-Systems
        - * @description This sketch creates an automated drawing based on a Lindenmayer
        - * or (L-) system. L-systems are often used in procedural graphics to make
        - * natural, geometric, or interesting "fractal-style" patterns.<br>
        - * Example created by <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>.<br>
        + * @name L-시스템
        + * @description 이 스케치는 린덴마이어(Lindenmayer) 또는 (L-) 시스템을 기반으로 한 자동 드로잉을 보여줍니다.
        + * L-시스템은 자연적, 기하학적, 또는 재밌는 "프랙탈형" 패턴을 만드는 제너레이티브 그래픽에 쓰입니다.<br>
        + * 이 예제는 <a href='http://lukedubois.com/' target='_blank'>R. Luke DuBois</a>가 제작하였습니다.<br>
          * <a href='https://en.wikipedia.org/wiki/L-system'>https://en.wikipedia.org/wiki/L-system</a>
          */
        -// TURTLE STUFF:
        -let x, y; // the current position of the turtle
        -let currentangle = 0; // which way the turtle is pointing
        -let step = 20; // how much the turtle moves with each 'F'
        -let angle = 90; // how much the turtle turns with a '-' or '+'
        +// 거북이:
        +let x, y; // 거북이의 현재 위치
        +let currentangle = 0; // 거북이가 가리키는 방향w
        +let step = 20; // 매 'F'마다 거북이가 움직이는 크기
        +let angle = 90; // '-' 또는 '+'에 따라 거북이가 회전하는 크기
         
        -// LINDENMAYER STUFF (L-SYSTEMS)
        -let thestring = 'A'; // "axiom" or start of the string
        -let numloops = 5; // how many iterations to pre-compute
        -let therules = []; // array for rules
        -therules[0] = ['A', '-BF+AFA+FB-']; // first rule
        -therules[1] = ['B', '+AF-BFB-FA+']; // second rule
        +// 린덴마이어 시스템(L-SYSTEMS)
        +let thestring = 'A'; // 공리, 또는 문자열의 시작
        +let numloops = 5; // 전처리할 반복문 개수
        +let therules = []; // 규칙 배열
        +therules[0] = ['A', '-BF+AFA+FB-']; // 첫 번째 규칙
        +therules[1] = ['B', '+AF-BFB-FA+']; // 두 번째 규칙
         
        -let whereinstring = 0; // where in the L-system are we?
        +let whereinstring = 0; // L-시스템 상 현재 위치?
         
         function setup() {
           createCanvas(710, 400);
           background(255);
           stroke(0, 0, 0, 255);
         
        -  // start the x and y position at lower-left corner
        +  // 좌측 하단 코너에서 x와 y 위치 시작
           x = 0;
           y = height-1;
         
        -  // COMPUTE THE L-SYSTEM
        +  // L-시스템 처리하기
           for (let i = 0; i < numloops; i++) {
             thestring = lindenmayer(thestring);
           }
        @@ -38,69 +37,69 @@ function setup() {
         
         function draw() {
         
        -  // draw the current character in the string:
        +  // 현재의 문자를 문자열로 그리기:
           drawIt(thestring[whereinstring]);
         
        -  // increment the point for where we're reading the string.
        -  // wrap around at the end.
        +  // 문자열을 읽는 지점 증가하기
        +  // 마지막에 wrap around
           whereinstring++;
           if (whereinstring > thestring.length-1) whereinstring = 0;
         
         }
         
        -// interpret an L-system
        +// L-시스템 해석하기
         function lindenmayer(s) {
        -  let outputstring = ''; // start a blank output string
        +  let outputstring = ''; // 빈 출력 문자열 시작하기
         
        -  // iterate through 'therules' looking for symbol matches:
        +  // 'therules'를 반복하여 일치하는 기호 찾기:
           for (let i = 0; i < s.length; i++) {
        -    let ismatch = 0; // by default, no match
        +    let ismatch = 0; // 기본값으로, 일치하는 기호 없음
             for (let j = 0; j < therules.length; j++) {
               if (s[i] == therules[j][0])  {
        -        outputstring += therules[j][1]; // write substitution
        -        ismatch = 1; // we have a match, so don't copy over symbol
        -        break; // get outta this for() loop
        +        outputstring += therules[j][1]; // 대체내용 작성
        +        ismatch = 1; // 일치하는 기호가 있으므로 복사하지 않음
        +        break; // for() 반복문 나오기
               }
             }
        -    // if nothing matches, just copy the symbol over.
        +    // 일치하는 기호가 없으면 복사
             if (ismatch == 0) outputstring+= s[i];
           }
         
        -  return outputstring; // send out the modified string
        +  return outputstring; // 수정된 문자열 전송
         }
         
        -// this is a custom function that draws turtle commands
        +// 아래는 거북이를 그리는 사용자 정의 함수입니다.
         function drawIt(k) {
         
        -  if (k=='F') { // draw forward
        -    // polar to cartesian based on step and currentangle:
        +  if (k=='F') { // 앞으로 그리기
        +    // step과 currentangle을 기준으로, 극좌표에서 직교 좌표로 변환하기:
             let x1 = x + step*cos(radians(currentangle));
             let y1 = y + step*sin(radians(currentangle));
        -    line(x, y, x1, y1); // connect the old and the new
        +    line(x, y, x1, y1); // 이전의 것과 새로운 것을 연결
         
        -    // update the turtle's position:
        +    // 거북이의 위치 업데이트:
             x = x1;
             y = y1;
           } else if (k == '+') {
        -    currentangle += angle; // turn left
        +    currentangle += angle; // 왼쪽으로 돌기
           } else if (k == '-') {
        -    currentangle -= angle; // turn right
        +    currentangle -= angle; // 오른쪽으로 돌기
           }
         
        -  // give me some random color values:
        +  // 무작위의 색상값을 주세요:
           let r = random(128, 255);
           let g = random(0, 192);
           let b = random(0, 50);
           let a = random(50, 100);
         
        -  // pick a gaussian (D&D) distribution for the radius:
        +  // 반지름에 대한 가우스 분포(D&D) 선택하기:
           let radius = 0;
           radius += random(0, 15);
           radius += random(0, 15);
           radius += random(0, 15);
           radius = radius / 3;
         
        -  // draw the stuff:
        +  // 그리기:
           fill(r, g, b, a);
           ellipse(x, y, radius, radius);
         }
        \ No newline at end of file
        diff --git a/src/data/examples/ko/09_Simulate/08_Spring.js b/src/data/examples/ko/09_Simulate/08_Spring.js
        index b307142cca..03feae7e50 100644
        --- a/src/data/examples/ko/09_Simulate/08_Spring.js
        +++ b/src/data/examples/ko/09_Simulate/08_Spring.js
        @@ -1,9 +1,10 @@
         /*
        - * @name Spring
        +<<<<<<< HEAD
        + * @name 용수철
          * @frame 710, 400
        - * @description Click, drag, and release the horizontal bar to start the spring.
        + * @description 수평 막대를 클릭하고 드래그한 뒤 놓으면 용수철 효과를 볼 수 있습니다.
          */
        -// Spring drawing constants for top bar
        +// 상단의 막대기를 위한 용수철(spring) 그리기
         let springHeight = 32,
             left,
             right,
        @@ -12,17 +13,17 @@ let springHeight = 32,
             over = false,
             move = false;
         
        -// Spring simulation constants
        -let M = 0.8,  // Mass
        -    K = 0.2,  // Spring constant
        -    D = 0.92, // Damping
        -    R = 150;  // Rest position
        +// 용수철 시뮬레이션 상수들
        +let M = 0.8,  // Mass(질량)
        +    K = 0.2,  // 용수철(spring) 상수
        +    D = 0.92, // Damping(감쇠)
        +    R = 150;  // Rest Position(놓인 위치)
         
        -// Spring simulation variables
        -let ps = R,   // Position
        -    vs = 0.0, // Velocity
        -    as = 0,   // Acceleration
        -    f = 0;    // Force
        +// 용수철 시뮬레이션 변수들
        +let ps = R,   // 위치
        +    vs = 0.0, // 속도
        +    as = 0,   // 가속도
        +    f = 0;    // 힘
         
         function setup() {
           createCanvas(710, 400);
        @@ -39,12 +40,12 @@ function draw() {
         }
         
         function drawSpring() {
        -  // Draw base
        +  // 바탕 그리기
           fill(0.2);
           let baseWidth = 0.5 * ps + -8;
           rect(width / 2 - baseWidth, ps + springHeight, width / 2 + baseWidth, height);
         
        -  // Set color and draw top bar
        +  // 상단 막대기의 색상 설정하고 그리기
           if (over || move) {
             fill(255);
           } else {
        @@ -55,26 +56,26 @@ function drawSpring() {
         }
         
         function updateSpring() {
        -  // Update the spring position
        +  // 용수철(spring) 위치 업데이트
           if ( !move ) {
             f = -K * ( ps - R ); // f=-ky
        -    as = f / M;          // Set the acceleration, f=ma == a=f/m
        -    vs = D * (vs + as);  // Set the velocity
        -    ps = ps + vs;        // Updated position
        +    as = f / M;          // 가속도 설정, f=ma == a=f/m
        +    vs = D * (vs + as);  // 속도 설정
        +    ps = ps + vs;        // 업데이트된 위치
           }
         
           if (abs(vs) < 0.1) {
             vs = 0.0;
           }
         
        -  // Test if mouse if over the top bar
        +  // 마우스가 상단 막대기 위에 있는지 여부 테스트
           if (mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + springHeight) {
             over = true;
           } else {
             over = false;
           }
         
        -  // Set and constrain the position of top bar
        +  // 상단 막대기의 위치 설정 및 제한
           if (move) {
             ps = mouseY - springHeight / 2;
             ps = constrain(ps, minHeight, maxHeight);
        diff --git a/src/data/examples/ko/09_Simulate/09_Springs.js b/src/data/examples/ko/09_Simulate/09_Springs.js
        index 43d6f7e6d6..bca9c5c5c5 100644
        --- a/src/data/examples/ko/09_Simulate/09_Springs.js
        +++ b/src/data/examples/ko/09_Simulate/09_Springs.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Springs
        + * @name 용수철들
          * @frame 710,400
        - * @description Move the mouse over one of the circles and click to re-position.
        - * When you release the mouse, it will snap back into position.
        - * Each circle has a slightly different behavior.
        - * (ported from https://processing.org/examples/springs.html)
        + * @description 마우스로 원형 하나를 클릭해 재배치해보세요.
        + * 마우스 클릭을 놓으면 원위치로 되돌아갑니다.
        + * 각 원형은 조금씩 다른 행동을 보입니다.
        + * (https://processing.org/examples/springs.html에서 옮김)
          */
         let num = 3;
         let springs = [];
        @@ -39,9 +39,9 @@ function mouseReleased() {
           }
         }
         
        -// Spring class
        +// 용수철(Spring) 클래스
         function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
        -  // Screen values
        +  // 화면상 위치값들
           // this.xpos = _x;
           // this.ypos = _y;
         
        @@ -54,20 +54,20 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
           this.over = false;
           this.move = false;
         
        -	// Spring simulation constants
        -  this.mass = _m;       // Mass
        +  // 용수철 시뮬레이션 상수들
        +  this.mass = _m;       // Mass(질량)
           this.k = 0.2;    // Spring constant
           this.k = _k_in;
        -  this.damp = _d;       // Damping
        -  this.rest_posx = _x;  // Rest position X
        -  this.rest_posy = _y;  // Rest position Y
        +  this.damp = _d;       // Damping(감쇠)
        +  this.rest_posx = _x;  // 놓인 위치 X
        +  this.rest_posy = _y;  // 놓인 위치 Y
         
        -  // Spring simulation variables
        -  //float pos = 20.0; // Position
        -  this.velx = 0.0;   // X Velocity
        -  this.vely = 0.0;   // Y Velocity
        -  this.accel = 0;    // Acceleration
        -  this.force = 0;    // Force
        +  // 용수철 시뮬레이션 변수들
        +  //float pos = 20.0; // 위치
        +  this.velx = 0.0;   // X 속도
        +  this.vely = 0.0;   // Y 속도
        +  this.accel = 0;    // 가속도
        +  this.force = 0;    // 힘
         
           this.friends = _others;
           this.id = _id;
        @@ -80,15 +80,16 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	}
         
         	this.force = -this.k * (this.y_pos - this.rest_posy);  // f=-ky
        -	this.accel = this.force / this.mass;                 // Set the acceleration, f=ma == a=f/m
        -	this.vely = this.damp * (this.vely + this.accel);         // Set the velocity
        -	this.y_pos = this.y_pos + this.vely;           // Updated position
        +	this.accel = this.force / this.mass; // 가속도 설정하기, f=ma == a=f/m
        +	this.vely = this.damp * (this.vely + this.accel); // 속도 설정하기
        +	this.y_pos = this.y_pos + this.vely; // 업데이트된 위치
         
         
         	this.force = -this.k * (this.x_pos - this.rest_posx);  // f=-ky
        -	this.accel = this.force / this.mass;                 // Set the acceleration, f=ma == a=f/m
        -	this.velx = this.damp * (this.velx + this.accel);         // Set the velocity
        -	this.x_pos = this.x_pos + this.velx;           // Updated position
        +	this.accel = this.force / this.mass; // 가속도 설정하기, f=ma == a=f/m
        +	this.velx = this.damp * (this.velx + this.accel); // 속도 설정하기
        +	this.x_pos = this.x_pos + this.velx; // 업데이트된 위치
        +
         
         
         	if ((this.overEvent() || this.move) && !(this.otherOver()) ) {
        @@ -98,7 +99,7 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	  }
           }
         
        -  // Test to see if mouse is over this spring
        +  // 마우스가 이 용수철 위에 있는지의 여부 테스트
           this.overEvent = function() {
         	let disX = this.x_pos - mouseX;
         	let disY = this.y_pos - mouseY;
        @@ -110,7 +111,7 @@ function Spring (_x, _y, _s, _d, _m, _k_in, _others, _id) {
         	  }
           }
         
        -  // Make sure no other springs are active
        +  // 다른 용수철이 움직이지 않도록 처리
           this.otherOver = function() {
         	for (let i = 0; i < num; i++) {
         	  if (i != this.id) {
        diff --git a/src/data/examples/ko/09_Simulate/10_SoftBody.js b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        index b227393300..a34f32ec5a 100644
        --- a/src/data/examples/ko/09_Simulate/10_SoftBody.js
        +++ b/src/data/examples/ko/09_Simulate/10_SoftBody.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Soft Body
        - * @description Original example by Ira Greenberg.
        - * <br><br>Softbody dynamics simulation using curveVertex() and curveTightness().
        + * @name 소프트 바디
        + * @description 이라 그린버그(Ira Greenberg) 원본 제작.
        + * <br><br>curveVertex() 와 curveTightness()를 사용한 소프트 바디 역학 시뮬레이션.
          */
        -// center point
        +// 중심점
         let centerX = 0.0, centerY = 0.0;
         
         let radius = 45, rotAngle = -90;
        @@ -11,10 +11,10 @@ let accelX = 0.0, accelY = 0.0;
         let deltaX = 0.0, deltaY = 0.0;
         let springing = 0.0009, damping = 0.98;
         
        -//corner nodes
        +// 모서리의 노드들
         let nodes = 5;
         
        -//zero fill arrays
        +// 빈 배열
         let nodeStartX = [];
         let nodeStartY = [];
         let nodeX = [];
        @@ -22,17 +22,17 @@ let nodeY = [];
         let angle = [];
         let frequency = [];
         
        -// soft-body dynamics
        +// 소프트 바디 역학
         let organicConstant = 1.0;
         
         function setup() {
           createCanvas(710, 400);
         
        -  //center shape in window
        +  // 화면상의 중심 도형
           centerX = width / 2;
           centerY = height / 2;
         
        -  //initialize arrays to 0
        +  // 배열을 0으로 초기화
           for (let i = 0; i < nodes; i++){
             nodeStartX[i] = 0;
             nodeStartY[i] = 0;
        @@ -41,7 +41,7 @@ function setup() {
             angle[i] = 0;
           }
         
        -  // iniitalize frequencies for corner nodes
        +  // 모서리 노드들의 빈도수 초기화
           for (let i = 0; i < nodes; i++){
             frequency[i] = random(5, 12);
           }
        @@ -51,7 +51,7 @@ function setup() {
         }
         
         function draw() {
        -  //fade background
        +  // 배경 사라지게하기
           fill(0, 100);
           rect(0, 0, width, height);
           drawShape();
        @@ -59,14 +59,14 @@ function draw() {
         }
         
         function drawShape() {
        -  //  calculate node  starting locations
        +  // 노드 시작 위치 계산
           for (let i = 0; i < nodes; i++){
             nodeStartX[i] = centerX + cos(radians(rotAngle)) * radius;
             nodeStartY[i] = centerY + sin(radians(rotAngle)) * radius;
             rotAngle += 360.0 / nodes;
           }
         
        -  // draw polygon
        +  // 다각형 그리기
           curveTightness(organicConstant);
           fill(255);
           beginShape();
        @@ -80,28 +80,28 @@ function drawShape() {
         }
         
         function moveShape() {
        -  //move center point
        +  // 중심점 옮기기
           deltaX = mouseX - centerX;
           deltaY = mouseY - centerY;
         
        -  // create springing effect
        +  // 스프링같은 효과 만들기
           deltaX *= springing;
           deltaY *= springing;
           accelX += deltaX;
           accelY += deltaY;
         
        -  // move predator's center
        +  // 프레데터(predator)의 중심 옮기기
           centerX += accelX;
           centerY += accelY;
         
        -  // slow down springing
        +  // 스프링같은 효과 감쇠하기
           accelX *= damping;
           accelY *= damping;
         
        -  // change curve tightness
        +  // 커브의 탄성 바꾸기
           organicConstant = 1 - ((abs(accelX) + abs(accelY)) * 0.1);
         
        -  //move nodes
        +  // 노드 옮기기
           for (let i = 0; i < nodes; i++){
             nodeX[i] = nodeStartX[i] + sin(radians(angle[i])) * (accelX * 2);
             nodeY[i] = nodeStartY[i] + sin(radians(angle[i])) * (accelY * 2);
        diff --git a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        index ddb21859d3..8f11abfee3 100644
        --- a/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/11_SmokeParticleSystem.js
        @@ -1,13 +1,15 @@
         /*
        - * @name SmokeParticles
        - * @description a port of Dan Shiffman's SmokeParticleSystem example originally
        - * for Processing. Creates smokey particles :p
        +<<<<<<< HEAD
        + * @name 연기 파티클
        + * @description 다니엘 쉬프만(Dan Shiffman)이 프로세싱(Processing)을 위해 제작한
        + * 연기 파티클 시스템(SmokeParticleSystem) 예제를 옮겨왔습니다.
        + * 마치 연기와 같은 파티클을 만들어볼까요 :p
          */
         
        -// texture for the particle
        +// 파티클 텍스쳐
         let particle_texture = null;
         
        -// variable holding our particle system
        +// 파티클 시스템을 담는 변수
         let ps = null;
         
         function preload() {
        @@ -16,10 +18,10 @@ function preload() {
         
         function setup() {
         
        -  //set the canvas size
        +  // 캔버스 사이즈 설정
           createCanvas(640, 360);
         
        -  //initialize our particle system
        +  // 파티클 시스템 초기화
           ps = new ParticleSystem(0, createVector(width / 2, height - 60), particle_texture);
         }
         
        @@ -35,12 +37,12 @@ function draw() {
             ps.addParticle();
           }
         
        -  // Draw an arrow representing the wind force
        +  // 바람의 힘을 뜻하는 화살표 그리기
           drawVector(wind, createVector(width / 2, 50, 0), 500);
         }
         
         /**
        - *  This function draws an arrow showing the direction our "wind" is blowing.
        + *  이 함수는 "wind(바람)"이 부는 방향을 나타낸 화살표를 그립니다.
          */
         function drawVector(v, loc, scale){
           push();
        @@ -55,19 +57,19 @@ function drawVector(v, loc, scale){
           line(len, 0, len-arrowsize, -arrowsize / 2);
           pop();
         }
        -//========= PARTICLE SYSTEM ===========
        +//========= 파티클 시스템 ===========
         
         /**
        - * A basic particle system class
        - * @param num the number of particles
        - * @param v the origin of the particle system
        - * @param img_ a texture for each particle in the system
        - * @constructor
        + * 기본적인 파티클 시스템 클래스
        + * @param num 파티클 개수를 나타내는 매개 변수
        + * @param v 파티클 시스템의 원점을 나타내는 매개 변수
        + * @param img_ 시스템 상 각 파티클의 텍스쳐를 나타내는 매개 변수
        + * @constructor 생성자
          */
         let ParticleSystem = function(num, v, img_) {
         
           this.particles = [];
        -  this.origin = v.copy(); // we make sure to copy the vector value in case we accidentally mutate the original by accident
        +  this.origin = v.copy(); // 실수로 원래 벡터값(origin)을 바꾼 경우를 대비하여, 벡터값을 복사합니다.
           this.img = img_
           for(let i = 0; i < num; ++i){
             this.particles.push(new Particle(this.origin, this.img));
        @@ -75,23 +77,24 @@ let ParticleSystem = function(num, v, img_) {
         };
         
         /**
        - * This function runs the entire particle system.
        + * 이 함수는 전체 파티클 시스템을 실행합니다.
          */
         ParticleSystem.prototype.run = function() {
         
        -  // cache length of the array we're going to loop into a variable
        -  // You may see <variable>.length in a for loop, from time to time but
        -  // we cache it here because otherwise the length is re-calculated for each iteration of a loop
        +  // 변수들에 반복할, 숨겨진 배열 길이
        +  // for 반복문에 <variable> .length가 표시 될 수 있지만, 매 반복마다 그 길이가
        +  // 다시 계산되기 때문에 여기에 숨깁니다.
           let len = this.particles.length;
         
        -  //loop through and run particles
        +  //파티클 반복 및 실행
           for (let i = len - 1; i >= 0; i--) {
             let particle = this.particles[i];
             particle.run();
         
        -    // if the particle is dead, we remove it.
        -    // javascript arrays don't have a "remove" function but "splice" works just as well.
        -    // we feed it an index to start at, then how many numbers from that point to remove.
        +    // 파티클이 죽을 경우, 제거(remove)합니다.
        +    // 자바스크립트의 배열에는 "remove" 기능이 없지만,
        +    // 대신 동일한 기능을 수행하는 "splice"를 사용할 수 있습니다.
        +    // 제거를 시작할 지점에 인덱스를 넣고, 해당 지점부터 몇 개를 제거할 지 넣을 수 있습니다.
             if (particle.isDead()) {
               this.particles.splice(i, 1);
             }
        @@ -99,8 +102,8 @@ ParticleSystem.prototype.run = function() {
         }
         
         /**
        - * Method to add a force vector to all particles currently in the system
        - * @param dir a p5.Vector describing the direction of the force.
        + * 현재 시스템의 존재하는 모든 파티클에 힘 벡터를 추가하는 메소드
        + * @param dir 힘의 방향을 묘사하는 p5.Vector 매개 변수
          */
         ParticleSystem.prototype.applyForce = function(dir) {
           let len = this.particles.length;
        @@ -110,16 +113,16 @@ ParticleSystem.prototype.applyForce = function(dir) {
         }
         
         /**
        - * Adds a new particle to the system at the origin of the system and with
        - * the originally set texture.
        + * 본래 지정된 텍스쳐와 동일한 텍스쳐의 파티클을 시스템 원점에 추가
          */
         ParticleSystem.prototype.addParticle = function() {
             this.particles.push(new Particle(this.origin, this.img));
         }
         
        -//========= PARTICLE  ===========
        +
        +//========= 파티클 ===========
         /**
        - *  A simple Particle class, renders the particle as an image
        + * 파티클을 이미지로 렌더링하는 간단한 파티클 클래스
          */
         let Particle = function (pos, img_) {
           this.loc = pos.copy();
        @@ -134,7 +137,7 @@ let Particle = function (pos, img_) {
         }
         
         /**
        - *  Simulataneously updates and displays a particle.
        + *  파티클을 업데이트하는 동시에 보이게 하기
          */
         Particle.prototype.run = function() {
           this.update();
        @@ -142,7 +145,7 @@ Particle.prototype.run = function() {
         }
         
         /**
        - *  A function to display a particle
        + *  파티클을 화면에 보이게하는 메소드
          */
         Particle.prototype.render = function() {
           imageMode(CENTER);
        @@ -151,15 +154,15 @@ Particle.prototype.render = function() {
         }
         
         /**
        - *  A method to apply a force vector to a particle.
        + *  파티클에 힘 벡터를 적용하는 메소드
          */
         Particle.prototype.applyForce = function(f) {
           this.acc.add(f);
         }
         
         /**
        - *  This method checks to see if the particle has reached the end of it's lifespan,
        - *  if it has, return true, otherwise return false.
        + *  파티클의 lifespan(수명)이 끝나가는지 여부를 확인하는 메소드
        + *  만약 끝나간다면 true(참)을, 그렇지 않다면 false(거짓)을 반환
          */
         Particle.prototype.isDead = function () {
           if (this.lifespan <= 0.0) {
        @@ -170,7 +173,7 @@ Particle.prototype.isDead = function () {
         }
         
         /**
        - *  This method updates the position of the particle.
        + *  파티클의 위치를 업데이트하는 메소드
          */
         Particle.prototype.update = function() {
           this.vel.add(this.acc);
        diff --git a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        index 449e5ad27e..3299544550 100755
        --- a/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        +++ b/src/data/examples/ko/09_Simulate/12_BrownianMotion.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Brownian Motion
        - * @description Recording random movement as a continuous line.
        - * Port of original example from the Processing examples page.
        + * @name 브라운 운동
        + * @description 무작위의 움직임을 연속된 선으로서 기록합니다.
        + * 프로세싱(Processing) 홈페이지의 예제 페이지에 있는 원본 예제를 옮겨왔습니다.
          */
         
         let num = 2000;
        @@ -23,21 +23,21 @@ function setup() {
         function draw() {
           background(51);
         
        -  // Shift all elements 1 place to the left
        +  // 모든 요소들을 좌측으로 1자리 이동
           for ( let i = 1; i < num; i++ ) {
             ax[i - 1] = ax[i];
             ay[i - 1] = ay[i];
           }
         
        -  // Put a new value at the end of the array
        +  // 배열의 끝에 새로운 값 넣기
           ax[num - 1] += random(-range, range);
           ay[num - 1] += random(-range, range);
         
        -  // Constrain all points to the screen
        +  // 모든 점들을 화면에 제한
           ax[num - 1] = constrain(ax[num - 1], 0, width);
           ay[num - 1] = constrain(ay[num - 1], 0, height);
         
        -  // Draw a line connecting the points
        +  // 점들을 잇는 선 그리기
           for ( let j = 1; j < num; j++ ) {
             let val = j / num * 204.0 + 51;
             stroke(val);
        diff --git a/src/data/examples/ko/09_Simulate/13_Chain.js b/src/data/examples/ko/09_Simulate/13_Chain.js
        index ba52c54587..48dd33d3fa 100644
        --- a/src/data/examples/ko/09_Simulate/13_Chain.js
        +++ b/src/data/examples/ko/09_Simulate/13_Chain.js
        @@ -1,7 +1,8 @@
         /*
        - * @name Chain
        - * @description One mass is attached to the mouse position and the other is attached the position of the other mass. The gravity in the environment pulls down on both.
        - * Ported from the Processing Examples page.
        + * @name 사슬
        + * @description 한 도형은 마우스 커서 위치에, 다른 하나는 이 도형의 위치에 붙어 따라옵니다.
        + * 화면에는 중력이 작용하여 두 도형을 아래 방향으로 끌어당깁니다.
        + * 프로세싱(Processing) 홈페이지의 예제 페이지에서 옮겨왔습니다.
          */
         let s1, s2;
         let gravity = 9.0;
        @@ -10,7 +11,7 @@ let mass = 2.0;
         function setup() {
           createCanvas(720, 400);
           fill(255, 126);
        -  // Inputs: x, y, mass, gravity
        +  // 입력: x, y, mass(질량), gravity(중력)
           s1 = new Spring2D(0.0, width / 2, mass, gravity);
           s2 = new Spring2D(0.0, width / 2, mass, gravity);
         }
        @@ -24,9 +25,9 @@ function draw() {
         }
         
         function Spring2D(xpos, ypos, m, g) {
        -  this.x = xpos;// The x- and y-coordinates
        +  this.x = xpos;// x 와 y 좌표
           this.y = ypos;
        -  this.vx = 0; // The x- and y-axis velocities
        +  this.vx = 0; // x축과 y축 속도
           this.vy = 0;
           this.mass = m;
           this.gravity = g;
        diff --git a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        index 0956a80792..ad9e572770 100755
        --- a/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        +++ b/src/data/examples/ko/09_Simulate/14_SnowflakeParticleSystem.js
        @@ -1,11 +1,11 @@
         /*
        - * @name Snowflakes
        - * @description Particle system simulating the motion of falling snowflakes.
        - * Uses an array of objects to hold the snowflake particles.
        - * Contributed by Aatish Bhatia.
        + * @name 눈송이 파티클
        + * @description 이 파티클 시스템은 마치 떨어지는 눈송이같은 모션을 시뮬레이션합니다.
        + * 눈송이 파티클을 담는 객체 배열을 사용합니다.
        + * 애티쉬 바티아(Aatish Bhatia) 기여.
          */
         
        -let snowflakes = []; // array to hold snowflake objects
        +let snowflakes = []; // 눈송이 객체를 담는 배열
         
         function setup() {
           createCanvas(400, 600);
        @@ -15,42 +15,42 @@ function setup() {
         
         function draw() {
           background('brown');
        -  let t = frameCount / 60; // update time
        +  let t = frameCount / 60; // 시간 업데이트
         
        -  // create a random number of snowflakes each frame
        +  // 매 프라임마다 무작위 개수의 눈송이 생성
           for (let i = 0; i < random(5); i++) {
        -    snowflakes.push(new snowflake()); // append snowflake object
        +    snowflakes.push(new snowflake()); // 눈송이 객체 추가
           }
         
        -  // loop through snowflakes with a for..of loop
        +  // for 반복문을 사용하여 눈송이 반복
           for (let flake of snowflakes) {
        -    flake.update(t); // update snowflake position
        -    flake.display(); // draw snowflake
        +    flake.update(t); // 눈송이 위치 업데이트
        +    flake.display(); // 눈송이 그리기
           }
         }
         
        -// snowflake class
        +// snowflake 클래스
         function snowflake() {
        -  // initialize coordinates
        +  // 좌표값 초기화
           this.posX = 0;
           this.posY = random(-50, 0);
           this.initialangle = random(0, 2 * PI);
           this.size = random(2, 5);
         
        -  // radius of snowflake spiral
        -  // chosen so the snowflakes are uniformly spread out in area
        +  // 방사형 눈송이의 반지름
        +  // 눈송이를 화면에 고루 퍼뜨리기 위해 선택
           this.radius = sqrt(random(pow(width / 2, 2)));
         
           this.update = function(time) {
        -    // x position follows a circle
        -    let w = 0.6; // angular speed
        +    // 원형을 따라다니는 x 위치
        +    let w = 0.6; // 각속도
             let angle = w * time + this.initialangle;
             this.posX = width / 2 + this.radius * sin(angle);
         
        -    // different size snowflakes fall at slightly different y speeds
        +    // 크기가 다른 눈송이가 미묘하게 다른 y 속도로 떨어집니다.
             this.posY += pow(this.size, 0.5);
         
        -    // delete snowflake if past end of screen
        +    // 화면 하단을 지나친 눈송이는 삭제
             if (this.posY > height) {
               let index = snowflakes.indexOf(this);
               snowflakes.splice(index, 1);
        diff --git a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        index fd93ffa845..40e17ca292 100644
        --- a/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        +++ b/src/data/examples/ko/09_Simulate/15_penrose_tiles.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Penrose Tiles
        + * @name 펜로즈 타일
          * @frame 710,400
        - * @description This is a port by David Blitz of the "Penrose Tile" example from processing.org/examples
        + * @description 이 예제는 데이비드 블리츠(David Blitz)가 processing.org/examples의 "펜로즈 타일(Penrose Tile)" 예제에서 옮겨왔습니다.
          */
         
         let ds;
        @@ -9,7 +9,7 @@ let ds;
         function setup() {
           createCanvas(710, 400);
           ds = new PenroseLSystem();
        -  //please, play around with the following line
        +  //다음의 줄과 함께 놀아보세요!
           ds.simulate(5);
         }
         
        @@ -21,17 +21,17 @@ function draw() {
         function PenroseLSystem() {
             this.steps = 0;
         
        -   //these are axiom and rules for the penrose rhombus l-system
        -   //a reference would be cool, but I couldn't find a good one
        +   //아래는 펜로즈 마름모 L-시스템의 공리와 규칙들입니다.
        +   //레퍼런스가 있다면 좋겠지만, 좋은 사례를 찾지 못했습니다.
             this.axiom = "[X]++[X]++[X]++[X]++[X]";
             this.ruleW = "YF++ZF----XF[-YF----WF]++";
             this.ruleX = "+YF--ZF[---WF--XF]+";
             this.ruleY = "-WF++XF[+++YF++ZF]-";
             this.ruleZ = "--YF++++WF[+ZF++++XF]--XF";
         
        -    //please play around with the following two lines
        +    //아래의 두 줄과 함께 놀아보세요!
             this.startLength = 460.0;
        -    this.theta = TWO_PI / 10.0; //36 degrees, try TWO_PI / 6.0, ...
        +    this.theta = TWO_PI / 10.0; //36도, TWO_PI / 6.0도을 넣어보세요, ...
             this.reset();
         }
         
        @@ -51,14 +51,14 @@ PenroseLSystem.prototype.getAge = function () {
             return this.generations;
           }
         
        -//apply substitution rules to create new iteration of production string
        +//대체 규칙을 적용하여, 문자열의 새로운 반복 생성
         PenroseLSystem.prototype.iterate = function() {
             let newProduction = "";
         
             for(let i=0; i < this.production.length; ++i) {
               let step = this.production.charAt(i);
        -      //if current character is 'W', replace current character
        -      //by corresponding rule
        +      // 현재 문자가 'W'이면,
        +      // 이 현재 문자를 규칙에 맞게 대체합니다.
               if (step == 'W') {
                 newProduction = newProduction + this.ruleW;
               }
        @@ -72,8 +72,8 @@ PenroseLSystem.prototype.iterate = function() {
                 newProduction = newProduction + this.ruleZ;
               }
               else {
        -        //drop all 'F' characters, don't touch other
        -        //characters (i.e. '+', '-', '[', ']'
        +        // 모든 'F'를 drop 삭제하되, 
        +        // 여타 문자들(예. '+', '-', '[', ']')은 건들지 않는다.
                 if (step != 'F') {
                   newProduction = newProduction + step;
                 }
        @@ -85,7 +85,7 @@ PenroseLSystem.prototype.iterate = function() {
             this.production = newProduction;
         }
         
        -//convert production string to a turtle graphic
        +//문자열을 거북이 그래픽으로 변환
         PenroseLSystem.prototype.render = function () {
             translate(width / 2, height / 2);
         
        @@ -97,7 +97,7 @@ PenroseLSystem.prototype.render = function () {
             for(let i=0; i<this.steps; ++i) {
               let step = this.production.charAt(i);
         
        -      //'W', 'X', 'Y', 'Z' symbols don't actually correspond to a turtle action
        +      //'W', 'X', 'Y', 'Z' 기호들은 거북이 동작에 상응하지 않습니다.
               if( step == 'F') {
                 stroke(255, 60);
                 for(let j=0; j < this.repeats; j++) {
        diff --git a/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        index c86a08e6a1..c0c1ff2057 100644
        --- a/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        +++ b/src/data/examples/ko/09_Simulate/16_Recursive_Tree.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Recursive Tree
        - * @description Renders a simple tree-like structure via recursion.
        - * The branching angle is calculated as a function of the horizontal mouse
        - * location. Move the mouse left and right to change the angle.
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/tree.html">Recursive Tree Example</a> for Processing.
        + * @name 재귀 나무
        + * @description 재귀를 통해 나무와 같은 구조를 간단히 렌더링합니다.
        + * 나뭇가지의 분기 각도는 마우스 수평 위치에 대한 함수로써 계산됩니다.
        + * 마우스를 좌우로 움직혀 각도를 바꿔보세요.
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/tree.html">재귀 나무 예제</a> 에서 옮겨왔습니다.
          */
         let theta;
         
        @@ -15,36 +15,36 @@ function draw() {
           background(0);
           frameRate(30);
           stroke(255);
        -  // Let's pick an angle 0 to 90 degrees based on the mouse position
        +  // 마우스 위치에 따라 0부터 90도 중 각도 한 개를 골라볼까요!
           let a = (mouseX / width) * 90;
        -  // Convert it to radians
        +  // 이를 라디안 값으로 전환합니다.
           theta = radians(a);
        -  // Start the tree from the bottom of the screen
        +  // 화면 하단에서 나무 시작하기
           translate(width/2,height);
        -  // Draw a line 120 pixels
        +  // 120픽셀 길이의 선 그리기
           line(0,0,0,-120);
        -  // Move to the end of that line
        +  // 위의 선의 끝 지점으로 이동하기
           translate(0,-120);
        -  // Start the recursive branching!
        +  // 나뭇가지의 재귀적 분기 시작하기!
           branch(120);
         
         }
         
         function branch(h) {
        -  // Each branch will be 2/3rds the size of the previous one
        +  // 각각의 나뭇가지 크기는 이전 가지의 2/3에 해당합니다.
           h *= 0.66;
         
        -  // All recursive functions must have an exit condition!!!!
        -  // Here, ours is when the length of the branch is 2 pixels or less
        +  // 모든 재귀 함수에는 종료(exit) 조건이 있어야합니다!!!
        +  // 이 예제의 경우, 나뭇 가지의 길이가 2픽셀과 같거나 적을 때 입니다.
           if (h > 2) {
        -    push();    // Save the current state of transformation (i.e. where are we now)
        -    rotate(theta);   // Rotate by theta
        -    line(0, 0, 0, -h);  // Draw the branch
        -    translate(0, -h); // Move to the end of the branch
        -    branch(h);       // Ok, now call myself to draw two new branches!!
        -    pop();     // Whenever we get back here, we "pop" in order to restore the previous matrix state
        +    push();    // 현재의 변형 상태를 저장 (즉, 현재 상태)
        +    rotate(theta);   // theta(세타)값으로 회전하기
        +    line(0, 0, 0, -h);  // 나뭇가지 그리기
        +    translate(0, -h); // 나뭇가지의 끝 지점으로 이동하기
        +    branch(h);       // 자, 이제 자기 자신을 호출하여 2개의 새로운 나뭇가지를 그릴게요!
        +    pop();     // 이 지점에 도달할 때 마다, 이전 매트릭스 상태를 복원하기 위해 "pop(팝)"합니다.
         
        -    // Repeat the same thing, only branch off to the "left" this time!
        +    // 같은 내용을 반복하되, 이번에는 "왼쪽"으로만 가지가 분기하도록 만듭니다!
             push();
             rotate(-theta);
             line(0, 0, 0, -h);
        diff --git a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        index 76b0bdc4b2..6b41ae6ab4 100644
        --- a/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        +++ b/src/data/examples/ko/09_Simulate/17_Mandelbrot.js
        @@ -1,7 +1,7 @@
         /*
        - * @name The Mandelbrot Set
        - * @description Simple rendering of the Mandelbrot set.
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/mandelbrot.html">Mandelbrot Example</a> for Processing.
        + * @name 망델브로 집합
        + * @description 망델브로(Mandelbrot) 집합을 간단히 렌더링합니다.
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)을 위한 <a href="https://processing.org/examples/mandelbrot.html">망델브로 예제</a>에서 옮겨왔습니다.
          */
         
         function setup() {
        @@ -13,41 +13,41 @@ function setup() {
         function draw() {
           background(0);
         
        -  // Establish a range of values on the complex plane
        -  // A different range will allow us to "zoom" in or out on the fractal
        +  // 복잡한 평면 위에서 값의 범위를 설정
        +  // 설정된 범위에 따라 프랙탈을 줌인 또는 줌아웃할 수 있습니다.
         
        -  // It all starts with the width, try higher or lower values
        +  // 모든 것은 너비값에서 시작합니다. 더 크거나 적은 값을 시도해보세요.
           const w = 4;
           const h = (w * height) / width;
         
        -  // Start at negative half the width and height
        +  // 너비와 높이의 음의 절반에서 시작
           const xmin = -w/2;
           const ymin = -h/2;
         
        -  // Make sure we can write to the pixels[] array.
        -  // Only need to do this once since we don't do any other drawing.
        +  // pixels[] 배열에 쓸 수 있는지 확인합니다.
        +  // 다른 드로잉을 하지 않으므로, 이 작업은 한번만 수행합니다.
           loadPixels();
         
        -  // Maximum number of iterations for each point on the complex plane
        +  // 복잡한 평면 위의 각 점마다 반복할 수 있는 최대 횟수
           const maxiterations = 100;
         
        -  // x goes from xmin to xmax
        +  // x는 xmin에서 xmax로 이동
           const xmax = xmin + w;
        -  // y goes from ymin to ymax
        +  // y는 ymin에서 ymax로 이동
           const ymax = ymin + h;
         
        -  // Calculate amount we increment x,y for each pixel
        +  // 각 픽셀마다 x,y를 증가하는 양 계산
           const dx = (xmax - xmin) / (width);
           const dy = (ymax - ymin) / (height);
         
        -  // Start y
        +  // y 시작
           let y = ymin;
           for (let j = 0; j < height; j++) {
        -    // Start x
        +    // x 시작
             let x = xmin;
             for (let i = 0; i < width; i++) {
         
        -      // Now we test, as we iterate z = z^2 + cm does z tend towards infinity?
        +      // 이제, 우리가 z = z^2 + cm 를 반복 할 때 z가 무한대로 향하나요?
               let a = x;
               let b = y;
               let n = 0;
        @@ -57,22 +57,22 @@ function draw() {
                 const twoab = 2.0 * a * b;
                 a = aa - bb + x;
                 b = twoab + y;
        -        // Infinty in our finite world is simple, let's just consider it 16
        +        // 이 유한한 세상에서의 무한대 개념은 간단합니다. 여기서는 그냥 16이라 설정하지요.
                 if (dist(aa, bb, 0, 0) > 16) {
        -          break;  // Bail
        +          break; 
                 }
                 n++;
               }
         
        -      // We color each pixel based on how long it takes to get to infinity
        -      // If we never got there, let's pick the color black
        +      // 무한대에 도달하기까지 걸리는 시간을 기준으로 각 픽셀에 색상을 지정합니다.
        +      // 도달하지 못할 경우, 검정색으로 지정합니다.
               const pix = (i+j*width)*4;
               const norm = map(n, 0, maxiterations, 0, 1);
               let bright = map(sqrt(norm), 0, 1, 0, 255);
               if (n == maxiterations) {
                 bright = 0;
               } else {
        -        // Gosh, we could make fancy colors here if we wanted
        +        // 원한다면 여기서 좀 더 화려한 색상을 만들 수 있습니다.
                 pixels[pix + 0] = bright;
                 pixels[pix + 1] = bright;
                 pixels[pix + 2] = bright;
        diff --git a/src/data/examples/ko/10_Interaction/10_Tickle.js b/src/data/examples/ko/10_Interaction/10_Tickle.js
        index 006ce49caa..1a013d41a9 100644
        --- a/src/data/examples/ko/10_Interaction/10_Tickle.js
        +++ b/src/data/examples/ko/10_Interaction/10_Tickle.js
        @@ -1,14 +1,14 @@
         /*
        - * @name Tickle
        - * @description The word "tickle" jitters when the cursor hovers over.
        - * Sometimes, it can be tickled off the screen.
        + * @name 간질간질
        + * @description 마우스 커서를 갖다대면 "tickle"이라는 단어가 간지럼을 타듯 떨립니다.
        + * 너무 간지럽히면 화면 밖으로 튀어나갈 수도 있습니다 XD
          */
         let message = 'tickle',
           font,
        -  bounds, // holds x, y, w, h of the text's bounding box
        +  bounds, // 텍스트의 바운딩 박스에 대한 x, y, w, h값
           fontsize = 60,
           x,
        -  y; // x and y coordinates of the text
        +  y; // 텍스트의 x 와 y 좌표
         
         function preload() {
           font = loadFont('assets/SourceSansPro-Regular.otf');
        @@ -17,11 +17,11 @@ function preload() {
         function setup() {
           createCanvas(710, 400);
         
        -  // set up the font
        +  // 폰트 설정
           textFont(font);
           textSize(fontsize);
         
        -  // get the width and height of the text so we can center it initially
        +  // 초기화시 중앙 정렬을 하기 위해 텍스트의 너비 및 높이값을 받아옴
           bounds = font.textBounds(message, 0, 0, fontsize);
           x = width / 2 - bounds.w / 2;
           y = height / 2 - bounds.h / 2;
        @@ -30,12 +30,12 @@ function setup() {
         function draw() {
           background(204, 120);
         
        -  // write the text in black and get its bounding box
        +  // 텍스트를 검정색으로 쓰고 그 바운딩 박스를 받아옴
           fill(0);
           text(message, x, y);
           bounds = font.textBounds(message, x, y, fontsize);
         
        -  // check if the mouse is inside the bounding box and tickle if so
        +  // 마우스가 바운딩 박스 안에 있는지를 확인하고, 안에 있다면 간질간질!
           if (
             mouseX >= bounds.x &&
             mouseX <= bounds.x + bounds.w &&
        diff --git a/src/data/examples/ko/10_Interaction/20_Follow1.js b/src/data/examples/ko/10_Interaction/20_Follow1.js
        index df0902cc09..c5b35b3a13 100644
        --- a/src/data/examples/ko/10_Interaction/20_Follow1.js
        +++ b/src/data/examples/ko/10_Interaction/20_Follow1.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Follow 1
        + * @name 따라다니기 1
          * @frame 710,400
        - * @description A line segment is pushed and pulled by the cursor.
        - * Based on code from Keith Peters.
        + * @description 마우스 커서로 선분을 밀고 당깁니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let x = 100,
           y = 100,
        diff --git a/src/data/examples/ko/10_Interaction/21_Follow2.js b/src/data/examples/ko/10_Interaction/21_Follow2.js
        index ebb87cb2ca..276ebaa52b 100644
        --- a/src/data/examples/ko/10_Interaction/21_Follow2.js
        +++ b/src/data/examples/ko/10_Interaction/21_Follow2.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Follow 2
        + * @name 따라다니기 2
          * @frame 710,400
        - * @description A two-segmented arm follows the cursor position. The relative
        - * angle between the segments is calculated with atan2() and the position
        - * calculated with sin() and cos(). Based on code from Keith Peters.
        + * @description 팔 형상의 두 선분이 마우스 커서의 위치를 따라다닙니다.
        + * 선분들 사이의 상대 각도는 atan2()로, 그 위치는 sin()과 cos()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let x = [0, 0],
           y = [0, 0],
        diff --git a/src/data/examples/ko/10_Interaction/22_Follow3.js b/src/data/examples/ko/10_Interaction/22_Follow3.js
        index 79878f8f2c..7f585e572b 100644
        --- a/src/data/examples/ko/10_Interaction/22_Follow3.js
        +++ b/src/data/examples/ko/10_Interaction/22_Follow3.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Follow 3
        + * @name 따라다니기 3
          * @frame 710,400
        - * @description A segmented line follows the mouse. The relative angle from
        - * each segment to the next is calculated with atan2() and the position of
        - * the next is calculated with sin() and cos(). Based on code from Keith Peters.
        + * @description 선분이 마우스를 따라다닙니다. 한 선분의 다음 선분에 대한 상대 각도는 atan2()로,
        + * 다음 선분의 위치는 sin()과 cos()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let x = [],
           y = [],
        diff --git a/src/data/examples/ko/10_Interaction/23_snake.js b/src/data/examples/ko/10_Interaction/23_snake.js
        index ac56aa3fd3..10422434f6 100644
        --- a/src/data/examples/ko/10_Interaction/23_snake.js
        +++ b/src/data/examples/ko/10_Interaction/23_snake.js
        @@ -1,17 +1,18 @@
         /*
        - * @name Snake game
        - * @description The famous snake game! Once you click run, click anywhere
        - * inside the black area, and control the snake using i j k and l. Don't let
        - * the snake hit itself or the wall!<br>
        - * Example created by <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta
        + * @name 스네이크 게임
        + * @description 그 유명한 스네이크 게임입니다! 실행(run)을 누르고, 
        + * 검은 화면 위 아무 지점을 클릭한 뒤, i,j,k,l 키로 뱀을 조종할 수 있습니다.
        + * 뱀이 벽이나 자신의 몸에 닿지 않도록 하세요!<br>
        + * 예제 제작: <a href='https://github.com/prashantgupta24' target='_blank'>프라샨트 굽타(Prashant Gupta)
          */
         
        -// the snake is divided into small segments, which are drawn and edited on each 'draw' call
        +// 뱀의 형상은 작은 조각(segment)들로 구성되는데,
        +// 이는 매 'draw' 호출에서 그려지고 수정됩니다.
         let numSegments = 10;
         let direction = 'right';
         
        -const xStart = 0; //starting x coordinate for snake
        -const yStart = 250; //starting y coordinate for snake
        +const xStart = 0; // 뱀의 시작 x좌표
        +const yStart = 250; // 뱀의 시작 y좌표
         const diff = 10;
         
         let xCor = [];
        @@ -50,15 +51,12 @@ function draw() {
         }
         
         /*
        - The segments are updated based on the direction of the snake.
        - All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0
        - gets the value of segment 1, segment 1 gets the value of segment 2, and so on,
        - and this results in the movement of the snake.
        -
        - The last segment is added based on the direction in which the snake is going,
        - if it's going left or right, the last segment's x coordinate is increased by a
        - predefined value 'diff' than its second to last segment. And if it's going up
        - or down, the segment's y coordinate is affected.
        + 뱀의 방향에 따라, 뱀의 형상을 구성하는 작은 조각(segment)들의 위치가 업데이트됩니다.
        + 0에서 n-1까지의 모든 조각들은 n에 도달할 때까지 그 다음 조각의 위치를 복사합니다.
        + 예를 들어, segment 0은 segment 1의 값을 받고, segment 1은 segment 2의 값을 받습니다. 뱀은 이러한 과정을 통해 움직이는 것입니다.
        + 이 때, 마지막 조각(segment)은 뱀이 가는 방향에 따라 추가됩니다. 
        + 뱀이 좌우로 움직일 때 가장 마지막 조각의 x값은, 마지막에서 두번째 조각의 x값보다 'diff'값만큼 증가합니다.
        + 뱀이 상하로 움직일 때는 가장 마지막 조각의 y값이 증가하는 식입니다.
         */
         function updateSnakeCoordinates() {
           for (let i = 0; i < numSegments - 1; i++) {
        @@ -86,9 +84,8 @@ function updateSnakeCoordinates() {
         }
         
         /*
        - I always check the snake's head position xCor[xCor.length - 1] and
        - yCor[yCor.length - 1] to see if it touches the game's boundaries
        - or if the snake hits itself.
        + 전 항상 뱀의 머리 위치인 xCor[xCor.length - 1]와
        + yCor[yCor.length - 1]를 확인하여 뱀이 화면 경계나 자신의 몸에 닿는지를 본답니다.
         */
         function checkGameStatus() {
           if (
        @@ -105,8 +102,8 @@ function checkGameStatus() {
         }
         
         /*
        - If the snake hits itself, that means the snake head's (x,y) coordinate
        - has to be the same as one of its own segment's (x,y) coordinate.
        + 뱀이 자신의 몸에 닿았다는건 다시말해, 뱀의 머리의 (x,y)좌표가
        + 조각(segment)들 중 한 (x,y)좌표와 일치한다는 것입니다.
         */
         function checkSnakeCollision() {
           const snakeHeadX = xCor[xCor.length - 1];
        @@ -119,9 +116,7 @@ function checkSnakeCollision() {
         }
         
         /*
        - Whenever the snake consumes a fruit, I increment the number of segments,
        - and just insert the tail segment again at the start of the array (basically
        - I add the last segment again at the tail, thereby extending the tail)
        + 뱀이 과일을 먹을 때마다 조각의 수가 증가하고, 배열의 시작에 꼬리 조각이 다시 삽입되도록 설정했습니다.(기본적으로, 마지막 조각을 꼬리 부분에 추가하여 꼬리를 늘리는 식이지요.)
         */
         function checkForFruit() {
           point(xFruit, yFruit);
        @@ -137,9 +132,10 @@ function checkForFruit() {
         
         function updateFruitCoordinates() {
           /*
        -    The complex math logic is because I wanted the point to lie
        -    in between 100 and width-100, and be rounded off to the nearest
        -    number divisible by 10, since I move the snake in multiples of 10.
        +    여기서 복잡한 연산 논리가 추가된 이유는
        +    뱀이 10의 배수 단위로 움직이도록 설정했기 때문입니다.
        +    점을 너비 100과 -100 사이에 있도록 하고,
        +    그 위치값이 가장 가까운 10의 배수 숫자로 반올림되도록 처리하였습니다.
           */
         
           xFruit = floor(random(10, (width - 100) / 10)) * 10;
        diff --git a/src/data/examples/ko/10_Interaction/24_Wavemaker.js b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        index 26d29ee0b2..85d0a0e979 100644
        --- a/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        +++ b/src/data/examples/ko/10_Interaction/24_Wavemaker.js
        @@ -1,11 +1,12 @@
         /*
        - * @name Wavemaker
        - * @description This illustrates how waves (like water waves) emerge
        - * from particles oscillating in place. Move your mouse to direct the wave.
        - * Contributed by Aatish Bhatia, inspired by <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a> by Dave Whyte.
        + * @name 파도 만들기
        + * @description 이 예제는 특정 위치에서 진동하는 파티클로 파도를 만드는 법을 설명합니다.
        + * 마우스를 움직여 파도의 방향을 바꿔보세요.
        + * 애티쉬 바티아(Aatish Bhatia) 기여, 댄 와이트(Dan Whyte) 제작 <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a>
        + * 로부터 영감을 받았습니다.
          */
         
        -let t = 0; // time variable
        +let t = 0; // 시간 변수
         
         function setup() {
           createCanvas(600, 600);
        @@ -14,24 +15,24 @@ function setup() {
         }
         
         function draw() {
        -  background(10, 10); // translucent background (creates trails)
        +  background(10, 10); // 불투명한 배경화면(파티클의 꼬리 만들기)
         
        -  // make a x and y grid of ellipses
        +  // 타원형으로 구성된 x와 y 그리드 만들기
           for (let x = 0; x <= width; x = x + 30) {
             for (let y = 0; y <= height; y = y + 30) {
        -      // starting point of each circle depends on mouse position
        +      // 각 타원의 시작 점은 마우스 위치에 따라 달라집니다.
               const xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true);
               const yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true);
        -      // and also varies based on the particle's location
        +      // 또, 파티클의 위치에 따라 달라집니다.
               const angle = xAngle * (x / width) + yAngle * (y / height);
         
        -      // each particle moves in a circle
        +      // 각 파티클은 동그라미를 그리며 움직입니다.
               const myX = x + 20 * cos(2 * PI * t + angle);
               const myY = y + 20 * sin(2 * PI * t + angle);
         
        -      ellipse(myX, myY, 10); // draw particle
        +      ellipse(myX, myY, 10); // 파티클로 그리기
             }
           }
         
        -  t = t + 0.01; // update time
        +  t = t + 0.01; // 시간 업데이트
         }
        diff --git a/src/data/examples/ko/10_Interaction/25_reach1.js b/src/data/examples/ko/10_Interaction/25_reach1.js
        index 7982061aac..483283d3da 100644
        --- a/src/data/examples/ko/10_Interaction/25_reach1.js
        +++ b/src/data/examples/ko/10_Interaction/25_reach1.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 1
        + * @name 팔닿기 1
          * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let segLength = 80,
           x,
        diff --git a/src/data/examples/ko/10_Interaction/26_reach2.js b/src/data/examples/ko/10_Interaction/26_reach2.js
        index 4d6ea72174..d6b1ae8272 100644
        --- a/src/data/examples/ko/10_Interaction/26_reach2.js
        +++ b/src/data/examples/ko/10_Interaction/26_reach2.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 2
        + * @name 팔닿기 2
          * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 팔 모양이 마우스 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let numSegments = 10,
           x = [],
        @@ -23,8 +23,8 @@ function setup() {
           strokeWeight(20);
           stroke(255, 100);
         
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        +  x[x.length - 1] = width / 2; // 기본 x좌표 설정
        +  y[x.length - 1] = height; // 기본 y좌표 설정
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/10_Interaction/27_reach3.js b/src/data/examples/ko/10_Interaction/27_reach3.js
        index 32739138b3..fdf58bc952 100644
        --- a/src/data/examples/ko/10_Interaction/27_reach3.js
        +++ b/src/data/examples/ko/10_Interaction/27_reach3.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 3
        + * @name 팔닿기 3
          * @frame 710,400
        - * @description The arm follows the position of the ball by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 팔모양이 공의 위치를 따라다닙니다. 팔의 각도는 atan2()로 계산됩니다.
        + * 이 예제는 키스 피터스(Keith Peters)가 제작한 코드를 기반으로 합니다.
          */
         let numSegments = 8,
           x = [],
        @@ -28,8 +28,8 @@ function setup() {
           stroke(255, 100);
           noFill();
         
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        +  x[x.length - 1] = width / 2; // 기본 x좌표 설정
        +  y[x.length - 1] = height; // 기본 y좌표 설정
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/11_Objects/01_Objects.js b/src/data/examples/ko/11_Objects/01_Objects.js
        index 79f10d3295..cffbe8d85c 100644
        --- a/src/data/examples/ko/11_Objects/01_Objects.js
        +++ b/src/data/examples/ko/11_Objects/01_Objects.js
        @@ -1,15 +1,15 @@
         /*
        - * @name Objects
        - * @description Create a Jitter class, instantiate an object,
        - * and move it around the screen. Adapted from Getting Started with
        - * Processing by Casey Reas and Ben Fry.
        + * @name 객체
        + * @description Jitter 클래스를 만들고, 객체를 인스턴스화하여
        + * 화면 안에서 움직여보세요. 캐시 리스(Casey Reas) & 벤 프라이(Ben Fry) 저 Getting Started with
        + * Processing에서 옮김.
          */
         
        -let bug; // Declare object
        +let bug; // 객체 선언하기
         
         function setup() {
           createCanvas(710, 400);
        -  // Create object
        +  // 객체 생성하기
           bug = new Jitter();
         }
         
        @@ -19,7 +19,7 @@ function draw() {
           bug.display();
         }
         
        -// Jitter class
        +// Jitter 클래스
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        index b57e9209e2..8a0a96a3f4 100644
        --- a/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        +++ b/src/data/examples/ko/11_Objects/02_Multiple_Objects.js
        @@ -1,17 +1,17 @@
         /*
        - * @name Multiple Objects
        - * @description Create a Jitter class, instantiate multiple objects,
        - * and move it around the screen.
        + * @name 복수 객체
        + * @description Jitter 클래스를 만들고, 복수의 객체를 인스턴스화하여
        + * 화면 안에서 움직여보세요.
          */
         
        -let bug1; // Declare objects
        +let bug1; // 객체들 선언하기
         let bug2;
         let bug3;
         let bug4;
         
         function setup() {
           createCanvas(710, 400);
        -  // Create object
        +  // 객체 생성하기
           bug1 = new Jitter();
           bug2 = new Jitter();
           bug3 = new Jitter();
        @@ -30,7 +30,7 @@ function draw() {
           bug4.display();
         }
         
        -// Jitter class
        +// Jitter 클래스
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Array.js b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        index ccc5406037..2fac9f60b8 100644
        --- a/src/data/examples/ko/11_Objects/03_Objects_Array.js
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Array.js
        @@ -1,14 +1,14 @@
         /*
        - * @name Array of Objects
        - * @description Create a Jitter class, instantiate an array of objects
        - * and move them around the screen.
        + * @name 객체 배열
        + * @description Jitter 클래스를 만들고, 객체 배열을 인스턴스화하여
        + * 화면 안에서 움직여보세요.
          */
         
        -let bugs = []; // array of Jitter objects
        +let bugs = []; // Jitter 객체들의 배열
         
         function setup() {
           createCanvas(710, 400);
        -  // Create objects
        +  // 객체들 생성하기
           for (let i = 0; i < 50; i++) {
             bugs.push(new Jitter());
           }
        @@ -22,7 +22,7 @@ function draw() {
           }
         }
         
        -// Jitter class
        +// Jitter 클래스
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        index 2796774489..25ffa5e70a 100644
        --- a/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        +++ b/src/data/examples/ko/11_Objects/03_Objects_Optional_Arguments.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Objects 2
        - * @description Ported from example by hbarragan. Move the cursor across the
        - * image to change the speed and positions of the geometry. The class MRect
        + * @name 객체 2
        + * @description hbarragan 제작 예제에서 옮김. 이미지 위로 마우스를 움직여
        + * 기하의 속도와 위치를 바꿔보세요. MRect 클래스가 선들의 군상을 정의합니다.
          * defines a group of lines.
          */
         
        @@ -33,12 +33,12 @@ function draw() {
         
         class MRect {
           constructor(iw, ixp, ih, iyp, id, it) {
        -    this.w = iw; // single bar width
        -    this.xpos = ixp; // rect xposition
        -    this.h = ih; // rect height
        -    this.ypos = iyp; // rect yposition
        -    this.d = id; // single bar distance
        -    this.t = it; // number of bars
        +    this.w = iw; // 막대기 한 개 너비
        +    this.xpos = ixp; // rect의 x위치
        +    this.h = ih; // rect의 높이
        +    this.ypos = iyp; // rect의 y위치
        +    this.d = id; // 막대기 간 거리
        +    this.t = it; // 막대기 개수
           }
         
           move(posX, posY, damping) {
        diff --git a/src/data/examples/ko/11_Objects/04_Inheritance.js b/src/data/examples/ko/11_Objects/04_Inheritance.js
        index 32b6a630e3..12b3737c05 100644
        --- a/src/data/examples/ko/11_Objects/04_Inheritance.js
        +++ b/src/data/examples/ko/11_Objects/04_Inheritance.js
        @@ -1,9 +1,9 @@
        -/* @name Inheritance
        - * @description A class can be defined using another class as a
        - * foundation. In object-oriented programming terminology, one class can
        - * inherit fields and methods from another. An object that inherits from
        - * another is called a subclass, and the object it inherits from is called
        - * a superclass. A subclass extends the superclass.
        +/* @name 상속
        + * @description 다른 클래스에 기초하여 클래스를 정의할 수 있습니다. 
        + * 객체 지향 프로그래밍 언어에서, 한 클래스는 다른 클래스의 필드와 메소드를 상속할 수 있습니다.
        + * 이처럼 다른 객체로부터 상속받는 객체를 하위 클래스라 하고,
        + * 상속하는 객체를 상위 클래스라고 합니다.
        + * 하위 클래스는 상위 클래스를 확장합니다.
          */
         let spots, arm;
         
        diff --git a/src/data/examples/ko/12_Lights/02_Directional.js b/src/data/examples/ko/12_Lights/02_Directional.js
        index 1c806373fc..2e09a2c792 100755
        --- a/src/data/examples/ko/12_Lights/02_Directional.js
        +++ b/src/data/examples/ko/12_Lights/02_Directional.js
        @@ -1,10 +1,11 @@
         /*
        - * @name Directional
        + * @name 디렉셔널 라이트
          * @frame 710,400
        - * @description Move the mouse to change the direction of the light.
        - * Directional light comes from one direction and is stronger when hitting a
        - * surface squarely and weaker if it hits at a a gentle angle. After hitting a
        - * surface, a directional light scatters in all directions.
        + * @description 마우스를 움직여 조명의 방향을 바꿔보세요.
        + * 디렉셔널 라이트는 한 방향에서 비롯되며
        + * 표면에 직각으로 닿을 때 강한 빛을,
        + * 부드러운 각도로 닿았을 때 약한 빛을 보입니다. 
        + * 디렉셔널 라이트는 표면에 닿으면 그 빛이 모든 방향으로 흩어집니다.
          */
         const radius = 200;
         
        diff --git a/src/data/examples/ko/12_Lights/05_Mixture.js b/src/data/examples/ko/12_Lights/05_Mixture.js
        index 6dc5513aa0..d01c872f70 100644
        --- a/src/data/examples/ko/12_Lights/05_Mixture.js
        +++ b/src/data/examples/ko/12_Lights/05_Mixture.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Mixture
        + * @name 혼합 라이트
          * @frame 710,400 (optional)
        - * @description Display a box with three different kinds of lights.
        + * @description 세 개의 다른 조명과 함께 박스를 보여줍니다.
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        @@ -11,13 +11,13 @@ function setup() {
         function draw() {
           background(0);
         
        -  // Orange point light on the right
        +  // 우측에서 비추는 오렌지색 포인트 라이트
           pointLight(150, 100, 0, 500, 0, 200);
         
        -  // Blue directional light from the left
        +  // 좌측에서 비추는 파랑색 디렉셔널 라이트
           directionalLight(0, 102, 255, -1, 0, 0);
         
        -  // Yellow spotlight from the front
        +  // 정면에서 비추는 노랑색 스포트라이트
           pointLight(255, 255, 109, 0, 0, 300);
         
           rotateY(map(mouseX, 0, width, 0, PI));
        diff --git a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        index 1d5ed269c5..028d28ef51 100644
        --- a/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        +++ b/src/data/examples/ko/13_Motion/01_non_orthogonal_reflection.js
        @@ -1,18 +1,18 @@
         /*
        - * @name Non Orthogonal Reflection
        + * @name 비직각 반사
          * @frame 710,400 (optional)
        - * @description This is a port by David Blitz of the "Reflection 1" example from processing.org/examples
        + * @description 이 예제는 processing.org/examples의 "Reflection 1" 예제를 데이비드 블리츠(David Blitz)가 옮긴 것입니다.
          */
         
        -//Position of left hand side of floor
        +// 바닥의 왼쪽 위치
         let base1;
         
        -//Position of right hand side of floor
        +// 바닥의 오른쪽 위치
         let base2;
        -//Length of floor
        +// 바닥의 길이
         //let baseLength;
         
        -// Variables related to moving ball
        +// 움직이는 공에 대한 변수들
         let position;
         let velocity;
         let r = 6;
        @@ -26,49 +26,49 @@ function setup() {
           base2 = createVector(width, height);
           //createGround();
         
        -  //start ellipse at middle top of screen
        +  // 화면 중앙의 상단에서 타원형 시작
           position = createVector(width / 2, 0);
         
        -  //calculate initial random velocity
        +  // 초기 임의 속도 계산
           velocity = p5.Vector.random2D();
           velocity.mult(speed);
         }
         
         function draw() {
        -  //draw background
        +  // 배경 그리기
           fill(0, 12);
           noStroke();
           rect(0, 0, width, height);
         
        -  //draw base
        +  // base(밑바닥) 그리기
           fill(200);
           quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
         
        -  //calculate base top normal
        +  // base(밑바닥) 상단의 normal(표준) 계산하기
           let baseDelta = p5.Vector.sub(base2, base1);
           baseDelta.normalize();
           let normal = createVector(-baseDelta.y, baseDelta.x);
           let intercept = p5.Vector.dot(base1, normal);
         
        -  //draw ellipse
        +  // ellipse(타원) 그리기
           noStroke();
           fill(255);
           ellipse(position.x, position.y, r * 2, r * 2);
         
        -  //move ellipse
        +  // 타원 움직이기
           position.add(velocity);
         
        -  //normalized incidence vector
        +  // 표준화된 투사 벡터
           incidence = p5.Vector.mult(velocity, -1);
           incidence.normalize();
         
        -  // detect and handle collision with base
        +  // 밑바닥과의 충돌 감지하고 조정하기
           if (p5.Vector.dot(normal, position) > intercept) {
        -    //calculate dot product of incident vector and base top
        +    //투사 벡터와 밑바닥 상단의 dot(점) 계산
             let dot = incidence.dot(normal);
         
        -    //calculate reflection vector
        -    //assign reflection vector to direction vector
        +    // 반사 벡터 계산
        +    // 반사 벡터를 방향 벡터에 지정
             velocity.set(
               2 * normal.x * dot - incidence.x,
               2 * normal.y * dot - incidence.y,
        @@ -76,7 +76,7 @@ function draw() {
             );
             velocity.mult(speed);
         
        -    // draw base top normal at collision point
        +      // 충돌 지점에서 밑바닥 상단 표준 그리기
             stroke(255, 128, 0);
             line(
               position.x,
        @@ -87,23 +87,23 @@ function draw() {
           }
           //}
         
        -  // detect boundary collision
        -  // right
        +  // 경계면 충돌 감지
        +  // 우측
           if (position.x > width - r) {
             position.x = width - r;
             velocity.x *= -1;
           }
        -  // left
        +  // 좌측
           if (position.x < r) {
             position.x = r;
             velocity.x *= -1;
           }
        -  // top
        +  // 상단
           if (position.y < r) {
             position.y = r;
             velocity.y *= -1;
         
        -    //randomize base top
        +    // 밑바닥의 상단 임의화하기
             base1.y = random(height - 100, height);
             base2.y = random(height - 100, height);
           }
        diff --git a/src/data/examples/ko/13_Motion/02_Linear_Motion.js b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        index 421f99c104..454e13377a 100644
        --- a/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        +++ b/src/data/examples/ko/13_Motion/02_Linear_Motion.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Linear
        + * @name 선형
          * @frame 720,400
        - * @description Changing a variable to create a moving line.
        - * When the line moves off the edge of the window,
        - * the variable is set to 0, which places the line back at the bottom of the screen.
        + * @description 변수를 바꿔 움직이는 선을 만들어보세요.
        + * 선이 화면 상단 밖으로 나가면 변수는 0이 되어
        + * 선의 위치를 화면의 하단으로 되돌립니다.
          */
         
         let a;
        diff --git a/src/data/examples/ko/13_Motion/03_Bounce.js b/src/data/examples/ko/13_Motion/03_Bounce.js
        index a3354e015f..c1a6b9ae7f 100644
        --- a/src/data/examples/ko/13_Motion/03_Bounce.js
        +++ b/src/data/examples/ko/13_Motion/03_Bounce.js
        @@ -1,24 +1,24 @@
         /*
        - * @name Bounce
        + * @name 바운스
          * @frame 720,400
        - * @description When the shape hits the edge of the window, it reverses its direction.
        + * @description 도형이 화면의 모서리에 닿으면 반대 방향으로 움직입니다.
          */
         
        -let rad = 60; // Width of the shape
        -let xpos, ypos; // Starting position of shape
        +let rad = 60; // 도형의 너비
        +let xpos, ypos; // 도형의 시작점
         
        -let xspeed = 2.8; // Speed of the shape
        -let yspeed = 2.2; // Speed of the shape
        +let xspeed = 2.8; // 도형의 속도
        +let yspeed = 2.2; // 도형의 속도
         
        -let xdirection = 1; // Left or Right
        -let ydirection = 1; // Top to Bottom
        +let xdirection = 1; // 왼쪽 또는 오른쪽
        +let ydirection = 1; // 위 또는 아래
         
         function setup() {
           createCanvas(720, 400);
           noStroke();
           frameRate(30);
           ellipseMode(RADIUS);
        -  // Set the starting position of the shape
        +  // 도형의 시작점 설정
           xpos = width / 2;
           ypos = height / 2;
         }
        @@ -26,12 +26,12 @@ function setup() {
         function draw() {
           background(102);
         
        -  // Update the position of the shape
        +  // 도형의 위치 업데이트
           xpos = xpos + xspeed * xdirection;
           ypos = ypos + yspeed * ydirection;
         
        -  // Test to see if the shape exceeds the boundaries of the screen
        -  // If it does, reverse its direction by multiplying by -1
        +  // 도형이 화면 경계를 넘어가는 지 테스트
        +  // 넘어갈 경우, -1을 곱하여 방향을 반대로 돌린다.
           if (xpos > width - rad || xpos < rad) {
             xdirection *= -1;
           }
        @@ -39,6 +39,6 @@ function draw() {
             ydirection *= -1;
           }
         
        -  // Draw the shape
        +  // 도형 그리기
           ellipse(xpos, ypos, rad, rad);
         }
        diff --git a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        index 9c38b8c6f3..108b83b8ba 100644
        --- a/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        +++ b/src/data/examples/ko/13_Motion/04_Bouncy_Bubbles.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Bouncy Bubbles
        + * @name 버블 바운스
          * @frame 720,400
        - * @description  based on code from Keith Peters. Multiple-object collision..
        + * @description 이 예제는 키스 피터스(Keith Peters)가 제작한 복수-객체 충돌(Multiple-object collision) 예제 코드를 기반으로 합니다.
          */
         
         let numBalls = 13;
        diff --git a/src/data/examples/ko/13_Motion/05_Morph.js b/src/data/examples/ko/13_Motion/05_Morph.js
        index c6479c27d6..6a950d7d97 100644
        --- a/src/data/examples/ko/13_Motion/05_Morph.js
        +++ b/src/data/examples/ko/13_Motion/05_Morph.js
        @@ -1,50 +1,49 @@
         /*
        - * @name Morph
        + * @name 변형(morph)
          * @frame 720,400
        - * @description Changing one shape into another by interpolating vertices from one to another.
        + * @description 버텍스를 보간하여 한 모양에서 다른 모양으로 바꾸기
          */
         
        -// Two ArrayLists to store the vertices for two shapes
        -// This example assumes that each shape will have the same
        -// number of vertices, i.e. the size of each ArrayList will be the same
        +// 두 도형의 버텍스들을 저장하는 두 개의 배열 리스트(ArrayList)
        +// 이 예제는 두 도형이 동일한 개수의 버텍스를 갖고 있다는 것을 전제합니다.
        +// 즉, 배열 리스트가 동일하다는 뜻입니다.
         let circle = [];
         let square = [];
         
        -// An ArrayList for a third set of vertices, the ones we will be drawing
        -// in the window
        +// 3번째 버텍스 묶음 저장을 위한 배열 리스트
        +// 화면상 그려집니다.
         let morph = [];
         
        -// This boolean variable will control if we are morphing to a circle or square
        +// 이 불리언 변수는 원형이나 사각형으로 변형할지 여부를 결정합니다.
         let state = false;
         
         function setup() {
           createCanvas(720, 400);
         
        -  // Create a circle using vectors pointing from center
        +    // 중심을 가리키는 벡터를 사용하여 원 그리기
           for (let angle = 0; angle < 360; angle += 9) {
        -    // Note we are not starting from 0 in order to match the
        -    // path of a circle.
        +    // 주의: 원의 이동 경로와 상응하기 위해, 0에서 시작하지 않습니다.
             let v = p5.Vector.fromAngle(radians(angle - 135));
             v.mult(100);
             circle.push(v);
        -    // Let's fill out morph ArrayList with blank PVectors while we are at it
        +    // morph 배열 리스트를 빈 PVector로 채웁니다.
             morph.push(createVector());
           }
         
        -  // A square is a bunch of vertices along straight lines
        -  // Top of square
        +  // 사각형은 직선을 따라 이어진 여러 개의 버텍스입니다.
        +  // 사각형 상단
           for (let x = -50; x < 50; x += 10) {
             square.push(createVector(x, -50));
           }
        -  // Right side
        +  // 사각형 우측
           for (let y = -50; y < 50; y += 10) {
             square.push(createVector(50, y));
           }
        -  // Bottom
        +  // 사각형 하단
           for (let x = 50; x > -50; x -= 10) {
             square.push(createVector(x, 50));
           }
        -  // Left side
        +  // 사각형 좌측
           for (let y = 50; y > -50; y -= 10) {
             square.push(createVector(-50, y));
           }
        @@ -53,35 +52,35 @@ function setup() {
         function draw() {
           background(51);
         
        -  // We will keep how far the vertices are from their target
        +  // 이 버텍스들이 목표 대상으로부터 얼마나 멀리 있는지 확인
           let totalDistance = 0;
         
        -  // Look at each vertex
        +  // 각 버텍스 확인
           for (let i = 0; i < circle.length; i++) {
             let v1;
        -    // Are we lerping to the circle or square?
        +    // 원형이나 사각형으로 선형 보간합니까?
             if (state) {
               v1 = circle[i];
             } else {
               v1 = square[i];
             }
        -    // Get the vertex we will draw
        +    // 그려질 버텍스 가져오기
             let v2 = morph[i];
        -    // Lerp to the target
        +    // 대상을 향해 선형 보간하기
             v2.lerp(v1, 0.1);
        -    // Check how far we are from target
        +    // 목표 대상으로부터 얼마나 멀리 있는지 확인
             totalDistance += p5.Vector.dist(v1, v2);
           }
         
        -  // If all the vertices are close, switch shape
        +  // 모든 버텍스들이 가까워지면, 모양 전환
           if (totalDistance < 0.1) {
             state = !state;
           }
         
        -  // Draw relative to center
        +  // 중심을 기준으로 그리기
           translate(width / 2, height / 2);
           strokeWeight(4);
        -  // Draw a polygon that makes up all the vertices
        +  // 모든 버텍스를 구성하는 다각형 그리기
           beginShape();
           noFill();
           stroke(255);
        diff --git a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        index 4c347c7e00..0a65c143f6 100644
        --- a/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        +++ b/src/data/examples/ko/13_Motion/06_Moving_On_Curves.js
        @@ -1,21 +1,21 @@
         /*
        - * @name Moving On Curves
        + * @name 곡선 위 움직이기
          * @frame 720,400
        - * @description In this example, the circles moves along the curve y = x^4.
        - * Click the mouse to have it move to a new position.
        + * @description 이 예제에서, 원들은 y = x^4 곡선을 따라 움직입니다.
        + * 마우스를 클릭하여 새로운 위치로 움직이도록 해보세요.
          */
         
        -let beginX = 20.0; // Initial x-coordinate
        -let beginY = 10.0; // Initial y-coordinate
        -let endX = 570.0; // Final x-coordinate
        -let endY = 320.0; // Final y-coordinate
        -let distX; // X-axis distance to move
        -let distY; // Y-axis distance to move
        -let exponent = 4; // Determines the curve
        -let x = 0.0; // Current x-coordinate
        -let y = 0.0; // Current y-coordinate
        -let step = 0.01; // Size of each step along the path
        -let pct = 0.0; // Percentage traveled (0.0 to 1.0)
        +let beginX = 20.0; // 초기 x 좌표
        +let beginY = 10.0; // 초기 y 좌표
        +let endX = 570.0; // 최종 x 좌표
        +let endY = 320.0; // 최종 y 좌표
        +let distX; // 이동할 X축 거리
        +let distY; // 이동할 Y축 거리
        +let exponent = 4; // 곡선 결정
        +let x = 0.0; // 현재 x 좌표
        +let y = 0.0; // 현재 y 좌표
        +let step = 0.01; // 경로를 따른 각 단계별 움직임 크기
        +let pct = 0.0; // 이동 거리 비율 (0.0과 1.0 사이)
         
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        index 0c4bc70751..a1854cb62d 100644
        --- a/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        +++ b/src/data/examples/ko/15_Instance_Mode/01_Instantiating.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Instantiation
        - * @description Create a p5 instance, which keeps all variables
        - * out of the global scope of your page.
        + * @name 인스턴스화
        + * @description p5 인스턴스를 만들어, 해당 페이지의 모든 변수들이
        + * 전역 범위로서 사용되지 않도록 합니다.
          */
         let sketch = function(p) {
           let x = 100;
        @@ -20,7 +20,7 @@ let sketch = function(p) {
         
         let myp5 = new p5(sketch);
         
        -// Compare to "global mode"
        +// "전역 모드(global mode)"와 비교
         // let x = 100;
         // let y = 100;
         
        diff --git a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        index 9675fdeaaf..b5d6647f6e 100644
        --- a/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        +++ b/src/data/examples/ko/15_Instance_Mode/02_Instance_Container.js
        @@ -1,14 +1,12 @@
         /*
          * @norender
        - * @name Instance Container
        - * @description Optionally, you can specify a default container for the canvas
        - * and any other elements to append to with a second argument. You can give the
        - * ID of an element in your html, or an html node itself.
        - *
        - * Here are three different options for selecting a container
        - * DOM element. All DOM elements (canvas, buttons, divs, etc) created by p5
        - * will be attached to the DOM element specified as the second argument to the
        - * p5() call.
        + * @name 인스턴스 컨테이너
        + * @description 캔버스에 기본 컨테이너를 지정하거나,
        + * 두번째 인수로 추가될 수 있는 모든 요소를 지정할 수 있습니다. 
        + * HTML의 요소 id나 HTML 노드 그 자체도 지원됩니다.
        + * 컨테이너 DOM 요소를 지정하는 세 가지 다른 방법이 있습니다.
        + * p5로 만들어진 모든 DOM 요소(캔버스, 버튼, div 등)는
        + * p5()함수 호출시 두 번째 인수로 지정된 DOM 요소에 담기게 됩니다.
          */
         <!-- pass in the ID of the container element -->
         <!DOCTYPE html>
        diff --git a/src/data/examples/ko/16_Dom/03_Input_Button.js b/src/data/examples/ko/16_Dom/03_Input_Button.js
        index 5ec69a29ed..76549e0e51 100644
        --- a/src/data/examples/ko/16_Dom/03_Input_Button.js
        +++ b/src/data/examples/ko/16_Dom/03_Input_Button.js
        @@ -1,14 +1,14 @@
         /*
        - * @name Input and Button
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Input text and click the button to see it affect the the canvas.
        + * @name 입력과 버튼
        + * @description 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 텍스트를 입력하고 버튼을 클릭하면 어떤 효과가 캔버스에 나타나는지 보세요.
          */
         let input, button, greeting;
         
         function setup() {
        -  // create canvas
        +  // 캔버스 생성하기
           createCanvas(710, 400);
         
           input = createInput();
        diff --git a/src/data/examples/ko/16_Dom/04_Slider.js b/src/data/examples/ko/16_Dom/04_Slider.js
        index 0582953c37..551a4687c4 100644
        --- a/src/data/examples/ko/16_Dom/04_Slider.js
        +++ b/src/data/examples/ko/16_Dom/04_Slider.js
        @@ -1,19 +1,19 @@
         /*
        - * @name Slider
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Move the sliders to control the R, G, B values of the background.
        + * @name 슬라이더
        + * @description 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 슬라이더를 움직여 배경색의 R,G,B값을 조정해보세요.
          */
         let rSlider, gSlider, bSlider;
         
         function setup() {
        -  // create canvas
        +  // 캔버스 생성하기
           createCanvas(710, 400);
           textSize(15);
           noStroke();
         
        -  // create sliders
        +  // 슬라이더 생성하기
           rSlider = createSlider(0, 255, 100);
           rSlider.position(20, 20);
           gSlider = createSlider(0, 255, 0);
        diff --git a/src/data/examples/ko/16_Dom/07_Modify_DOM.js b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        index c784755f29..7366f94e56 100644
        --- a/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        +++ b/src/data/examples/ko/16_Dom/07_Modify_DOM.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Modifying the DOM
        + * @name DOM 변경
          * @frame 710,300
        - * @description <p>Create DOM elements and modify their properties every time
        - * draw() is called. You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.</p>
        + * @description <p>DOM 요소를 만들고 draw()함수가 매번 호출될 때마다
        + * 그 속성들을 변경해보세요. 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.</p>
          */
         let dancingWords = [];
         
        @@ -24,18 +24,17 @@ class DanceSpan {
         }
         
         function setup() {
        -  // This paragraph is created aside of the main block of code.
        -  // It's to differentiate the creation of an element from its
        -  // selection. Selected elements don't need to be created by
        -  // p5js, they can be just plain HTML.
        +  // 이 단락은 윗 단의 주요 코드 블록의 부록으로 작성되었습니다.
        +  // 아래의 코드들은 요소의 생성과 지정 기능을 각각 구분하고자 합니다.
        +  // 지정된 요소들은 p5js로 생성될 필요가 없으며,
        +  // 일반적인 HTML일 수 있습니다.
           createP(
             'I learn in this Letter, that Don Peter of Aragon, ' +
               ' comes this night to Messina'
           ).addClass('text').hide();
         
        -  // This line grabs the paragraph just created, but it would
        -  // also grab any other elements with class 'text' in the HTML
        -  // page.
        +  // 이 줄은 금방 생성된 '단락'을 받지만,
        +  // 동시에 HTML 페이지상 'text' 클래스를 가진 다른 요소들을 받아오기도 합니다.
           const texts = selectAll('.text');
         
           for (let i = 0; i < texts.length; i++) {
        diff --git a/src/data/examples/ko/16_Dom/08_Video.js b/src/data/examples/ko/16_Dom/08_Video.js
        index 45454f006b..87841c4410 100644
        --- a/src/data/examples/ko/16_Dom/08_Video.js
        +++ b/src/data/examples/ko/16_Dom/08_Video.js
        @@ -1,24 +1,22 @@
         /*
        - * @name Video
        + * @name 비디오
          * @frame 710,250
        - * @description <p>Load a video with multiple formats and toggle between playing
        - * and paused with a button press.
        - * <p><em><span class="small"> To run this example locally, you will need at least
        - * one video file, and the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.</span></em></p>
        + * @description <p>다양한 형식의 비디오를 불러오고 버튼을 눌러 재생과 일시 정지를 전환합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가하면 됩니다.</span></em></p>
          */
         let playing = false;
         let fingers;
         let button;
         
         function setup() {
        -  // specify multiple formats for different browsers
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
           button = createButton('play');
        -  button.mousePressed(toggleVid); // attach button listener
        +  button.mousePressed(toggleVid); // 버튼 리스너 붙이기
         }
         
        -// plays or pauses the video depending on current state
        +// 현재 상태에 따라 비디오를 재생 또는 일시 정지
         function toggleVid() {
           if (playing) {
             fingers.pause();
        diff --git a/src/data/examples/ko/16_Dom/09_Video_Canvas.js b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        index 81de6efd7c..02b9727715 100644
        --- a/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        +++ b/src/data/examples/ko/16_Dom/09_Video_Canvas.js
        @@ -1,28 +1,27 @@
         /*
        - * @name Video Canvas
        - * @description <p>Load a video with multiple formats and draw it to the canvas.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 비디오 캔버스
        + * @description <p>비디오를 다양한 형식으로 불러와 캔버스 위에 그릴 수 있도록 합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let fingers;
         
         function setup() {
           createCanvas(710, 400);
        -  // specify multiple formats for different browsers
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
        -  fingers.hide(); // by default video shows up in separate dom
        -  // element. hide it and draw it to the canvas
        -  // instead
        +  fingers.hide(); // 기본값으로, 비디오는 별개의 DOM 요소로 나타납니다.
        +  // 이를 우선 숨긴 뒤, 캔버스에 그릴 수 있도록 해볼까요
         }
         
         function draw() {
           background(150);
        -  image(fingers, 10, 10); // draw the video frame to canvas
        -  filter('GRAY');
        -  image(fingers, 150, 150); // draw a second copy to canvas
        +  image(fingers, 10, 10); // 캔버스에 비디오 프레임 그리기
        +  filter(GRAY);
        +  image(fingers, 150, 150); // 캔버스에 두번째 사본 그리기
         }
         
         function mousePressed() {
        -  fingers.loop(); // set the video to loop and start playing
        +  fingers.loop(); // 반복 재생 설정 및 비디오 재생
         }
        diff --git a/src/data/examples/ko/16_Dom/10_Video_Pixels.js b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        index ba7dcf0638..10bd28beef 100644
        --- a/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        +++ b/src/data/examples/ko/16_Dom/10_Video_Pixels.js
        @@ -1,16 +1,16 @@
         /*
        - * @name Video Pixels
        + * @name 비디오 픽셀
          * @frame 320,240
        - * @description <p>Load a video, manipulate its pixels and draw to canvas.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @description <p>비디오를 불러와 픽셀을 조정하고 캔버스에 그려보세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let fingers;
         
         function setup() {
           createCanvas(320, 240);
        -  // specify multiple formats for different browsers
        +  // 여러 브라우저 지원을 위해 다양한 비디오 형식 지정
           fingers = createVideo(['assets/fingers.mov', 'assets/fingers.webm']);
           fingers.loop();
           fingers.hide();
        diff --git a/src/data/examples/ko/16_Dom/11_Capture.js b/src/data/examples/ko/16_Dom/11_Capture.js
        index 31e706d487..4c3457e2a3 100644
        --- a/src/data/examples/ko/16_Dom/11_Capture.js
        +++ b/src/data/examples/ko/16_Dom/11_Capture.js
        @@ -1,13 +1,13 @@
         /*
        - * @name Video Capture
        + * @name 실시간 비디오
          * @frame 710,240
        - * @description <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p><br><br>
        - * Capture video from the webcam and display
        - * on the canvas as well with invert filter. Note that by
        - * default the capture feed shows up, too. You can hide the
        - * feed by uncommenting the capture.hide() line.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 비디오 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p><br><br>
        + * 웹캠을 통해 보여지는 실시간 비디오 화면을 캔버스 위에 그릴 수 있습니다.
        + * 반전 효과 필터도 적용할 수 있습니다.
        + * 실시간 비디오 화면은 기본값으로 캔버스 위에 나타납니다.
        + * 아래의 코드 중 capture.hide()의 주석 처리(//)를 해제하면 이 실시간 비디오 화면을 숨길 수 있습니다. 
          */
         let capture;
         
        diff --git a/src/data/examples/ko/16_Dom/12_Drop.js b/src/data/examples/ko/16_Dom/12_Drop.js
        index 3d42627e50..c3541c6d1f 100644
        --- a/src/data/examples/ko/16_Dom/12_Drop.js
        +++ b/src/data/examples/ko/16_Dom/12_Drop.js
        @@ -1,16 +1,16 @@
         /*
        - * @name Drop
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Drag an image file onto the canvas to see it displayed.
        + * @name 드롭 기능
        + * @description 여러분의 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가하면 됩니다.<br><br>
        + * 이미지 파일을 캔버스에 드래그 & 드롭하여 화면에 보이는지 확인해보세요.
          */
         
         function setup() {
        -  // create canvas
        +  // 캔버스 생성
           const c = createCanvas(710, 400);
           background(100);
        -  // Add an event for when a file is dropped onto the canvas
        +  // 캔버스에 이미지 파일이 드롭될 때 이벤트 추가
           c.drop(gotFile);
         }
         
        @@ -24,11 +24,11 @@ function draw() {
         }
         
         function gotFile(file) {
        -  // If it's an image file
        +  // 드롭된 파일이 이미지 파일이라면,
           if (file.type === 'image') {
        -    // Create an image DOM element but don't show it
        +    // 이미지 DOM 요소를 생성하되, 화면엔 띄우지 않는다.
             const img = createImg(file.data).hide();
        -    // Draw the image onto the canvas
        +    // 이미지를 캔버스에 그린다.
             image(img, 0, 0, width, height);
           } else {
             console.log('Not an image file!');
        diff --git a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        index c06901439a..aa89265d1d 100644
        --- a/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        +++ b/src/data/examples/ko/17_Drawing/00_Continuous_Lines.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Continous Lines
        - * @description Click and drag the mouse to draw a line.
        + * @name 연속된 선
        + * @description 마우스를 클릭하고 드래그하여 선을 그려보세요.
          */
         function setup() {
           createCanvas(710, 400);
        -  background(102);
        +  background(102);ㅌ
         }
         
         function draw() {
        diff --git a/src/data/examples/ko/17_Drawing/01_Pattern.js b/src/data/examples/ko/17_Drawing/01_Pattern.js
        index ab3ee36eb5..c1db5a64fd 100644
        --- a/src/data/examples/ko/17_Drawing/01_Pattern.js
        +++ b/src/data/examples/ko/17_Drawing/01_Pattern.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Patterns
        - * @description Move the cursor over the image to draw with a software tool
        - * which responds to the speed of the mouse.
        + * @name 패턴
        + * @description 캔버스 위로 마우스를 움직여 드로잉할 수 있는 소프트웨어 툴입니다.
        + * 이 때, 드로잉은 마우스의 속도에 반응합니다.
          */
         function setup() {
           createCanvas(710, 400);
        @@ -9,16 +9,15 @@ function setup() {
         }
         
         function draw() {
        -  // Call the variableEllipse() method and send it the
        -  // parameters for the current mouse position
        -  // and the previous mouse position
        +  // variableEllipse()메소드를 호출하고, 여기에
        +  // 마우스의 현재 및 이전 위치를 담은 매개 변수를 보냅니다.
           variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
         }
         
        -// The simple method variableEllipse() was created specifically
        -// for this program. It calculates the speed of the mouse
        -// and draws a small ellipse if the mouse is moving slowly
        -// and draws a large ellipse if the mouse is moving quickly
        +// 이 간단한 메소드 variableEllipse()는 이 프로그램을 위해
        +// 작성되었습니다. 메소드는 마우스의 속도를 계산하는데,
        +// 마우스가 천천히 움직이면 작은 타원을,
        +// 마우스가 빨리 움직이면 큰 타원을 그립니다.
         
         function variableEllipse(x, y, px, py) {
           let speed = abs(x - px) + abs(y - py);
        diff --git a/src/data/examples/ko/17_Drawing/02_Pulses.js b/src/data/examples/ko/17_Drawing/02_Pulses.js
        index c256672539..3b2e77f82d 100644
        --- a/src/data/examples/ko/17_Drawing/02_Pulses.js
        +++ b/src/data/examples/ko/17_Drawing/02_Pulses.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Pulses
        - * @description Software drawing instruments can follow a rhythm or abide by
        - * rules independent of drawn gestures. This is a form of collaborative drawing
        - * in which the draftsperson controls some aspects of the image and the software
        - * controls others.
        + * @name 율동
        + * @description 드로잉 스포트웨어는 특정 리듬이나, 그려진 제스쳐로부터 독립된 규칙을 따를 수 있습니다.
        + * 이 예제의 경우, 협업 드로잉으로도 볼 수 있습니다.
        + * 사용자가 이미지의 일부를 조정하면 소프트웨어가 다른 일부를 조정하는 식입니다.
          */
         let angle = 0;
         
        @@ -15,7 +14,7 @@ function setup() {
         }
         
         function draw() {
        -  // Draw only when mouse is pressed
        +  // 마우스가 클릭될 때만 그리기
           if (mouseIsPressed === true) {
             angle += 5;
             let val = cos(radians(angle)) * 12.0;
        diff --git a/src/data/examples/ko/18_Transform/00_Translate.js b/src/data/examples/ko/18_Transform/00_Translate.js
        index 1599f1cf4f..69f5a29aa1 100644
        --- a/src/data/examples/ko/18_Transform/00_Translate.js
        +++ b/src/data/examples/ko/18_Transform/00_Translate.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Translate
        - * @description The translate() function allows objects to be
        - * moved to any location within the window. The first parameter
        - * sets the x-axis offset and the second parameter sets the
        - * y-axis offset. This example shows how transforms accumulate.
        + * @name 변환(Translate)
        + * @description translate() 함수는 객체를 화면 내 어떤 위치로든 이동하게 합니다.
        + * 그 첫 번째 매개변수는 x축의 오프셋(offset)을,
        + * 두 번째 매개변수는 y축의 오프셋을 지정합니다.
        + * 이 예제는 이러한 변환들이 축적되는 것을 보여줍니다.
          */
         
         let x = 0;
        @@ -17,23 +17,22 @@ function setup() {
         
         function draw() {
           background(102);
        -  // Animate by increasing our x value
        +  // x값을 증가시켜 움직이게 만들기
           x = x + 0.8;
        -  // If the shape goes off the canvas, reset the position
        +  // 도형이 캔버스 밖으로 나가면, 위치를 리셋한다.
           if (x > width + dim) {
             x = -dim;
           }
         
        -  // Even though our rect command draws the shape with its
        -  // center at the origin, translate moves it to the new
        -  // x and y position
        +  // rect 명령어는 원점을 중심점으로 삼는 도형을 그리지만,
        +  // translate은 이를 새로운 x와 y 위치로 옮깁니다.
           translate(x, height / 2 - dim / 2);
           fill(255);
           rect(-dim / 2, -dim / 2, dim, dim);
         
        -  // Transforms accumulate. Notice how this rect moves
        -  // twice as fast as the other, but it has the same
        -  // parameter for the x-axis value
        +  // translate(변환)은 축적됩니다. 이 rect가 다른 rect와
        +  // 동일한 x축값 매개변수를 가졌음에도
        +  // 두 배로 빠르게 움직이는 걸 볼 수 있습니다.
           translate(x, dim);
           fill(0);
           rect(-dim / 2, -dim / 2, dim, dim);
        diff --git a/src/data/examples/ko/18_Transform/01_Scale.js b/src/data/examples/ko/18_Transform/01_Scale.js
        index d176f25680..93a4ad67fd 100644
        --- a/src/data/examples/ko/18_Transform/01_Scale.js
        +++ b/src/data/examples/ko/18_Transform/01_Scale.js
        @@ -1,11 +1,10 @@
         /*
        - * @name Scale
        - * @description Paramenters for the scale() function are values
        - * specified as decimal percentages. For example, the method
        - * call scale(2.0) will increase the dimension of the shape by
        - * 200 percent. Objects always scale from the origin. This example
        - * shows how transforms accumulate and also how scale and translate
        - * interact depending on their order.
        + * @name 크기 조정(Scale)
        + * @description scale()함수의 매개 변수는 10진수 백분율로 표현됩니다.
        + * 예를 들어, scale(2.0) 메소드 호출은 도형의 차원을 200 퍼센트 증가시킵니다.
        + * 오브젝트의 크기는 항상 원점을 기준으로 조정됩니다. 
        + * 이 예제는 그러한 변형이 누적되는 양상과, 순서에 따라 scale과 translate이
        + * 상호작용하는 것을 보여줍니다.
          */
         
         let a = 0.0;
        @@ -14,31 +13,31 @@ let s = 0.0;
         function setup() {
           createCanvas(720, 400);
           noStroke();
        -  //Draw all rectangles from their center as opposed to
        -  // the default upper left corner
        +  // 드로잉 시작 기본 위치인 상단 좌측 코너가 아닌,
        +  // 화면 중앙에서 직사각형이 그려지도록 합니다.
           rectMode(CENTER);
         }
         
         function draw() {
           background(102);
         
        -  //Slowly increase 'a' and then animate 's' with
        -  //a smooth cyclical motion by finding the cosine of 'a'
        +  // 'a'를 천천히 증가시킨 다음 'a'의 코사인을 찾아,
        +  // 's'에 부드럽고 주기적인 애니메이션 효과를 줍니다.
           a = a + 0.04;
           s = cos(a) * 2;
         
        -  //Translate our rectangle from the origin to the middle of
        -  //the canvas, then scale it with 's'
        +  // 사각형을 원점에서 캔버스 중간으로 변환(translate)한 다음,
        +  // 's'로 크기를 조정합니다.
           translate(width / 2, height / 2);
           scale(s);
           fill(51);
           rect(0, 0, 50, 50);
         
        -  //Translate and scale are accumulating, so this translate
        -  //moves the second rectangle further right than the first
        -  //and the scale is getting doubled. Note that cosine is
        -  //making 's' both negative and positive, thus it cycles
        -  //from left to right.
        +  // 변환과 크기 조정은 누적됩니다.
        +  // 따라서 변환된 두 번째 사각형은 첫 번째 사각형보다 
        +  // 조금 더 오른쪽으로 이동하게 되고, 그 크기는 두배가 됩니다.
        +  // 한편, 코사인은 's'가 음수와 양수를 오가도록 하는데,
        +  // 이에 따라 사각형이 왼쪽과 오른쪽을 순환하게 됩니다.
           translate(75, 0);
           fill(255);
           scale(s);
        diff --git a/src/data/examples/ko/18_Transform/02_Rotate.js b/src/data/examples/ko/18_Transform/02_Rotate.js
        index 6b91dc2186..d25d8de8f9 100644
        --- a/src/data/examples/ko/18_Transform/02_Rotate.js
        +++ b/src/data/examples/ko/18_Transform/02_Rotate.js
        @@ -1,14 +1,13 @@
         /*
        - * @name Rotate
        - * @description Rotating a square around the Z axis.
        - * To get the results you expect, send the rotate function angle
        - * parameters that are values between 0 and PI*2 (TWO_PI which is
        - * roughly 6.28). If you prefer to think about angles as degrees
        - * (0-360), you can use the radians() method to convert your values.
        - * For example: scale(radians(90)) is identical to the statement
        - * scale(PI/2). In this example, every even numbered second a jitter
        - * is added to the rotation. During odd seconds rotation moves CW and
        - * CCW at the speed determined by the last jitter value.
        + * @name 회전(Rotate)
        + * @description Z축을 기준으로 사각형 회전시킵니다.
        + * 원하는 결과를 얻기 위해, 0부터 PI*2(즉, TWO_PI, 약 6.28)에 해당하는,
        + * rotate 함수 속 각도 매개 변수를 보냅니다.
        + * 각도를 도(0-360) 단위로 표현하고 싶다면, radians() 메소드를 통해 변환하면 됩니다.
        + * 예: scale(radians(90))은 선언문 scale(PI/2)과 동일합니다.
        + * 이 예제에서, 모든 짝수 초마다 jitter(떨림)가 회전에 더해집니다.
        + * 홀수 초에는 마지막 jitter값으로 결정된 속도에 따라
        + * 시계 방향 또는 반시계 방향으로 회전합니다.
          */
         
         let angle = 0.0;
        @@ -18,26 +17,26 @@ function setup() {
           createCanvas(720, 400);
           noStroke();
           fill(255);
        -  //Draw the rectangle from the center and it will also be the
        -  //rotate around that center
        +  //중심으로부터 사각형을 그리고,
        +  //사각형이 중심을 기준으로 회전하도록 만들기
           rectMode(CENTER);
         }
         
         function draw() {
           background(51);
         
        -  // during even-numbered seconds (0, 2, 4, 6...) add jitter to
        -  // the rotation
        +  // 짝수 초(0, 2, 4, 6...)동안 회전에
        +  // jitter(떨림) 더하기
           if (second() % 2 === 0) {
             jitter = random(-0.1, 0.1);
           }
        -  //increase the angle value using the most recent jitter value
        +  // 가장 마지막 jitter값을 사용해 각도값 증가시키기
           angle = angle + jitter;
        -  //use cosine to get a smooth CW and CCW motion when not jittering
        +  // 떨림이 없는 경우, 코싸인을 사용해 부드러운 시계 방향 및 반시계 방향 모션 받기
           let c = cos(angle);
        -  //move the shape to the center of the canvas
        +  //도형을 캔버스의 중앙으로 이동시키기
           translate(width / 2, height / 2);
        -  //apply the final rotation
        +  //최종 회전 적용하기
           rotate(c);
           rect(0, 0, 180, 180);
         }
        diff --git a/src/data/examples/ko/18_Transform/03_Arm.js b/src/data/examples/ko/18_Transform/03_Arm.js
        index 733fe30909..b62f1dac02 100644
        --- a/src/data/examples/ko/18_Transform/03_Arm.js
        +++ b/src/data/examples/ko/18_Transform/03_Arm.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Arm
        - * @description This example uses transform matrices to create
        - * an arm. The angle of each segment is controlled with the
        - * mouseX and mouseY position. The transformations applied to
        - * the first segment are also applied to the second segment
        - * because they are inside the same push() and
        - * pop() matrix group.
        + * @name 팔모양
        + * @description 이 예제는 변형 행렬을 사용하여 팔모양을 만듭니다.
        + * 각 선분의 각도는 mouseX 및 mouseY 위치로 조정됩니다.
        + * 첫 번째 선분에 적용된 변형은 두 번째 선분에도 적용됩니다.
        + * 두 선분 모두 동일한 push() 및 pop() 행렬 그룹에 속하기 때문입니다.
          */
         
         let x, y;
        @@ -17,10 +15,10 @@ function setup() {
           createCanvas(720, 400);
           strokeWeight(30);
         
        -  //Stroke with a semi-transparent white
        +  // 반투명한 선 그리기
           stroke(255, 160);
         
        -  //Position the "shoulder" of the arm in the center of the canvas
        +  // 팔의 "어깨" 위치를 캔버스 중앙에 위치시키기
           x = width * 0.5;
           y = height * 0.5;
         }
        @@ -28,20 +26,20 @@ function setup() {
         function draw() {
           background(0);
         
        -  //Change the angle of the segments according to the mouse positions
        +  // 마우스 위치에 따라 선분의 각도 바꾸기
           angle1 = (mouseX / float(width) - 0.5) * -TWO_PI;
           angle2 = (mouseY / float(height) - 0.5) * PI;
         
        -  //use push and pop to "contain" the transforms. Note that
        -  // even though we draw the segments using a custom function,
        -  // the transforms still accumulate
        +  // push와 pop을 사용해 변형을 담기
        +  // 사용자 정의 함수를 사용해 선분을 그려도
        +  // 변형 내용이 축적되는 걸 볼 수 있습니다.
           push();
           segment(x, y, angle1);
           segment(segLength, 0, angle2);
           pop();
         }
         
        -//a custom function for drawing segments
        +// 선분을 그리기 위한 사용자 정의 함수
         function segment(x, y, a) {
           translate(x, y);
           rotate(a);
        diff --git a/src/data/examples/ko/19_Typography/00_Letters.js b/src/data/examples/ko/19_Typography/00_Letters.js
        index 2e16306ae3..f9084ab958 100644
        --- a/src/data/examples/ko/19_Typography/00_Letters.js
        +++ b/src/data/examples/ko/19_Typography/00_Letters.js
        @@ -1,23 +1,23 @@
         /*
        - * @name Letters
        - * @description Letters can be drawn to the screen by loading a font, setting
        - * its characteristics and then drawing the letters. This example uses a for
        - * loop and unicode reference numbers to automatically fill the canvas with
        - * characters in a grid. Vowels are selected and given a specific fill color.
        + * @name 글자
        + * @description 폰트를 불러와 글자 속성을 설정하면, 화면에 글자를 그릴 수 있습니다.
        + * 이 예제에서는 for 반복문과 유니코드 참조 번호를 사용하여,
        + * 그리드 속 글자들로 캔버스를 자동으로 채웁니다.
        + * 이 중, 모음들만 선택되어 특정 색상이 부여됩니다.
          */
         let font,
           fontsize = 32;
         
         function preload() {
        -  // Ensure the .ttf or .otf font stored in the assets directory
        -  // is loaded before setup() and draw() are called
        +  // setup()과 draw()를 호출하기에 앞서,
        +  // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
           font = loadFont('assets/SourceSansPro-Regular.otf');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -  // Set text characteristics
        +  // 텍스트 속성 설정
           textFont(font);
           textSize(fontsize);
           textAlign(CENTER, CENTER);
        @@ -26,22 +26,22 @@ function setup() {
         function draw() {
           background(160);
         
        -  // Set the gap between letters and the left and top margin
        +  // 글자 간, 그리고 글자와 좌측 및 상단 간의 margin(여백) 설정
           let gap = 52;
           let margin = 10;
           translate(margin * 4, margin * 4);
         
        -  // Set the counter to start at the character you want
        -  // in this case 35, which is the # symbol
        +  // 원하는 글자에서 시작하도록 카운터 설정
        +  // 이 예제에서는 유니코드 35, 즉 # 기호입니다.
           let counter = 35;
         
        -  // Loop as long as there is space on the canvas
        +  // 캔버스에 공간이 확보되는 한 반복하기
           for (let y = 0; y < height - gap; y += gap) {
             for (let x = 0; x < width - gap; x += gap) {
        -      // Use the counter to retrieve individual letters by their Unicode number
        +      // 카운터를 사용해 유니코드 번호로 개별 글자를 검색
               let letter = char(counter);
         
        -      // Add different color to the vowels and other characters
        +      // 모음과 기타 글자들에 각각 다른 색상 더하기
               if (
                 letter === 'A' ||
                 letter === 'E' ||
        @@ -54,10 +54,10 @@ function draw() {
                 fill(255);
               }
         
        -      // Draw the letter to the screen
        +      // 화면에 글자 그리기
               text(letter, x, y);
         
        -      // Increment the counter
        +      // 카운터 증가시키기
               counter++;
             }
           }
        diff --git a/src/data/examples/ko/19_Typography/01_Words.js b/src/data/examples/ko/19_Typography/01_Words.js
        index d76271f2b8..725cb82229 100644
        --- a/src/data/examples/ko/19_Typography/01_Words.js
        +++ b/src/data/examples/ko/19_Typography/01_Words.js
        @@ -1,22 +1,22 @@
         /*
        - * @name Words
        - * @description The text() function is used for writing words to the screen.
        - * The words can be aligned left, center, or right with the textAlign()
        - * function, and like with shapes, words can be colored with fill().
        + * @name 단어
        + * @description text()함수는 화면에 단어를 쓸 때 사용됩니다.
        + * textAlign()함수로 단어들을 왼쪽, 가운데, 또는 오른쪽 정렬할 수 있으며, 
        + * 도형과 마찬가지로, 단어들 역시 fill()로 그 색을 채울 수 있습니다.
          */
         let font,
           fontsize = 40;
         
         function preload() {
        -  // Ensure the .ttf or .otf font stored in the assets directory
        -  // is loaded before setup() and draw() are called
        +  // setup()과 draw()를 호출하기에 앞서,
        +  // assets 파일 경로에 .ttf 또는 .otf 폰트가 저장 및 로드되었는지 확인하세요. 
           font = loadFont('assets/SourceSansPro-Regular.otf');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -  // Set text characteristics
        +  // 텍스트 속성 설정
           textFont(font);
           textSize(fontsize);
           textAlign(CENTER, CENTER);
        @@ -25,26 +25,25 @@ function setup() {
         function draw() {
           background(160);
         
        -  // Align the text to the right
        -  // and run drawWords() in the left third of the canvas
        +  // 텍스트를 오른쪽 정렬하고
        +  // 캔버스의 좌측 1/3 영역에서 drawWords() 실행하기
           textAlign(RIGHT);
           drawWords(width * 0.25);
         
        -  // Align the text in the center
        -  // and run drawWords() in the middle of the canvas
        +  // 텍스트를 가운데 정렬하고
        +  // 캔버스의 가운데 영역에서 drawWords() 실행하기
           textAlign(CENTER);
           drawWords(width * 0.5);
         
        -  // Align the text to the left
        -  // and run drawWords() in the right third of the canvas
        +  // 텍스트를 왼쪽 정렬하고
        +  // 캔버스의 우측 1/3 영역에서 drawWords() 실행하기
           textAlign(LEFT);
           drawWords(width * 0.75);
         }
         
         function drawWords(x) {
        -  // The text() function needs three parameters:
        -  // the text to draw, the horizontal position,
        -  // and the vertical position
        +  // text() 함수에는 세 개의 매개 변수가 필요합니다:
        +  // 그려질 텍스트, 가로 위치, 그리고 세로 위치
           fill(0);
           text('ichi', x, 80);
         
        diff --git a/src/data/examples/ko/20_3D/00_geometries.js b/src/data/examples/ko/20_3D/00_geometries.js
        index a58cce64e8..59a9b03459 100644
        --- a/src/data/examples/ko/20_3D/00_geometries.js
        +++ b/src/data/examples/ko/20_3D/00_geometries.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Geometries
        - * @description There are six 3D primitives in p5 now.
        + * @name 기하
        + * @description 현재 p5에는 여섯 개의 3D 기초 조형이 있습니다.
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        index d9adf11963..f92bbc0423 100644
        --- a/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        +++ b/src/data/examples/ko/20_3D/01_sine_cosine_in_3D.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Sine Cosine in 3D
        - * @description Sine, cosine and push / pop could be applied in 3D as well.
        + * @name 3D속 싸인 코싸인
        + * @description 싸인, 코싸인, 그리고 push / pop 함수는 3D에도 적용됩니다.
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/20_3D/02_multiple_lights.js b/src/data/examples/ko/20_3D/02_multiple_lights.js
        index 7bed590f63..5600458a62 100644
        --- a/src/data/examples/ko/20_3D/02_multiple_lights.js
        +++ b/src/data/examples/ko/20_3D/02_multiple_lights.js
        @@ -1,6 +1,11 @@
         /*
        +<<<<<<< HEAD
        + * @name 복수의 조명들
        + * @description 한 스케치 위에 여러 종류의 조명을 사용할 수 있습니다.
        +=======
          * @name Multiple Lights
          * @description All types of lights could be used in one sketch.
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        diff --git a/src/data/examples/ko/20_3D/03_materials.js b/src/data/examples/ko/20_3D/03_materials.js
        index 4dd7e97e37..89875cdc22 100644
        --- a/src/data/examples/ko/20_3D/03_materials.js
        +++ b/src/data/examples/ko/20_3D/03_materials.js
        @@ -1,8 +1,15 @@
         /*
        +<<<<<<< HEAD
        + * @name 재질(Materials)
        + * @description 지원되는 재질은 다섯 가지 입니다.
        + * 각각은 조명에 다르게 반응합니다.
        + * 마우스를 움직여 빛의 위치를 바꿔보세요.
        +=======
          * @name Materials
          * @description There are five types of materials supported.
          * They respond to light differently.
          * Move your mouse to change the light position.
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let img;
         function setup() {
        diff --git a/src/data/examples/ko/20_3D/04_textures.js b/src/data/examples/ko/20_3D/04_textures.js
        index 0a4df84872..54aafba4a6 100644
        --- a/src/data/examples/ko/20_3D/04_textures.js
        +++ b/src/data/examples/ko/20_3D/04_textures.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Textures
        - * @description Images and videos are supported for texture.
        + * @name 텍스처
        + * @description 이미지와 비디오가 텍스처를 지원합니다.
          */
        -// video source: https://vimeo.com/90312869
        +// 비디오 출처: https://vimeo.com/90312869
         let img;
         let vid;
         let theta = 0;
        @@ -24,7 +24,7 @@ function draw() {
           rotateZ(theta * mouseX * 0.001);
           rotateX(theta * mouseX * 0.001);
           rotateY(theta * mouseX * 0.001);
        -  //pass image as texture
        +  //이미지를 텍스처로 전달하기
           texture(vid);
           sphere(150);
           pop();
        diff --git a/src/data/examples/ko/20_3D/07_orbit_control.js b/src/data/examples/ko/20_3D/07_orbit_control.js
        index 7d30f82cbd..7c45043100 100644
        --- a/src/data/examples/ko/20_3D/07_orbit_control.js
        +++ b/src/data/examples/ko/20_3D/07_orbit_control.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Orbit Control
        - * @description Orbit control allows you to drag and move around the world.
        + * @name 궤도 제어
        + * @description 궤도 제어(Orbit Control)를 사용해 월드를 드래그하거나 움직일 수 있습니다.
          */
         function setup() {
           createCanvas(710, 400, WEBGL);
        @@ -10,7 +10,7 @@ function draw() {
           background(250);
           let radius = width * 1.5;
         
        -  //drag to move the world.
        +  //월드를 움직이도록 드래그
           orbitControl();
         
           normalMaterial();
        diff --git a/src/data/examples/ko/21_Input/00_Clock.js b/src/data/examples/ko/21_Input/00_Clock.js
        index 5603db0f3e..7d9b53c902 100644
        --- a/src/data/examples/ko/21_Input/00_Clock.js
        +++ b/src/data/examples/ko/21_Input/00_Clock.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Clock
        - * @description The current time can be read with the second(),
        - * minute(), and hour() functions. In this example, sin() and
        - * cos() values are used to set the position of the hands.
        + * @name 시계
        + * @description second(), minute(), 그리고 hour()함수를 사용하여
        + * 현재 시간을 읽어올 수 있습니다.
        + * 이 예제에서는 sin()과 cos()값이 시침, 분침, 초침의 위치를 정합니다.
          */
         let cx, cy;
         let secondsRadius;
        @@ -27,20 +27,20 @@ function setup() {
         function draw() {
           background(230);
         
        -  // Draw the clock background
        +  // 시계 배경 그리기
           noStroke();
           fill(244, 122, 158);
           ellipse(cx, cy, clockDiameter + 25, clockDiameter + 25);
           fill(237, 34, 93);
           ellipse(cx, cy, clockDiameter, clockDiameter);
         
        -  // Angles for sin() and cos() start at 3 o'clock;
        -  // subtract HALF_PI to make them start at the top
        +  // sin()과 cos()의 각도는 3시 정각에서 시작;
        +  // HALF_PI를 뺄셈하여 상단에서부터 시작하도록 설정
           let s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
           let m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI) - HALF_PI;
           let h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2) - HALF_PI;
         
        -  // Draw the hands of the clock
        +  // 시계침들 그리기
           stroke(255);
           strokeWeight(1);
           line(cx, cy, cx + cos(s) * secondsRadius, cy + sin(s) * secondsRadius);
        @@ -49,7 +49,7 @@ function draw() {
           strokeWeight(4);
           line(cx, cy, cx + cos(h) * hoursRadius, cy + sin(h) * hoursRadius);
         
        -  // Draw the minute ticks
        +  // 분침 그리기
           strokeWeight(2);
           beginShape(POINTS);
           for (let a = 0; a < 360; a += 6) {
        diff --git a/src/data/examples/ko/21_Input/01_Constrain.js b/src/data/examples/ko/21_Input/01_Constrain.js
        index 36a08abd31..5aff15a043 100644
        --- a/src/data/examples/ko/21_Input/01_Constrain.js
        +++ b/src/data/examples/ko/21_Input/01_Constrain.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Constrain
        - * @description Move the mouse across the screen to move
        - * the circle. The program constrains the circle to its box.
        + * @name 제한
        + * @description 화면 위로 마우스를 움직이면 동그라미가 움직이지만,
        + * 박스 안에서만 움직이도록 제한되어 있습니다.
          */
         let mx = 1;
         let my = 1;
        diff --git a/src/data/examples/ko/21_Input/02_Easing.js b/src/data/examples/ko/21_Input/02_Easing.js
        index 6fe01dc1b0..d84bae3c2a 100644
        --- a/src/data/examples/ko/21_Input/02_Easing.js
        +++ b/src/data/examples/ko/21_Input/02_Easing.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Easing
        - * @description Move the mouse across the screen and the symbol
        - * will follow. Between drawing each frame of the animation, the
        - * program calculates the difference between the position of the
        - * symbol and the cursor. If the distance is larger than 1 pixel,
        - * the symbol moves part of the distance (0.05) from its current
        - * position toward the cursor.
        + * @name 이징(Easing)
        + * @description 화면 위로 마우스 커서를 움직이면 기호가 따라옵니다.
        + * 애니메이션의 매 프레임 사이에, 프로그램은 기호와 마우스 커서 간의 거리를 계산합니다.
        + * 만약 그 거리가 1픽셀보다 크다면, 기호는 현재 위치로부터 커서의 위치를 향해 
        + * 일정 거리(0.05)를 이동합니다.
          */
         let x = 1;
         let y = 1;
        diff --git a/src/data/examples/ko/21_Input/03_Keyboard.js b/src/data/examples/ko/21_Input/03_Keyboard.js
        index c7b50f99a3..643e11c539 100644
        --- a/src/data/examples/ko/21_Input/03_Keyboard.js
        +++ b/src/data/examples/ko/21_Input/03_Keyboard.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Keyboard
        - * @description Click on the image to give it focus and
        - * press the letter keys to create forms in time and space.
        - * Each key has a unique identifying number. These numbers
        - * can be used to position shapes in space.
        + * @name 키보드
        + * @description 이미지를 클릭하여 포커스를 주고
        + * 키보드 입력을 통해 화면에 모양을 만듭니다.
        + * 각 자판은 고유의 식별 번호를 갖습니다. 
        + * 이 번호들은 도형의 화면 상 위치를 정합니다.
          */
         let rectWidth;
         
        @@ -15,7 +15,7 @@ function setup() {
         }
         
         function draw() {
        -  // keep draw() here to continue looping while waiting for keys
        +  // draw()를 여기에 작성하여 키보드 입력을 기다리는 동안 반복되게 합니다.
         }
         
         function keyPressed() {
        @@ -24,10 +24,10 @@ function keyPressed() {
             keyIndex = key.charCodeAt(0) - 'a'.charCodeAt(0);
           }
           if (keyIndex === -1) {
        -    // If it's not a letter key, clear the screen
        +    // 글자 자판이 아닐 경우, 화면을 비웁니다.
             background(230);
           } else {
        -    // It's a letter key, fill a rectangle
        +    // 글자 자판일 경우, 사각면을 채웁니다.
             randFill_r = Math.floor(Math.random() * 255 + 1);
             randFill_g = Math.floor(Math.random() * 255 + 1);
             randFill_b = Math.floor(Math.random() * 255 + 1);
        diff --git a/src/data/examples/ko/21_Input/04_Mouse1D.js b/src/data/examples/ko/21_Input/04_Mouse1D.js
        index eb613fbab9..0ca0d20e8e 100644
        --- a/src/data/examples/ko/21_Input/04_Mouse1D.js
        +++ b/src/data/examples/ko/21_Input/04_Mouse1D.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Mouse 1D
        - * @description Move the mouse left and right to
        - * shift the balance. The "mouseX" variable is used
        - * to control both the size and color of the rectangles.
        + * @name 1D 마우스
        + * @description 마우스를 좌우로 움직여 균형점을 이동해보세요. 
        + * mouseX 변수로 사각형의 크기와 색상 모두를 조정할 수 있습니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/05_Mouse2D.js b/src/data/examples/ko/21_Input/05_Mouse2D.js
        index efc623adae..72f1513be4 100644
        --- a/src/data/examples/ko/21_Input/05_Mouse2D.js
        +++ b/src/data/examples/ko/21_Input/05_Mouse2D.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Mouse 2D
        - * @description Moving the mouse changes the position and
        - * size of each box.
        + * @name 2D 마우스
        + * @description 마우스를 움직이면 각 상자의 위치와 크기가 바뀝니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/06_MouseIsPressed.js b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        index 27279e99b0..b29e306fec 100644
        --- a/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        +++ b/src/data/examples/ko/21_Input/06_MouseIsPressed.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Mouse Press
        - * @description Move the mouse to position the shape.
        - * Press the mouse button to invert the color.
        + * @name 마우스 버튼
        + * @description 마우스를 움직여 도형의 위치를 바꿔보세요.
        + * 마우스 버튼을 눌러 색을 반전시킬 수 있습니다.
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/ko/21_Input/07_Mouse_Functions.js b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        index ad1acdc7b2..659b8e8e27 100644
        --- a/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        +++ b/src/data/examples/ko/21_Input/07_Mouse_Functions.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Mouse Functions
        - * @description Click on the box and drag it across the screen.
        + * @name 마우스 함수
        + * @description 상자를 클릭한 뒤 화면 위에서 드래그 해보세요.
          */
         let bx;
         let by;
        @@ -21,7 +21,7 @@ function setup() {
         function draw() {
           background(237, 34, 93);
         
        -  // Test if the cursor is over the box
        +  // 상자 위에 커서가 있는지를 테스트
           if (
             mouseX > bx - boxSize &&
             mouseX < bx + boxSize &&
        @@ -39,7 +39,7 @@ function draw() {
             overBox = false;
           }
         
        -  // Draw the box
        +  // 상자 그리기
           rect(bx, by, boxSize, boxSize);
         }
         
        diff --git a/src/data/examples/ko/21_Input/08_Mouse_Signals.js b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        index 8847fe8f1c..694d9e8aae 100644
        --- a/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        +++ b/src/data/examples/ko/21_Input/08_Mouse_Signals.js
        @@ -1,10 +1,9 @@
         /*
        - * @name Mouse Signals
        - * @description Move and click the mouse to generate signals.
        - * The top row is the signal from "mouseX", the middle row is
        - * the signal from "mouseY", and the bottom row is the signal
        - * from "mouseIsPressed".
        - */
        + * @name 마우스 신호
        + * @description 마우스를 움직이고 클릭하여 신호를 만들어보세요.
        + * 상단의 행은 "mouseX", 가운데 행은 "mouseY",
        + * 하단의 행은 "mouseIsPressed"에 대한 신호입니다.
        +  */
         let xvals = [];
         let yvals = [];
         let bvals = [];
        @@ -22,7 +21,7 @@ function draw() {
             yvals[i - 1] = yvals[i];
             bvals[i - 1] = bvals[i];
           }
        -  // Add the new values to the end of the array
        +  // 배열의 마지막에 새로운 값들 더하기
           xvals[width - 1] = mouseX;
           yvals[width - 1] = mouseY;
         
        diff --git a/src/data/examples/ko/21_Input/09_Storing_Input.js b/src/data/examples/ko/21_Input/09_Storing_Input.js
        index 563ff80759..ea88476c2f 100644
        --- a/src/data/examples/ko/21_Input/09_Storing_Input.js
        +++ b/src/data/examples/ko/21_Input/09_Storing_Input.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Storing Input
        - * @description Move the mouse across the screen to
        - * change the position of the circles. The positions
        - * of the mouse are recorded into an array and played
        - * back every frame. Between each frame, the newest
        - * value are added to the end of each array and the
        - * oldest value is deleted.
        + * @name 입력값 저장
        + * @description 화면 위로 마우스를 움직여 원들의 위치를 바꿔보세요.
        + * 마우스의 위치값들은 배열에 기록되고 매 프레임마다 재생됩니다.
        + * 각 프레임이 재생되는 사이, 가장 새로운 값이 배열의 마지막에 더해지고
        + * 가장 오래된 값은 삭제됩니다.
          */
         let num = 60;
         let mx = [];
        @@ -24,14 +22,14 @@ function setup() {
         function draw() {
           background(237, 34, 93);
         
        -  // Cycle through the array, using a different entry on each frame.
        -  // Using modulo (%) like this is faster than moving all the values over.
        +  // 각 프레임마다 다른 입력값을 이용해 배열을 순환
        +  // 이처럼 모듈로(%)를 사용하면 모든 값들을 이동시키는 것보다 빠릅니다.
           let which = frameCount % num;
           mx[which] = mouseX;
           my[which] = mouseY;
         
           for (let i = 0; i < num; i++) {
        -    // which+1 is the smallest (the oldest in the array)
        +    // which+1은 가장 작은 값 (동시에, 배열에서 가장 오래된 값)
             let index = (which + 1 + i) % num;
             ellipse(mx[index], my[index], i, i);
           }
        diff --git a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        index 7d3e8f4b66..251a3b0c8a 100644
        --- a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        +++ b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        @@ -1,13 +1,13 @@
         /*
        - * @name Load Saved JSON
        - * @description Create a Bubble class, instantiate multiple bubbles using data from
        - * a JSON file, and display results on the screen.
        - *  Because the web browsers differ in where they save files, we do not make use of
        - * saveJSON, unlike the Processing example.<br><br>
        - * Based on Daniel Shiffman's <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON Example</a> for Processing.
        + * @name 저장된 JSON 불러오기
        + * @description Bubble 클래스를 만들고, JSON 파일의 데이터를 사용해 버블 여러 개를 인스턴스화합니다.
        + * 그리고, 그 결과물을 화면에 띄웁니다.
        + * 웹 브라우저마다 파일 저장 위치가 다르기 때문에,
        + * 프로세싱(Processing)의 예제와는 달리 saveJSON을 사용하지 않습니다.<br><br>
        + * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)의 <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON 예제</a> 참고
          */
         
        -// Bubble class
        +// Bubble 클래스
         class Bubble {
           constructor(x, y, diameter, name) {
             this.x = x;
        @@ -19,13 +19,13 @@ class Bubble {
             this.over = false;
           }
         
        -  // Check if mouse is over the bubble
        +  // 마우스가 버블 위에 있는지 확인
           rollover(px, py) {
             let d = dist(px, py, this.x, this.y);
             this.over = d < this.radius;
           }
         
        -  // Display the Bubble
        +  // 버블을 화면에 보이기
           display() {
             stroke(0);
             strokeWeight(0.8);
        @@ -39,23 +39,23 @@ class Bubble {
           }
         }
         
        -let data = {}; // Global object to hold results from the loadJSON call
        -let bubbles = []; // Global array to hold all bubble objects
        +let data = {}; // loadJSON 호출의 결과물을 담는 전역 객체
        +let bubbles = []; // 모든 버블 객체를 담는 전역 배열
         
        -// Put any asynchronous data loading in preload to complete before "setup" is run
        +// 비동기 데이터 로딩을 preload에 담아 setup이 실행되기 전 완료시킴
         function preload() {
           data = loadJSON('assets/bubbles.json');
         }
         
        -// Convert saved Bubble data into Bubble Objects
        +// 저장된 Bubble 데이터를 Bubble 객체로 전환
         function loadData() {
           let bubbleData = data['bubbles'];
           for (let i = 0; i < bubbleData.length; i++) {
        -    // Get each object in the array
        +    // 배열 속 각 객체 받아오기
             let bubble = bubbleData[i];
        -    // Get a position object
        +    // position 객체 받아오기
             let position = bubble['position'];
        -    // Get x,y from position
        +    // 위치로부터 x,y 받아오기
             let x = position['x'];
             let y = position['y'];
         
        @@ -63,23 +63,23 @@ function loadData() {
             let diameter = bubble['diameter'];
             let label = bubble['label'];
         
        -    // Put object in array
        +    // 배열에 객체 담기
             bubbles.push(new Bubble(x, y, diameter, label));
           }
         }
         
        -// Create a new Bubble each time the mouse is clicked.
        +// 마우스가 클릭될 때마다 새로운 Bubble 만들기
         function mousePressed() {
        -  // Add diameter and label to bubble
        +  // Bubble에 지름과 레이블 더하기
           let diameter = random(40, 80);
           let label = 'New Label';
         
        -  // Append the new JSON bubble object to the array
        +  // 배열에 새로운 JSON bubble 객체 더하기
           bubbles.push(new Bubble(mouseX, mouseY, diameter, label));
         
        -  // Prune Bubble Count if there are too many
        +  // 버블이 너무 많을 경우 개수 제거하기
           if (bubbles.length > 10) {
        -    bubbles.shift(); // remove first item from array
        +    bubbles.shift(); // 배열의 첫 번째 항목 제거하기
           }
         }
         
        @@ -91,13 +91,13 @@ function setup() {
         function draw() {
           background(255);
         
        -  // Display all bubbles
        +  // 모든 버블들 화면에 보이기
           for (let i = 0; i < bubbles.length; i++) {
             bubbles[i].display();
             bubbles[i].rollover(mouseX, mouseY);
           }
         
        -  // Label directions at bottom
        +  // 하단에서의 레이블 방향들
           textAlign(LEFT);
           fill(0);
           text('Click to add bubbles.', 10, height - 10);
        diff --git a/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
        index feffaffdc7..5b3eb5751d 100644
        --- a/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
        +++ b/src/data/examples/ko/33_Sound/00_Load_and_Play_Sound.js
        @@ -1,9 +1,17 @@
         /*
        +<<<<<<< HEAD
        + * @name 사운드 불러오기/재생
        + * @description preload()중 사운드 불러오기. 캔버스가 클릭될 때마다 소리를 재생합니다.
        + * <br><br><p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p><br><br>
        +=======
          * @name Load and Play Sound
          * @description Load sound during preload(). Play a sound when canvas is clicked.
          * <br><br><em><span class="small"> To run this example locally, you will need the
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
          * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em>
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let song;
         
        @@ -15,7 +23,11 @@ function setup() {
         
         function mousePressed() {
           if (song.isPlaying()) {
        +<<<<<<< HEAD
        +    // .isPlaying()은 불리언 값을 반환합니다.
        +=======
             // .isPlaying() returns a boolean
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
             song.stop();
             background(255, 0, 0);
           } else {
        diff --git a/src/data/examples/ko/33_Sound/01_Preload_Sound.js b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        index 08c419179e..38120ffaaa 100644
        --- a/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        +++ b/src/data/examples/ko/33_Sound/01_Preload_Sound.js
        @@ -1,13 +1,13 @@
         /*
        - * @name Preload SoundFile
        - * @description Call loadSound() during preload() to ensure that the
        - * sound is completely loaded before setup() is called. It's best to always
        - * call loadSound() in preload(), otherwise sounds won't necessarily be loaded
        - * by the time you want to play them in your sketch.
        + * @name 사운드 파일 미리 불러오기
        + * @description preload()에서 loadSound()를 호출하여,
        + * setup()이 호출되기 전에 미리 사운드 파일을 불러오도록 합니다.
        + * 이 때, preload()에서 loadSound()를 호출하는 것이 가장 좋은 방법입니다.
        + * 그렇지 않을 경우, 스케치에서 사운드 재생을 원하는 시점에 파일이 불러지지 않을 수 있습니다.
          *
        - * <br><br><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em>
        + * <br><br><p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         
         let song;
        @@ -18,14 +18,15 @@ function preload() {
         
         function setup() {
           createCanvas(710, 200);
        -  song.loop(); // song is ready to play during setup() because it was loaded during preload
        +  song.loop(); // 이제 노래 파일이 setup()에서 재생될 준비가 되었습니다.
        +               //preload에서 이미 한 차례 불러왔기 때문입니다.
           background(0, 255, 0);
         }
         
         function mousePressed() {
           if (song.isPlaying()) {
        -    // .isPlaying() returns a boolean
        -    song.pause(); // .play() will resume from .pause() position
        +    // .isPlaying()은 불리언 값을 반환합니다.
        +    song.pause(); // .play()는 .pause() 지점에서 다시 시작합니다.
             background(255, 0, 0);
           } else {
             song.play();
        diff --git a/src/data/examples/ko/33_Sound/02_soundFormats.js b/src/data/examples/ko/33_Sound/02_soundFormats.js
        index ae7571fb01..0cf8a92cdc 100644
        --- a/src/data/examples/ko/33_Sound/02_soundFormats.js
        +++ b/src/data/examples/ko/33_Sound/02_soundFormats.js
        @@ -1,54 +1,50 @@
         /**
        - *  @name soundFormats
        - *  @description <p>Technically, due to patent issues, there is no single
        - *  sound format that is supported by all web browsers. While
        - *  <a href="http://caniuse.com/#feat=mp3">mp3 is supported</a> across the
        - *  latest versions of major browsers on OS X and Windows, for example,
        - *  it may not be available on some less mainstream operating systems and
        - *  browsers.</p>
        + *  @name 사운드 파일 형식
        + *  @description <p>특허 문제로 인해, 모든 웹 브라우저가 지원하는
        + *  단일의 사운드 파일 형식은 존재하지 않습니다. 
        + *  예를 들어, 
        + *  <a href="http://caniuse.com/#feat=mp3">mp3</a>의 경우, OSX나 윈도우즈의
        + *  주요 브라우저 최신 버전에서 지원하긴 하지만, 일부 운영 체제나 브라우저에서는
        + *  사용하지 못할 수 있습니다.</p>
          *
        - *  <p>To ensure full compatibility, you can include the same sound file
        - *  in multiple formats, e.g. 'sound.mp3' and 'sound.ogg'. (Ogg is an
        - *  open source alternative to mp3.) You can convert audio files
        - *  into web friendly formats for free online at <a href="
        - *  http://media.io/">media.io</a></p>.
        + *  <p>사운드 파일의 완전한 호환성을 보장하기 위해, 동일한 사운드 파일을 
        + *  여러가지 형식으로 스케치에 포함시킬 수 있습니다. 'sound.mp3'나 'sound.ogg'가 그 예입니다.
        + *  (Ogg는 mp3의 대안형 오픈 소스입니다.) <a href="http://media.io/">media.io</a>
        + *  에서 오디오 파일을 웹-친화적인 형식으로 무료 변환할 수 있습니다.</p>.
          *
        - *  <p>The soundFormats() method tells loadSound which formats
        - *  we have included with our sketch. Then, loadSound will
        - *  attempt to load the first format that is supported by the
        - *  client's web browser.</p>
        + *  <p>soundFormats() 메소드는 현재 스케치에 포함된 사운드 파일의 형식들을 loadSound에게 지정합니다.
        + *  그러면, loadSound는 지정된 형식들 중 클라이언트의 웹 브라우저가 지원하는
        + *  첫번째 형식을 불러오도록 시도할 것입니다.</p>
          *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
         let song;
         
         function preload() {
        -  // we have included both an .ogg file and an .mp3 file
        +  // .ogg와 .mp3 파일 모두를 스케치에 포함시키기
           soundFormats('ogg', 'mp3');
         
        -  // if mp3 is not supported by this browser,
        -  // loadSound will load the ogg file
        -  // we have included with our sketch
        +  // 만약 mp3를 이 브라우저가 지원하지 않는다면,
        +  // loadSound는 스케치에 포함된 형식인 ogg 파일을 불러옵니다.
           song = loadSound('assets/lucky_dragons_-_power_melody.mp3');
         }
         
         function setup() {
           createCanvas(710, 200);
         
        -  // song loaded during preload(), ready to play in setup()
        +  // preload()중에 사운드 파일을 미리 불러와, setup()에서 재생할 수 있도록 준비
           song.play();
           background(0, 255, 0);
         }
         
         function mousePressed() {
           if (song.isPlaying()) {
        -    // .isPlaying() returns a boolean
        +    // .isPlaying()은 불리언 값을 반환합니다.
             song.pause();
             background(255, 0, 0);
           } else {
        -    song.play(); // playback will resume from the pause position
        +    song.play(); // playback은 pause(일시정지) 지점에서 다시 재생합니다.
             background(0, 255, 0);
           }
         }
        diff --git a/src/data/examples/ko/33_Sound/03_Play_Mode.js b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        index 3b89691dee..accdf51bc2 100644
        --- a/src/data/examples/ko/33_Sound/03_Play_Mode.js
        +++ b/src/data/examples/ko/33_Sound/03_Play_Mode.js
        @@ -1,13 +1,13 @@
         /*
        - * @name Play Mode
        + * @name 재생 모드
          * @description
        - * <p>In 'sustain' mode, the sound will overlap with itself.
        - * In 'restart' mode it will stop and then start again.
        - * Click mouse to play a sound file.
        - * Trigger lots of sounds at once! Press any key to change playmode.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * <p>'sustain' 모드에서는 사운드가 겹쳐서 재생됩니다.
        + * 'restart' 모드에서는 사운드가 멈췄다가 다시 재생합니다.
        + * 마우스 클릭으로 사운드 파일을 재생해보세요.
        + * 동시에 여러 사운드를 재생해보세요! 아무 자판을 눌러 재생 모드를 변경합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let playMode = 'sustain';
         let sample;
        diff --git a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        index b1d881db36..0f07dd1a6a 100644
        --- a/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        +++ b/src/data/examples/ko/33_Sound/04_Pan_SoundFile.js
        @@ -1,10 +1,10 @@
         /*
        - * @name Pan Sound
        - * @description <p>Click mouse to play the sound.
        - * Ball position follows mouse and correlates to panning of sound.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 사운드 패닝
        + * @description <p>마우스를 클릭해 사운드를 재생하세요.
        + * 공의 위치는 마우스의 위치와 더불어, 사운드의 패닝과도 관련됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          *
          */
         let ball = {};
        @@ -26,8 +26,8 @@ function draw() {
         }
         
         function mousePressed() {
        -  // map the ball's x location to a panning degree
        -  // between -1.0 (left) and 1.0 (right)
        +  // 공의 x 위치를 패닝 각도에 맵핑하기
        +  // -1.0 (좌) 과 1.0 (우) 사이
           let panning = map(ball.x, 0, width, -1.0, 1.0);
           soundFile.pan(panning);
           soundFile.play();
        diff --git a/src/data/examples/ko/33_Sound/05_Sound_Effect.js b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        index ee825d2e15..7f9b5e65a3 100644
        --- a/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        +++ b/src/data/examples/ko/33_Sound/05_Sound_Effect.js
        @@ -1,29 +1,29 @@
         /*
        - * @name Sound Effect
        - * @description <p>Play a sound effect when the mouse is clicked inside the circle.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 사운드 효과
        + * @description <p>마우스로 원 안쪽을 누르면 사운드 효과가 재생됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
        -// Adapted from Learning Processing by Daniel Shiffman
        +// 다니엘 쉬프만(Daniel Shiffman)의 Learning Processing을 적용
         // http://www.learningprocessing.com
        -// Doorbell sample by Corsica_S via freesound.org,
        +// 초인종 샘플 출처: freesound.org에서 Corsica_S 제작,
         // Creative Commons BY 3.0
         
        -// A Class to describe a "doorbell" (really a button)
        +// "doorbell(초인종)"을 설명하는 클래스 (실제로 버튼처럼 작동)
         class Doorbell {
           constructor(x_, y_, r_) {
        -    // Location and size
        +    // 위치와 크기
             this.x = x_;
             this.y = y_;
             this.r = r_;
           }
        -  // Is a point inside the doorbell? (used for mouse rollover, etc.)
        +  // doorbell 안에 마우스 점이 있나요? (마우스 롤오버 등에 사용)
           contains(mx, my) {
             return dist(mx, my, this.x, this.y) < this.r;
           }
         
        -  // Show the doorbell (hardcoded colors, could be improved)
        +  // doorbell을 보여주세요. (색상 부분은 하드코딩이네요. 더 나은 방법이 있을거에요.)
           display(mx, my) {
             if (this.contains(mx, my)) {
               fill(100);
        @@ -36,32 +36,32 @@ class Doorbell {
           }
         }
         
        -// A sound file object
        +// 사운드 파일 객체
         let dingdong;
         
        -// A doorbell object (that will trigger the sound)
        +// 초인종 객체 (사운드를 트리거)
         let doorbell;
         
         function setup() {
           createCanvas(200, 200);
         
        -  // Load the sound file.
        -  // We have included both an MP3 and an OGG version.
        +  // 사운드 파일 불러오기
        +  // 스케치에 MP3와 OGG 버전을 포함시킵니다.
           soundFormats('mp3', 'ogg');
           dingdong = loadSound('assets/doorbell.mp3');
         
        -  // Create a new doorbell
        +  // 새로운 초인종 만들기
           doorbell = new Doorbell(width / 2, height / 2, 64);
         }
         
         function draw() {
           background(255);
        -  // Show the doorbell
        +  // 초인종 보이기
           doorbell.display(mouseX, mouseY);
         }
         
         function mousePressed() {
        -  // If the user clicks on the doorbell, play the sound!
        +  // 사용자가 초인종을 클릭하면, 사운드 재생하기!
           if (doorbell.contains(mouseX, mouseY)) {
             dingdong.play();
           }
        diff --git a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        index 60ad548038..5edc06eb21 100644
        --- a/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        +++ b/src/data/examples/ko/33_Sound/06_Manipulate_Sound.js
        @@ -1,45 +1,44 @@
         /*
        - * @name Playback Rate
        - * @description <p>Load a SoundFile and map its playback rate to
        - * mouseY, volume to mouseX. Playback rate is the speed with
        - * which the web audio context processings the sound file information.
        - * Slower rates not only increase the duration of the sound, but also
        - * decrease the pitch because it is being played back at a slower frequency.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 재생 속도
        + * @description <p>사운드 파일을 불러와 재생 속도와 볼륨을 mouseY에 맵핑합니다.
        + * 여기서 재생 속도란, 웹 오디오가 사운드 파일 정보를 처리하는 속도를 말합니다.
        + * 재생 속도가 느리면 사운드의 지속 시간을 늘릴 뿐 아니라,
        + * 느린 주파수에서 재생되어 음고(pitch)를 감소시킵니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
        -// A sound file object
        +// 사운드 파일 객체
         let song;
         
         function preload() {
        -  // Load a sound file
        +  // 사운드 파일 불러오기
           song = loadSound('assets/Damscray_DancingTiger.mp3');
         }
         
         function setup() {
           createCanvas(710, 400);
         
        -  // Loop the sound forever
        -  // (well, at least until stop() is called)
        +  // 사운드 무한 반복하기
        +  // (뭐, 적어도 stop()이 호출되기 전까지요)
           song.loop();
         }
         
         function draw() {
           background(200);
         
        -  // Set the volume to a range between 0 and 1.0
        +  // 볼륨 범위를 0 과 1.0 사이로 설정
           let volume = map(mouseX, 0, width, 0, 1);
           volume = constrain(volume, 0, 1);
           song.amp(volume);
         
        -  // Set the rate to a range between 0.1 and 4
        -  // Changing the rate alters the pitch
        +  // 재생 속도 범위를 0.1 과 4 사이로 설정
        +  // 재생 속도를 변경하면 음고 또한 달라집니다.
           let speed = map(mouseY, 0.1, height, 0, 2);
           speed = constrain(speed, 0.01, 4);
           song.rate(speed);
         
        -  // Draw some circles to show what is going on
        +  // 원을 그려 어떤 일이 일어나는지 확인하기
           stroke(0);
           fill(51, 100);
           ellipse(mouseX, 100, 48, 48);
        diff --git a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        index 7bf3446e4f..91c2e4e994 100644
        --- a/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        +++ b/src/data/examples/ko/33_Sound/07_Amplitude_Analysis.js
        @@ -1,24 +1,21 @@
         /**
        - * @name Measuring Amplitude
        - * @description <p>Analyze the amplitude of sound with
        - * p5.Amplitude.</p>
        + * @name 진폭 측정
        + * @description <p>p5.Amplitude로 사운드의 진폭을 분석합니다.</p>
          *
        - *  <p><b>Amplitude</b> is the magnitude of vibration. Sound is vibration,
        - *  so its amplitude is is closely related to volume / loudness.</p>
        + *  <p><b>진폭(amplitude)</b>은 진동의 크기를 말합니다.
        + *  사운드는 진동이므로, 볼륨/음량과 밀접한 관계를 갖습니다.</p>
          *
        - * <p>The <code>getLevel()</code> method takes an array
        - * of amplitude values collected over a small period of time (1024 samples).
        - * Then it returns the <b>Root Mean Square (RMS)</b> of these values.</p>
        + * <p><code>getLevel()</code> 메소드는 짧은 시간 동안 수집된
        + * 진폭값(1024 샘플)을 배열에 담습니다.
        + * 그 다음, 이 값들의 <b>제곱 평균 제곱근(RMS)</b>을 반환합니다.</p>
          *
        - * <p>The original amplitude values for digital audio are between -1.0 and 1.0.
        - * But the RMS will always be positive, because it is squared.
        - * And, rather than use instantanous amplitude readings that are sampled at a rate
        - * of 44,100 times per second, the RMS is an average over time (1024 samples, in this case),
        - * which better represents how we hear amplitude.
        - * </p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * <p>디지털 오디오의 본래 진폭값은 -1.0과 1.0 사이입니다.
        + * 하지만, RMS는 제곱이므로 항상 양수입니다.
        + * 또한, RMS는 초당 44,000배의 속도에서 샘플링된 순간 진폭 판독값을 사용하는 대신
        + * 시간에 따른 평균값(이 경우, 1024 샘플)을 사용하여, 진폭을 듣는 방식을 더욱 잘 나타냅니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let song, analyzer;
         
        @@ -30,21 +27,21 @@ function setup() {
           createCanvas(710, 200);
           song.loop();
         
        -  // create a new Amplitude analyzer
        +  // 새로운 진폭 분석기 생성
           analyzer = new p5.Amplitude();
         
        -  // Patch the input to an volume analyzer
        +  // 볼륨 분석기에 입력값 패치하기
           analyzer.setInput(song);
         }
         
         function draw() {
           background(255);
         
        -  // Get the average (root mean square) amplitude
        +  // 평균 진폭값(RMS) 받아오기
           let rms = analyzer.getLevel();
           fill(127);
           stroke(0);
         
        -  // Draw an ellipse with size based on volume
        +  // 볼륨과 비례한 크기의 타원 그리기
           ellipse(width / 2, height / 2, 10 + rms * 200, 10 + rms * 200);
         }
        diff --git a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        index b38e423c75..2132861e7d 100644
        --- a/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        +++ b/src/data/examples/ko/33_Sound/08_Noise_Envelope.js
        @@ -1,49 +1,45 @@
         /**
        - *  @name Noise Drum Envelope
        - *  @description  <p>White Noise is a random audio signal with equal energy
        - *  at every part of the frequency spectrum</p>
        - *
        - *  <p>An Envelope is a series of fades, defined
        - *  as time / value pairs.</p>
        - *
        - *  <p>In this example, the p5.Env
        - *  will be used to "play" the p5.Noise like a drum by controlling its output
        - *  amplitude. A p5.Amplitude will get the level of all sound in the sketch, and
        - *  we'll use this value to draw a green rectangle that shows the envelope
        - *  in action.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        + *  @name 노이즈 드럼 엔벨로프
        + *  @description  <p> 화이트 노이즈는 주파수 영역의 모든 부분에서
        + *  동일한 에너지를 갖는, 임의의 오디오 신호입니다</p>
        + *  <p>엔벨로프(envelope)는 시간/값의 쌍으로 정의되는
        + *  일련의 페이드를 말합니다.</p>
        + *  <p>이 예제에서는, p5.Env로 출력된 진폭을 제어하여
        + *  p5.Noise를 마치 드럼처럼 "재생"합니다.
        + *  p5.Amplitude는 스케치에 포함된 모든 사운드들의 레벨을 가져오며,
        + *  작동 중인 엔벨로프를 이 값으로서 초록색 사각형으로 표현합니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
          */
         let noise, env, analyzer;
         
         function setup() {
           createCanvas(710, 200);
        -  noise = new p5.Noise(); // other types include 'brown' and 'pink'
        +  noise = new p5.Noise(); // 그 외 타입들은 '갈색'과 '분홍'을 포함
           noise.start();
         
        -  // multiply noise volume by 0
        -  // (keep it quiet until we're ready to make noise!)
        +  // 노이즈 볼륨에 0 곱하기
        +  // (노이즈 재생 전까지 조용하기 위해서요!)
           noise.amp(0);
         
           env = new p5.Env();
        -  // set attackTime, decayTime, sustainRatio, releaseTime
        +  // 어택 시간, 감쇠 시간, 지속 속도, 릴리즈 시간 설정
           env.setADSR(0.001, 0.1, 0.2, 0.1);
        -  // set attackLevel, releaseLevel
        +  // 어택 레벨, 릴리즈 레벨 설정
           env.setRange(1, 0);
         
        -  // p5.Amplitude will analyze all sound in the sketch
        -  // unless the setInput() method is used to specify an input.
        +  // setInput()메소드로 입력값을 지정하지 않는 이상,
        +  // p5.Amplitude는 스케치에 포함된 모든 사운드를 분석할 것입니다.
           analyzer = new p5.Amplitude();
         }
         
         function draw() {
           background(0);
         
        -  // get volume reading from the p5.Amplitude analyzer
        +  // p5.Amplitude analyzer(분석 장치)로부터 볼륨 판독값 받아오기
           let level = analyzer.getLevel();
         
        -  // use level to draw a green rectangle
        +  // 레벨값을 사용하여 초록색 사각형 그리기
           let levelHeight = map(level, 0, 0.4, 0, height);
           fill(100, 250, 100);
           rect(0, height, width, -levelHeight);
        diff --git a/src/data/examples/ko/33_Sound/09_Note_Envelope.js b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        index 4b9122d244..853814b982 100644
        --- a/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        +++ b/src/data/examples/ko/33_Sound/09_Note_Envelope.js
        @@ -1,18 +1,16 @@
         /**
        - *  @name Note Envelope
        - *  @description  <p>An Envelope is a series of fades, defined
        - *  as time / value pairs. In this example, the envelope
        - *  will be used to "play" a note by controlling the output
        - *  amplitude of an oscillator.<br/><br/>
        - *  The p5.Oscillator sends its output through
        - *  an internal Web Audio GainNode (p5.Oscillator.output).
        - *  By default, that node has a constant value of 0.5. It can
        - *  be reset with the osc.amp() method. Or, in this example, an
        - *  Envelope takes control of that node, turning the amplitude
        - *  up and down like a volume knob.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        + *  @name 음계 엔벨로프
        + *  @description  <p>엔벨로프(envelope)는 시간/값의 쌍으로 정의되는
        + *  일련의 페이드를 말합니다.
        + *  이 예제에서 엔벨로프는 오실레이터의 출력 진폭을 제어하여 
        + *  음계를 "재생"하는 데 사용됩니다.<br/><br/>
        + *  p5.Oscillator은 내부 웹 오디오 GainNode(p5.Oscillator.output)
        + *  를 거쳐 그 출력 내용을 전송합니다.
        + *  이 노드는 기본값으로 상수 0.5를 갖는데, osc.amp()메소드로 재설정할 수 있습니다.
        + *  또는 이 예제에서처럼, 엔벨로프가 직접 노드를 제어하여
        + *  마치 볼륨을 조정하듯 진폭을 조정할 수 있습니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
          */
         let osc, envelope, fft;
         
        @@ -23,13 +21,13 @@ function setup() {
           createCanvas(710, 200);
           osc = new p5.SinOsc();
         
        -  // Instantiate the envelope
        +  // 엔벨로프 인스턴스화
           envelope = new p5.Env();
         
        -  // set attackTime, decayTime, sustainRatio, releaseTime
        +  // 어택 시간, 감쇠 시간, 지속 속도, 릴리즈 시간 설정
           envelope.setADSR(0.001, 0.5, 0.1, 0.5);
         
        -  // set attackLevel, releaseLevel
        +  // 어택 레벨, 릴리즈 레벨 설정
           envelope.setRange(1, 0);
         
           osc.start();
        @@ -50,7 +48,7 @@ function draw() {
             note = (note + 1) % scaleArray.length;
           }
         
        -  // plot FFT.analyze() frequency analysis on the canvas
        +  // 캔버스에 FFT.analyze() 주파수 분석 내용 기입
           let spectrum = fft.analyze();
           for (let i = 0; i < spectrum.length / 20; i++) {
             fill(spectrum[i], spectrum[i] / 10, 0);
        diff --git a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        index 4737680b81..434bd0a2b1 100644
        --- a/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        +++ b/src/data/examples/ko/33_Sound/10_Oscillator_Waveform.js
        @@ -1,17 +1,16 @@
         /*
        - * @name Oscillator Frequency
        - * @description <p>Control an Oscillator and view the waveform using FFT.
        - * MouseX is mapped to frequency, mouseY is mapped to amplitude.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
        - * sound file.</span></em></p>
        + * @name 오실레이터 주파수
        + * @description <p>FFT를 사용하여 오실레이터를 제어하고 그 파형을 봅니다.
        + * MouseX는 주파수에, mouseY는 진폭에 매핑됩니다.</p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 됩니다.</span></em></p>
          */
         let osc, fft;
         
         function setup() {
           createCanvas(720, 256);
         
        -  osc = new p5.TriOsc(); // set frequency and type
        +  osc = new p5.TriOsc(); // 주파수와 종류 설정
           osc.amp(0.5);
         
           fft = new p5.FFT();
        @@ -21,7 +20,7 @@ function setup() {
         function draw() {
           background(255);
         
        -  let waveform = fft.waveform(); // analyze the waveform
        +  let waveform = fft.waveform(); // 파형 분석하기
           beginShape();
           strokeWeight(5);
           for (let i = 0; i < waveform.length; i++) {
        @@ -31,7 +30,7 @@ function draw() {
           }
           endShape();
         
        -  // change oscillator frequency based on mouseX
        +  // 오실레이터 주파수를 mouseX에 따라 변경
           let freq = map(mouseX, 0, width, 40, 880);
           osc.freq(freq);
         
        diff --git a/src/data/examples/ko/33_Sound/11_Live_Input.js b/src/data/examples/ko/33_Sound/11_Live_Input.js
        index 30136d62a0..dc3fefa8e4 100644
        --- a/src/data/examples/ko/33_Sound/11_Live_Input.js
        +++ b/src/data/examples/ko/33_Sound/11_Live_Input.js
        @@ -1,36 +1,33 @@
         /**
        - * @name Mic Input
        - * @description <p>Get audio input from your computer's microphone.
        - * Make noise to float the ellipse.</p>
        - * <p>Note: p5.AudioIn contains its own p5.Amplitude object,
        - * so you can call getLevel on p5.AudioIn without
        - * creating a p5.Amplitude.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        - */
        + * @name 마이크 입력
        + * @description <p>컴퓨터의 마이크를 통해 오디오 입력을 받습니다.
        + * 마이크에 소리를 내어 타원이 떠오르게 해보세요.</p>
        + * <p>주의: p5.AudioIn에는 p5.Amplitude 객체가 포함되어, 별도의
        + * p5.Amplitude를 생성하지 않고도 p5.AudioIn에서 getLevel을 호출할 수 있습니다.</p>
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p> */
         let mic;
         
         function setup() {
           createCanvas(710, 200);
         
        -  // Create an Audio input
        +  // 오디오 입력 생성하기
           mic = new p5.AudioIn();
         
        -  // start the Audio Input.
        -  // By default, it does not .connect() (to the computer speakers)
        +  // 오디오 입력 시작하기
        +  // 그 기본값은 .connect()(즉, 컴퓨터 스피커에 연결)되지 "않은" 상태입니다.
           mic.start();
         }
         
         function draw() {
           background(200);
         
        -  // Get the overall volume (between 0 and 1.0)
        +  // 전체 볼륨(0과 1.0 사이) 받아오기
           let vol = mic.getLevel();
           fill(127);
           stroke(0);
         
        -  // Draw an ellipse with height based on volume
        +  // 마이크 소리의 볼륨에 따라 떠있는 높이가 변하는 타원 그리기
           let h = map(vol, 0, 1, height, 0);
           ellipse(width / 2, h - 25, 50, 50);
         }
        diff --git a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        index 9bc8dedfd7..488985b5be 100644
        --- a/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        +++ b/src/data/examples/ko/33_Sound/12_FFT_Spectrum.js
        @@ -1,9 +1,9 @@
         /**
        - * @name Frequency Spectrum
        - * @description <p>Visualize the frequency spectrum of live audio input.</p>
        + * @name 주파수 스펙트럼
        + * @description <p>실시간 오디오 입력을 통해 주파수 스펙트럼을 시각화합니다.</p>
          * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let mic, fft;
         
        diff --git a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        index 4c765b059d..46e98c93d5 100644
        --- a/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        +++ b/src/data/examples/ko/33_Sound/13_Mic_Threshold.js
        @@ -1,12 +1,11 @@
         /**
        - * @name Mic Threshold
        - * @description <p>Trigger an event (draw a rectangle) when the Audio Input
        - * volume surpasses a threshold.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 마이크 임계값
        + * @description <p>입력된 오디오의 볼륨이 임계값을 초과하면
        + * 특정 이벤트(이 경우, 사각형 그리기)가 발생합니다.</p>
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
        -// Adapted from Learning Processing, Daniel Shiffman
        +// 다니엘 쉬프만(Daniel Shiffman)저 Learning Processing을 적용
         // learningprocessing.com
         let input;
         let analyzer;
        @@ -15,18 +14,18 @@ function setup() {
           createCanvas(710, 200);
           background(255);
         
        -  // Create an Audio input
        +  // 오디오 입력 생성하기
           input = new p5.AudioIn();
         
           input.start();
         }
         
         function draw() {
        -  // Get the overall volume (between 0 and 1.0)
        +  // 전체 볼륨(0과 1.0 사이) 받아오기
           let volume = input.getLevel();
         
        -  // If the volume > 0.1,  a rect is drawn at a random location.
        -  // The louder the volume, the larger the rectangle.
        +  // 만약 볼륨 > 0.1 이라면, 임의의 위치에 사각형 한 개가 그려집니다.
        +  // 볼륨이 커질수록, 사각형도 커집니다.
           let threshold = 0.1;
           if (volume > threshold) {
             stroke(0);
        @@ -34,14 +33,14 @@ function draw() {
             rect(random(40, width), random(height), volume * 50, volume * 50);
           }
         
        -  // Graph the overall potential volume, w/ a line at the threshold
        +  // 전체 볼륨 범위를 막대 그래프로 나타내고 임계값의 위치에는 선 하나 긋기
           let y = map(volume, 0, 1, height, 0);
           let ythreshold = map(threshold, 0, 1, height, 0);
         
           noStroke();
           fill(175);
           rect(0, 0, 20, height);
        -  // Then draw a rectangle on the graph, sized according to volume
        +  // 그 다음, 볼륨값을 보여주는 검정 사각형을 그래프 위에 그리기
           fill(0);
           rect(0, y, 20, y);
           stroke(0);
        diff --git a/src/data/examples/ko/33_Sound/14_Filter_LowPass.js b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js
        index d1337ed63e..8bf34f62ae 100644
        --- a/src/data/examples/ko/33_Sound/14_Filter_LowPass.js
        +++ b/src/data/examples/ko/33_Sound/14_Filter_LowPass.js
        @@ -1,4 +1,13 @@
         /**
        +<<<<<<< HEAD
        + *  @name 로우패스 필터
        + *  @description p5.SoundFile에 p5.LowPass 필터를 적용합니다.
        + *  FFT를 사용해 사운드를 시각화해보세요.
        + *  mouseX를 필터의 차단 주파수에, mouseY를 밴드패스 필터의 울림/폭에 맵핑합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        +=======
          *  @name Filter LowPass
          *  @description Apply a p5.LowPass filter to a p5.SoundFile.
          *  Visualize the sound with FFT.
        @@ -8,6 +17,7 @@
          * <p><em><span class="small"> To run this example locally, you will need the
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
          * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let soundFile;
         let fft;
        diff --git a/src/data/examples/ko/33_Sound/15_Filter_BandPass.js b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js
        index 5e128fcec1..818c6aa4ca 100644
        --- a/src/data/examples/ko/33_Sound/15_Filter_BandPass.js
        +++ b/src/data/examples/ko/33_Sound/15_Filter_BandPass.js
        @@ -1,4 +1,13 @@
         /**
        +<<<<<<< HEAD
        + *  @name 밴드패스 필터
        + *  @description 화이트 노이즈에 p5.BandPass 필터를 적용합니다.
        + *  FFT를 사용해 사운드를 시각화해보세요.
        + *  mouseX를 필터의 밴드패스(대역) 주파수에, mouseY를 밴드패스 필터의 울림/폭에 맵핑합니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        +=======
          *  @name Filter BandPass
          *  @description Apply a p5.BandPass filter to white noise.
          *  Visualize the sound with FFT.
        @@ -8,6 +17,7 @@
          * <p><em><span class="small"> To run this example locally, you will need the
          * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
          * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
          */
         let noise;
         let fft;
        @@ -21,8 +31,13 @@ function setup() {
         
           noise = new p5.Noise();
         
        +<<<<<<< HEAD
        +  noise.disconnect(); // 마스터 출력과 사운드 파일 연결 해제...
        +  filter.process(noise); // ...그리고 필터에 연결하여 밴드패스만 들리게하기
        +=======
           noise.disconnect(); // Disconnect soundfile from master output...
           filter.process(noise); // ...and connect to filter so we'll only hear BandPass.
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           noise.start();
         
           fft = new p5.FFT();
        @@ -31,6 +46,18 @@ function setup() {
         function draw() {
           background(30);
         
        +<<<<<<< HEAD
        +  // mouseX를 FFT 스펙트럼 범위(10Hz-22050Hz)에 해당하는 밴드패스 주파수에 맵핑하기
        +  filterFreq = map(mouseX, 0, width, 10, 22050);
        +  // mouseY를 울림/폭에 맵핑하기
        +  filterWidth = map(mouseY, 0, height, 0, 90);
        +  // 필터 매개 변수들 설정
        +  filter.set(filterFreq, filterWidth);
        +
        +  // FFT 스펙트럼 분석 중 x와 h가 아래와 같은 모든 값들 그리기:
        +  // x = 최저(10Hz)~최고(22050Hz) 주파수,
        +  // h = 해당 주파수에서의 에너지 / 진폭
        +=======
           // Map mouseX to a bandpass freq from the FFT spectrum range: 10Hz - 22050Hz
           filterFreq = map(mouseX, 0, width, 10, 22050);
           // Map mouseY to resonance/width
        @@ -41,6 +68,7 @@ function draw() {
           // Draw every value in the FFT spectrum analysis where
           // x = lowest (10Hz) to highest (22050Hz) frequencies,
           // h = energy / amplitude at that frequency
        +>>>>>>> cf3314557fcd084720a3cbca0fa45ce5ce151753
           let spectrum = fft.analyze();
           noStroke();
           for (let i = 0; i < spectrum.length; i++) {
        diff --git a/src/data/examples/ko/33_Sound/16_Delay.js b/src/data/examples/ko/33_Sound/16_Delay.js
        index 0027b42f73..f18120992f 100644
        --- a/src/data/examples/ko/33_Sound/16_Delay.js
        +++ b/src/data/examples/ko/33_Sound/16_Delay.js
        @@ -1,14 +1,14 @@
         /**
        - *  @name Delay
        + *  @name 딜레이 필터
          *  @description
        - *  Click the mouse to hear the p5.Delay process a SoundFile.
        - *  MouseX controls the p5.Delay Filter Frequency.
        - *  MouseY controls both the p5.Delay Time and Resonance.
        - *  Visualize the resulting sound's volume with an Amplitude object.
        + *  마우스를 클릭하여 p5.Delay로 처리된 사운드 파일을 들어보세요.
        + *  MouseX는 p5.Delay필터의 주파수를 조정합니다.
        + *  MouseY는 p5.Delay필터의 시간과 울림 정도를 조정합니다.
        + *  Amplitude(진폭) 객체로 출력된 사운드의 볼륨을 시각화해보세요.
          *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         
         let soundFile, analyzer, delay;
        @@ -21,11 +21,11 @@ function preload() {
         function setup() {
           createCanvas(710, 400);
         
        -  soundFile.disconnect(); // so we'll only hear delay
        +  soundFile.disconnect(); // 여기선 딜레이만 들을 수 있습니다.
         
           delay = new p5.Delay();
           delay.process(soundFile, 0.12, 0.7, 2300);
        -  delay.setType('pingPong'); // a stereo effect
        +  delay.setType('pingPong'); // 스테레오 효과
         
           analyzer = new p5.Amplitude();
         }
        @@ -33,10 +33,10 @@ function setup() {
         function draw() {
           background(0);
         
        -  // get volume reading from the p5.Amplitude analyzer
        +  // p5.Amplitude 분석 장치의 볼륨 판독 내용 받아오기
           let level = analyzer.getLevel();
         
        -  // use level to draw a green rectangle
        +  // 레벨을 사용하여 초록색 사각형 그리기
           let levelHeight = map(level, 0, 0.1, 0, height);
           fill(100, 250, 100);
           rect(0, height, width, -levelHeight);
        diff --git a/src/data/examples/ko/33_Sound/17_Reverb.js b/src/data/examples/ko/33_Sound/17_Reverb.js
        index db99aa3ed1..672383782b 100644
        --- a/src/data/examples/ko/33_Sound/17_Reverb.js
        +++ b/src/data/examples/ko/33_Sound/17_Reverb.js
        @@ -1,11 +1,12 @@
         /**
        - *  @name Reverb
        - *  @description Reverb gives depth and perceived space to a sound. Here,
        - *  noise is processed with reverb.
        +<<<<<<< HEAD
        + *  @name 리버브
        + *  @description 리버브(reverb)는 사운드에 깊이감과 공간감을 더합니다.
        + *  이 예제에서 노이즈는 reverb로 처리됩니다.
          *
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let sound, reverb;
         
        @@ -13,8 +14,8 @@ function preload() {
           soundFormats('mp3', 'ogg');
           soundFile = loadSound('assets/Damscray_DancingTiger');
         
        -  // disconnect the default connection
        -  // so that we only hear the sound via the reverb.process
        +  // 기본값으로 설정된 연결 상태를 해제하여
        +  // reverb.process를 통해서만 사운드를 들을 수 있도록 처리합니다.
           soundFile.disconnect();
         }
         
        @@ -24,11 +25,11 @@ function setup() {
         
           reverb = new p5.Reverb();
         
        -  // sonnects soundFile to reverb with a
        -  // reverbTime of 6 seconds, decayRate of 0.2%
        +  // 6초의 reverbTime(리버브 시간)과 0.2%의 decayRate(감쇠 속도)를 갖는
        +  // 리버브에 사운드 파일 연결하기 
           reverb.process(soundFile, 6, 0.2);
         
        -  reverb.amp(4); // turn it up!
        +  reverb.amp(4); // 턴잇업!
         }
         
         function mousePressed() {
        diff --git a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        index bfcfecb57e..51fa1b3416 100644
        --- a/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        +++ b/src/data/examples/ko/33_Sound/18_Convolution_Reverb.js
        @@ -1,38 +1,35 @@
         /**
        - * @name Convolution Reverb
        - * @description <p>The p5.Convolver can recreate the sound of actual
        - * spaces using convolution. Convolution takes an Impulse Response,
        - * (the sound of a room reverberating), and uses that to
        - * recreate the sound of that space.</p><p>Click to play a sound through
        - * convolution. Every time you click, the sound is convolved with
        - * a different Impulse Response. To hear the Impulse Response itself,
        - * press any key.</p>
        - *
        - * <p><em><span class="small">To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
        - * These convolution samples are Creative Commons BY
        - * <a href="https://www.freesound.org/people/recordinghopkins/">
        - * recordinghopkins</a></em></span></p>
        + * @name 컨볼루션 리버브
        + * @description <p>The p5.Convolver
        + * p5.Convolver는 컨볼루션을 사용하여 실제 공간 사운드를 재현합니다. 
        + * 컨볼루션은 임펄스 응답(즉, 반향하는 공간의 사운드)으로 해당 공간의 사운드를 재생성합니다.
        + * 컨볼루션으로 처리된 소리를 재생하려면 클릭하세요.
        + * 매번 클릭할 때마다, 서로 다른 임펄스 응답으로 재생성된 사운드를 들을 수 있습니다.
        + * 임펄스 응답만 재생하려면 아무 키나 누르세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
        + * 컨볼루션 샘플들은 <a href="https://www.freesound.org/people/recordinghopkins/">
        + * recordinghopkins</a>가 제작한 크리에이티브 커먼즈(CC)입니다.</span></p>
          */
         let sound, env, cVerb, fft;
         let currentIR = 0;
         let rawImpulse;
         
         function preload() {
        -  // we have included both MP3 and OGG versions of all the impulses/sounds
        +  // 모든 임펄스/사운드들의 MP3 및 OGG 버전을 이 스케치에 포함시킵니다.
           soundFormats('ogg', 'mp3');
         
        -  // create a p5.Convolver
        +  // p5.Convolver 생성하기
           cVerb = createConvolver('assets/bx-spring');
         
        -  // add Impulse Responses to cVerb.impulses array, in addition to bx-spring
        +  // bx-spring에 더해, cVerb.impulses 배열에 임펄스 응답 추가하기
           cVerb.addImpulse('assets/small-plate');
           cVerb.addImpulse('assets/drum');
           cVerb.addImpulse('assets/beatbox');
           cVerb.addImpulse('assets/concrete-tunnel');
         
        -  // load a sound that will be processed by the p5.ConvultionReverb
        +  // p5.ConvultionReverb로 처리될 사운드 불러오기 
           sound = loadSound('assets/Damscray_DancingTiger');
         }
         
        @@ -40,10 +37,10 @@ function setup() {
           createCanvas(710, 400);
           rawImpulse = loadSound('assets/' + cVerb.impulses[currentIR].name);
         
        -  // disconnect from master output...
        +  // 마스터 출력으로부터 연결 해제하고...
           sound.disconnect();
        -  // ... and process with cVerb
        -  // so that we only hear the reverb
        +  // ... cVerb로 처리하여
        +  // 오직 리버브만 들을 수 있도록 합니다.
           cVerb.process(sound);
         
           fft = new p5.FFT();
        @@ -55,7 +52,7 @@ function draw() {
         
           let spectrum = fft.analyze();
         
        -  // Draw every value in the frequencySpectrum array as a rectangle
        +  // frequencySpectrum 배열에 있는 모든 값들을 사각형으로 그리기
           noStroke();
           for (let i = 0; i < spectrum.length; i++) {
             let x = map(i, 0, spectrum.length, 0, width);
        @@ -65,23 +62,23 @@ function draw() {
         }
         
         function mousePressed() {
        -  // cycle through the array of cVerb.impulses
        +  // cVerb.impulses 배열 반복하기
           currentIR++;
           if (currentIR >= cVerb.impulses.length) {
             currentIR = 0;
           }
           cVerb.toggleImpulse(currentIR);
         
        -  // play the sound through the impulse
        +  // 임펄스를 거쳐 사운드 재생하기
           sound.play();
         
        -  // display the current Impulse Response name (the filepath)
        +  // 현재 임펄스 응답 이름 보이기(파일 경로)
           println('Convolution Impulse Response: ' + cVerb.impulses[currentIR].name);
         
           rawImpulse.setPath('assets/' + cVerb.impulses[currentIR].name);
         }
         
        -// play the impulse (without convolution)
        +// 임펄스 재생하기(컨볼루션 없이)
         function keyPressed() {
           rawImpulse.play();
         }
        diff --git a/src/data/examples/ko/33_Sound/19_Record_Save.js b/src/data/examples/ko/33_Sound/19_Record_Save.js
        index b44b7379a8..5d11d49f9b 100644
        --- a/src/data/examples/ko/33_Sound/19_Record_Save.js
        +++ b/src/data/examples/ko/33_Sound/19_Record_Save.js
        @@ -1,17 +1,16 @@
         /**
        - * @name Record Save Audio
        - * @description Record a sound, play it back and save
        - * it as a .wav file to the client's computer.
        - * We need three objects: a p5.AudioIn (mic / sound source),
        - * p5.SoundRecorder (records the sound), and a
        - * p5.SoundFile (play back / save).
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * a sound file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 오디오 녹음/저장
        + * @description 
        + * 사운드를 녹음하고 재생한 뒤, 클라이언트 컴퓨터에 .wav 파일로 저장하세요
        + * 이 예제에서는 총 세 개의 객체가 필요합니다: p5.AudioIn(마이크/사운드 소스),
        + * p5.SoundRecorder(사운드 녹음), 그리고 p5.SoundFile(재생/저장)
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면 적어도 한 개의 사운드 파일이 필요하고,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>를 추가해야 되며, 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">로컬 서버</a>를 작동시켜야 합니다.</span></em></p>
          */
         let mic, recorder, soundFile;
         
        -let state = 0; // mousePress will increment from Record, to Stop, to Play
        +let state = 0; // 마우스 버튼이 눌리면 녹음, 정지, 재생 순으로 상태가 변합니다.
         
         function setup() {
           createCanvas(400, 400);
        @@ -19,40 +18,40 @@ function setup() {
           fill(0);
           text('Enable mic and click the mouse to begin recording', 20, 20);
         
        -  // create an audio in
        +  // AudioIn 생성하기
           mic = new p5.AudioIn();
         
        -  // users must manually enable their browser microphone for recording to work properly!
        +  // 녹음 기능을 제대로 작동시키려면, 사용자가 브라우저 마이크를 수동으로 활성화해야 됩니다!
           mic.start();
         
        -  // create a sound recorder
        +  // 사운드 녹음기 생성하기
           recorder = new p5.SoundRecorder();
         
        -  // connect the mic to the recorder
        +  // 마이크를 녹음기에 연결
           recorder.setInput(mic);
         
        -  // create an empty sound file that we will use to playback the recording
        +  // 녹음된 사운드를 재생할 빈 사운드 파일 생성
           soundFile = new p5.SoundFile();
         }
         
         function mousePressed() {
        -  // use the '.enabled' boolean to make sure user enabled the mic (otherwise we'd record silence)
        +  // '.enabled' 불리언을 사용하여 사용자의 마이크 활성화 여부 확인(그렇지 않을 경우, 침묵 상태를 녹음하게 됩니다!)
           if (state === 0 && mic.enabled) {
        -    // Tell recorder to record to a p5.SoundFile which we will use for playback
        +    // p5.SoundFile에 녹음하라고 녹음기에 지시하기. 이 파일은 녹음 사운드를 재생하는 데에 쓰입니다.
             recorder.record(soundFile);
         
             background(255, 0, 0);
             text('Recording now! Click to stop.', 20, 20);
             state++;
           } else if (state === 1) {
        -    recorder.stop(); // stop recorder, and send the result to soundFile
        +    recorder.stop(); // 녹음기를 멈추고, 결과물을 soundFile에 보내기
         
             background(0, 255, 0);
             text('Recording stopped. Click to play & save', 20, 20);
             state++;
           } else if (state === 2) {
        -    soundFile.play(); // play the result!
        -    saveSound(soundFile, 'mySound.wav'); // save file
        +    soundFile.play(); // 결과물 재생하기!
        +    saveSound(soundFile, 'mySound.wav'); // 파일 저장하기
             state++;
           }
         }
        diff --git a/src/data/examples/ko/33_Sound/21_FreqModulation.js b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        index ab51e8bc61..27140d9a8f 100644
        --- a/src/data/examples/ko/33_Sound/21_FreqModulation.js
        +++ b/src/data/examples/ko/33_Sound/21_FreqModulation.js
        @@ -1,68 +1,62 @@
         /**
        - * @name Frequency Modulation
        - * @description <p>Frequency Modulation is a powerful form of synthesis.
        - * In its simplest form, FM involves two oscillators, referred
        - * to as the carrier and the modulator. As the modulator's waveform oscillates
        - * between some minimum and maximum amplitude value, that momentary value
        - * is added to ("modulates") the frequency of the carrier.</p>
        - * <p>The <b>carrier</b> is typically set to oscillate at an audible frequency
        - * that we perceive as a pitch—in this case, it is a sine wave oscilaltor at 220Hz,
        - * equivalent to an "A3" note. The carrier is connected to master output by default
        - * (this is the case for all p5.Oscillators).</p>
        - * <p>We will <code>disconnect</code> the <b>modulator</b> from master output,
        - * and instead connect to the frequency of the carrier:
        - * <code>carrier.freq(modulator)</code>. This adds the output amplitude of the
        - * modulator to the frequency of the carrier.</p>
        + * @name 주파수 변조(FM)
        + * @description <p> 주파수 변조(Frequancy Modulator, FM)는 강력한 합성 방식입니다.
        + * 아주 간단히 말하자면, FM은 반송파와 변조기라는 두 개의 오실레이터를 포함합니다.
        + * 변조기의 파형이 최소 및 최대 진폭 값 사이에서 진동하면, 그 순간의 값이 반송파 주파수에 추가(즉, "변조")됩니다</p>
        + * <p><b>반송파</b>는, 우리가 일반적으로 음고(pitch)라 부르는, 가청 주파수에서 진동합니다.
        + * 이 예제의 경우, "A3"음과 동일한 220Hz의 사인파 오실레이터입니다.
        + * 모든 p5.Oscillator들은 그 기본값으로 반송파가 마스터 출력에 연결되어 있습니다.
        + * <p>이 예제에서 우리는 <b>변조기</b>를 마스터 출력과 <code>연결 해제</code>하고,
        + * 대신 다음을 사용하여 반송파 주파수에 연결합니다: <code>carrier.freq(modulator)</code>.
        + * 이는 변조기의 출력 진폭을 반송파 주파수에 추가합니다.</p>
          * <p>
        - * <b>Modulation Depth</b> describes how much the carrier frequency will modulate.
        - * It is based on the amplitude of the modulator.
        - * The modulator produces a continuous stream of amplitude values that we will add
        - * to the carrier frequency. An amplitude of zero means silence, so the modulation will
        - * have no effect. An amplitude of 1.0 scales the range of output values
        - * between +1.0 and -1.0. That is the standard range for sound that gets sent to
        - * your speakers, but in FM we are instead sending the modulator's output to the carrier frequency,
        - * where we'd barely notice the +1Hz / -1Hz modulation.
        - * So we will typically increase the amplitude ("depth") of the modulator to numbers much higher than what
        - * we might send to our speakers.</p>
        - * <p><b>Modulation Frequency</b> is the speed of modulation. When the modulation frequency is lower
        - * than 20Hz, we stop hearing its frequency as pitch, and start to hear it as a beating rhythm.
        - * For example, try 7.5Hz at a depth of 20 to mimic the "vibrato" effect of an operatic vocalist.
        - * The term for this is Low Frequency Oscillator, or LFO. Modulators set to higher frequencies can
        - * also produce interesting effects, especially when the frequency has a harmonic relationship
        - * to the carrier signal. For example, listen to what happens when the modulator's frequency is
        - * half or twice that of the carrier. This is the basis for FM Synthesis, developed by John Chowning
        - * in the 1960s, which came to revolutionize synthesis in the 1980s and is often used to synthesize
        - * brass and bell-like sounds.
        + * <b>변조 깊이</b>는 반송파 주파수가 변조된 정도를 묘사합니다.
        + * 이는 변조기의 진폭을 기반으로 합니다.
        + * 변조기는 반송파 주파수에 추가될, 진폭 값들의 연속적인 스트림을 생성합니다. 
        + * 진폭이 0이면 묵음이 발생하므로 변조가 적용되지 않습니다. 
        + * 진폭이 1.0이면 출력값의 범위가 +1.0과 -1.0 사이로 조정됩니다.
        + * 이는 스피커로 전송되는 사운드의 표준 범위이기도 합니다.
        + * 하지만, FM에서는 변조기의 출력을 반송파 주파수로 전송하는데,
        + * 반송파 주파수에서는 + 1Hz / -1Hz 변조를 거의 찾아보기 힘듭니다. 
        + * 따라서, 변조기의 진폭("깊이")을 스피커로 보내는 값보다 훨씬 높은 숫자로 증가시키는 게 일반적입니다.</p>
        + * <p><b>변조 주파수</b>는 변조 속도를 나타냅니다.
        + * 변조 주파수가 20Hz보다 낮으면, 우리는 주파수를 음고가 아닌 비트와 리듬으로서 듣게 됩니다.
        + * 예를 들어, 오페라 보컬의 "비브라토" 효과를 따라하고자, 깊이 20에서 7.5Hz를 시도해보세요.
        + * 이를 위한 용어는 저주파수 오실레이터(Low Frequency Oscillator, LFO)입니다.
        + * 더 높은 주파수로 설정된 변조기는 여러가지 흥미로운 효과들을 만들 수 있습니다.
        + * 특히, 주파수가 반송파 신호와 화음을 이룰 경우 그렇습니다.
        + * 그 예로, 변조기의 주파수가 반송파 주파수의 절반 또는 두 배일 때 발생하는 사운드를 들어세요.
        + * 이는 존 차우닝(John Chowning)이 1960년대에 개발한 "FM 합성" 개념의 근간이기도 합니다.
        + * FM 합성은 1980년대에 이르러 사운드 합성을 변혁시킨 바 있으며, 놋쇠나 종소리를 합성하는 데에 자주 사용됩니다. *
          *
        - * <p>In this example,</p><p>
        - * - MouseX controls the modulation depth (the amplitude of the modulator) from -150 to 150.
        - * When the modulator's amplitude is set to 0 (in the middle), notice how the modulation
        - * has no effect. The greater (the absolute value of) the number, the greater the effect.
        - * If the modulator waveform is symetrical like a square <code>[]</code>, sine <code>~</code>
        - * or triangle <code>/\</code>, the negative amplitude will be the same as positive amplitude.
        - * But in this example, the modulator is an asymetrical sawtooth wave, shaped like this /.
        - * When we multiply it by a negative number, it goes backwards like this \. To best
        - * observe the difference, try lowering the frequency.
        + * <p>이 예제에서는,</p><p>
        + * - MouseX가 변조 깊이(즉, 변조기의 진폭)를 -150부터 150까지 조정합니다.
        + * 변조기 진폭이 0(즉, 가운데)으로 설정되면, 아무런 변조 효과가 발생하지 않습니다.
        + * 숫자의 절대값이 커질수록, 효과가 커집니다.
        + * 변조기 파형이 마치 사각형 <code>[]</code>, 싸인 <code>~</code>
        + * 또는 삼각형 <code>/\</code>과 같이 대칭일 경우, 음수의 진폭과 양수의 진폭은 동일합니다.
        + * 하지만 이 예제 속 변조기는 마치 이러한 모양 / 의 톱니처럼 생긴 비대칭적인 파형을 갖습니다.
        + * 여기에 음수를 곱하면, 파형이 마치 이러한 모양 \ 처럼 반대로 바뀝니다. 
        + * 그 차이를 명확히 관찰하려면, 주파수를 낮춰보세요.
          * </p>
        - * <p>- MouseY controls the frequency of the modulator from 0 to 112 Hz.
        - * Try comparing modulation frequencies below the audible range (which starts around 20hz),
        - * and above it, especially in a harmonic relationship to the carrier frequency (which is 220hz, so
        - * try half that, 1/3, 1/4 etc...).
        + * <p>- MouseY는 변조기의 주파수를 0부터 112Hz까지 조정합니다.
        + * 가청 범위(약 20hz에서 시작) 이하 및 이상 영역에서의 변조기 주파수를 비교해보세요.
        + * 특히, 반송파 주파수(220hz이므로 1/2, 1/3, 1/4 등으로 나눠보세요)와 화음을 이루는 상태에서요! *
          *
        - * <p><em><span class="small">You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * for this example to work in your own project.</em></span></p>
        + * <p><em><span class="small">로컬 프로젝트에서 이 예제를 실행하려면,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>
        + * 를 추가해야 됩니다.</em></span></p>
          */
         
        -let carrier; // this is the oscillator we will hear
        -let modulator; // this oscillator will modulate the frequency of the carrier
        +let carrier; // 이것이 바로 우리가 듣게될 오실레이터입니다.
        +let modulator; // 이 오실레이터가 반송파 주파수를 변조할 것입니다.
         
        -let analyzer; // we'll use this visualize the waveform
        +let analyzer; // 이것을 사용해 파형을 시각화합니다.
         
        -// the carrier frequency pre-modulation
        +// 반송파 주파수 사전 변조
         let carrierBaseFreq = 220;
         
        -// min/max ranges for modulator
        +// 변조기의 최저/최고 범위
         let modMaxFreq = 112;
         let modMinFreq = 0;
         let modMaxDepth = 150;
        @@ -73,42 +67,42 @@ function setup() {
           noFill();
         
           carrier = new p5.Oscillator('sine');
        -  carrier.amp(0); // set amplitude
        -  carrier.freq(carrierBaseFreq); // set frequency
        -  carrier.start(); // start oscillating
        +  carrier.amp(0); // 진폭 설정
        +  carrier.freq(carrierBaseFreq); // 주파수 설정
        +  carrier.start(); // 오실레이팅 시작
         
        -  // try changing the type to 'square', 'sine' or 'triangle'
        +  // 종류를 'square(사각형)', 'sine(싸인)' 또는 'triangle(삼각형)'으로 바꿔보세요!
           modulator = new p5.Oscillator('sawtooth');
           modulator.start();
         
        -  // add the modulator's output to modulate the carrier's frequency
        +  // 반송파 주파수를 변조하기 위해 변조기의 출력값 더하기
           modulator.disconnect();
           carrier.freq(modulator);
         
        -  // create an FFT to analyze the audio
        +  // 오디오 분석을 위해 FFT 생성하기
           analyzer = new p5.FFT();
         
        -  // fade carrier in/out on mouseover / touch start
        +  // 마우스 오버 / 스타트 터치 시, 반송파 페이드 인/아웃
           toggleAudio(cnv);
         }
         
         function draw() {
           background(30);
         
        -  // map mouseY to modulator freq between a maximum and minimum frequency
        +  // 최대 및 최소 주파수 사이의 변조기 주파수에 mouseY를 매핑하기
           let modFreq = map(mouseY, height, 0, modMinFreq, modMaxFreq);
           modulator.freq(modFreq);
         
        -  // change the amplitude of the modulator
        -  // negative amp reverses the sawtooth waveform, and sounds percussive
        +  // 변조기의 진폭 바꾸기
        +  // 음수의 amp는 톱니 파형을 반대로 뒤집고, 두드리는 듯한 사운드를 만듭니다.
           //
           let modDepth = map(mouseX, 0, width, modMinDepth, modMaxDepth);
           modulator.amp(modDepth);
         
        -  // analyze the waveform
        +  // 파형 분석하기
           waveform = analyzer.waveform();
         
        -  // draw the shape of the waveform
        +  // 파형 그리기
           stroke(255);
           strokeWeight(10);
           beginShape();
        @@ -120,7 +114,7 @@ function draw() {
           endShape();
         
           strokeWeight(1);
        -  // add a note about what's happening
        +  // 어떤 일이 일어나는 지에 대한 설명을 추가합니다.
           text('Modulator Frequency: ' + modFreq.toFixed(3) + ' Hz', 20, 20);
           text(
             'Modulator Amplitude (Modulation Depth): ' + modDepth.toFixed(3),
        @@ -134,7 +128,7 @@ function draw() {
           );
         }
         
        -// helper function to toggle sound
        +// 사운드 토글을 위한 helper 함수
         function toggleAudio(cnv) {
           cnv.mouseOver(function() {
             carrier.amp(1.0, 0.01);
        diff --git a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        index bc77cbd091..a45481d22d 100644
        --- a/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        +++ b/src/data/examples/ko/33_Sound/22_AmplitudeModulation.js
        @@ -1,76 +1,72 @@
         /**
        - * @name Amplitude Modulation
        - * @description <p>Amplitude Modulation involves two oscillators, referred
        - * to as the carrier and the modulator, where the modulator controls
        - * the carrier's amplitude.</p>
        + * @name 진폭 변조(AM)
        + * @description <p>진폭 변조(Amplitude Modulation, AM)은
        + * 반송파와 변조기라는 두 개의 오실레이터를 포함하고, 이는 반송파의 진폭을 조정합니다.</p>
          *
        - * <p>The carrier is typically set at an audible frequency (i.e. 440 Hz)
        - * and connected to master output by default. The carrier.amp is
        - * set to zero because we will have the modulator control its amplitude.</p>
        + * <p>반송파는 일반적으로 가청 주파수(예. 440Hz)에 설정됩니다.
        + * 그리고, 그 기본값으로 마스터 출력에 연결되어 있습니다.a
        + * carrier.amp는 0으로 설정되어 있는데, 이는 변조기로 진폭을 조정하기 위해서입니다.</p>
          *
        - * <p>The modulator is disconnected from master output. Instead, it is connected
        - * to the amplitude of the Carrier, like this: carrier.amp(modulator).</p>
        + * <p>이 예제에서 변조기는 마스터 출력과 연결이 해제되어 있습니다.
        + * 대신, 다음을 통해 반송파의 진폭에 연결되어 있습니다: carrier.amp(변조기).</p>
          *
        - * <p>In this example...</p>
        - * <p>- MouseX controls the amplitude of the modulator
        - * from 0 to 1. When the modulator's amplitude is set to 0, the
        - * amplitude modulation has no effect.</p>
        + * <p>이 예제에서는,</p>
        + * <p>- MouseX가 변조기의 진폭을 0부터 1까지 조정합니다.
        + * 변조기 진폭이 0으로 설정되면, 아무런 변조 효과가 발생하지 않습니다.</p>
          *
        - * <p>- MouseY controls the frequency of the modulator from 0 to 20hz.
        - * This range is lower frequencies than humans can hear, and we perceive the
        - * modulation as a rhythm. This range can simulate effects such as Tremolo.
        - * Ring Modulation is a type of Amplitude Modulation where the original
        - * carrier signal is not present, and often involves modulation at a faster
        - * frequency. </p>
        + * <p>- MouseY는 변조기의 주파수를 0부터 20hz까지 조정합니다.
        + * 이 범위는 인간이 들을 수 있는 주파수보다 낮으므로, 우리는 변조 사운드를 리듬으로서 듣게됩니다.
        + * 이 범위를 사용해 마치 풍금 소리와같은 효과를 만들 수 있습니다.
        + * 링 변조는 진폭 변조의 한 종류로, 원본 반송파 신호가 존재하지 않고, 더 빠른 주파수를 변조합니다.</p>
          *
        - * <p><em><span class="small">You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a>
        - * for this example to work in your own project.</em></span></p>
        + * <p><em><span class="small">로컬 프로젝트에서 이 예제를 실행하려면,
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound 라이브러리</a>
        + * 를 추가해야 됩니다.</em></span></p>
          */
        -let carrier; // this is the oscillator we will hear
        -let modulator; // this oscillator will modulate the amplitude of the carrier
        -let fft; // we'll visualize the waveform
        +let carrier; // 이것이 바로 우리가 듣게될 오실레이터입니다.
        +let modulator; // 이 오실레이터가 반송파 주파수를 변조할 것입니다.
        +let fft; // 이것을 사용해 파형을 시각화합니다.
         
         function setup() {
           createCanvas(800, 400);
           noFill();
        -  background(30); // alpha
        +  background(30); // 알파값
         
        -  carrier = new p5.Oscillator(); // connects to master output by default
        +  carrier = new p5.Oscillator(); // 기본값으로, 마스터 출력에 연결된 상태입니다.
           carrier.freq(340);
           carrier.amp(0);
        -  // carrier's amp is 0 by default, giving our modulator total control
        +  // 반송파의 amp는 기본값으로 0을 가져, 변조기에게 완전한 제어 권한을 부여합니다.
         
           carrier.start();
         
           modulator = new p5.Oscillator('triangle');
        -  modulator.disconnect(); // disconnect the modulator from master output
        +  modulator.disconnect(); // 변조기를 마스터 출력과 연결 해제합니다.
           modulator.freq(5);
           modulator.amp(1);
           modulator.start();
         
        -  // Modulate the carrier's amplitude with the modulator
        -  // Optionally, we can scale the signal.
        +  // 변조기를 사용해 반송파의 진폭을 변조하기
        +  // 추가적으로, 신호도 조정할 수 있습니다.
           carrier.amp(modulator.scale(-1, 1, 1, -1));
         
        -  // create an fft to analyze the audio
        +  // 오디오 분석을 위해 FFT 생성하기
           fft = new p5.FFT();
         }
         
         function draw() {
        -  background(30, 30, 30, 100); // alpha
        +  background(30, 30, 30, 100); // 알파값
         
        -  // map mouseY to moodulator freq between 0 and 20hz
        +  // 0과 20hz 사이의 변조기 주파수에 mouseY를 매핑하기
           let modFreq = map(mouseY, 0, height, 20, 0);
           modulator.freq(modFreq);
         
           let modAmp = map(mouseX, 0, width, 0, 1);
        -  modulator.amp(modAmp, 0.01); // fade time of 0.1 for smooth fading
        +  modulator.amp(modAmp, 0.01); // 페이드 타임을 0.1로 조정하여 페이딩을 부드럽게 만들기
         
        -  // analyze the waveform
        +  // 파형 분석하기
           waveform = fft.waveform();
         
        -  // draw the shape of the waveform
        +  // 파형 그리기
           drawWaveform();
         
           drawText(modFreq, modAmp);
        diff --git a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        index 0942148573..83902a3de1 100644
        --- a/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        +++ b/src/data/examples/ko/35_Mobile/00_Acceleration_Ball_Bounce.js
        @@ -1,17 +1,17 @@
         /*
        - * @name Acceleration Ball Bounce
        - * @description Move an ellipse around based on accelerationX and accelerationY values, and bounces when touch the edge of the canvas.
        + * @name 가속도와 바운스
        + * @description accelerationX와 accelerationY 값을 활용해 타원을 움직이고, 캔버스의 경계에 닿았을 때 튕기도록 만듭니다.
          */
         
        -// Position Variables
        +// 위치 변수들
         let x = 0;
         let y = 0;
         
        -// Speed - Velocity
        +// 속도 변수들
         let vx = 0;
         let vy = 0;
         
        -// Acceleration
        +// 가속 변수들
         let ax = 0;
         let ay = 0;
         
        @@ -38,7 +38,7 @@ function ballMove() {
           y = y + vy * vMultiplier;
           x = x + vx * vMultiplier;
         
        -  // Bounce when touch the edge of the canvas
        +  // 캔버스의 경계에 닿았을 때 튕기기
           if (x < 0) {
             x = 0;
             vx = -vx * bMultiplier;
        diff --git a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        index 80cddb8562..de4f128884 100644
        --- a/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        +++ b/src/data/examples/ko/35_Mobile/01_Simple_Draw.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Simple Draw
        - * @description Touch to draw on the screen using mouseX, mouseY, pmouseX, and pmouseY values.
        + * @name 간단한 드로잉
        + * @description mouseX, mouseY, pmouseX, pmouseY 값을 사용하여 스크린을 터치했을 때 그려지도록 합니다.
          */
         
         function setup() {
        diff --git a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        index a7183d1def..cecd1bed76 100644
        --- a/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        +++ b/src/data/examples/ko/35_Mobile/02_Acceleration_Color.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Acceleration Color
        - * @description Use deviceMoved() to detect when the device is rotated. The background RGB color values are mapped to accelerationX, accelerationY, and accelerationZ values.
        + * @name 가속도 색상
        + * @description deviceMoved()를 사용해 모바일 기기의 회전을 감지합니다. 배경의 RGB 색상값은 각각 accelerationX, accelerationY, accelerationZ 값에 매핑됩니다.
          */
         
         let r, g, b;
        diff --git a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        index 5d2880dbe7..404fae8810 100644
        --- a/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        +++ b/src/data/examples/ko/35_Mobile/03_Shake_Ball_Bounce.js
        @@ -1,7 +1,9 @@
         /*
        - * @name Shake Ball Bounce
        - * @description Create a Ball class, instantiate multiple objects, move it around the screen, and bounce when touch the edge of the canvas.
        - * Detect shake event based on total change in accelerationX and accelerationY and speed up or slow down objects based on detection.
        + * @name 흔들기와 바운스
        + * @description Ball 클래스를 생성하고 복수의 객체를 인스턴스화한 뒤, 화면 위에서 움직여보세요.
        + * 공이 캔버스의 경계에 닿으면 튕깁니다. 
        + * accelerationX와 accelerationY의 총 변화를 기반으로 흔들림을 감지하고,
        + * 그러한 감지를 기반으로 객체의 속도를 높이거나 줄입니다.
          */
         
         let balls = [];
        @@ -31,18 +33,18 @@ function draw() {
         }
         
         function checkForShake() {
        -  // Calculate total change in accelerationX and accelerationY
        +  // accelerationX와 accelerationY의 총 변화 계산
           accChangeX = abs(accelerationX - pAccelerationX);
           accChangeY = abs(accelerationY - pAccelerationY);
           accChangeT = accChangeX + accChangeY;
        -  // If shake
        +  // 만약 흔들린다면,
           if (accChangeT >= threshold) {
             for (let i = 0; i < balls.length; i++) {
               balls[i].shake();
               balls[i].turn();
             }
           }
        -  // If not shake
        +  // 만약 흔들리지 않는다면,
           else {
             for (let i = 0; i < balls.length; i++) {
               balls[i].stopShake();
        @@ -52,7 +54,7 @@ function checkForShake() {
           }
         }
         
        -// Ball class
        +// Ball 클래스
         class Ball {
           constructor() {
             this.x = random(width);
        @@ -70,7 +72,7 @@ class Ball {
             this.y += this.yspeed * this.direction;
           }
         
        -  // Bounce when touch the edge of the canvas
        +  // 캔버스 경계에 닿았을 때 공 튀기기
           turn() {
             if (this.x < 0) {
               this.x = 0;
        @@ -87,14 +89,14 @@ class Ball {
             }
           }
         
        -  // Add to xspeed and yspeed based on
        -  // the change in accelerationX value
        +  // accerlerationX 값의 변화를 기반으로
        +  // xspeed와 yspeed에 더하기
           shake() {
             this.xspeed += random(5, accChangeX / 3);
             this.yspeed += random(5, accChangeX / 3);
           }
         
        -  // Gradually slows down
        +  // 점점 느려지기
           stopShake() {
             if (this.xspeed > this.oxspeed) {
               this.xspeed -= 0.6;
        diff --git a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        index ea39b5414f..7479b4c77c 100644
        --- a/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        +++ b/src/data/examples/ko/35_Mobile/04_Tilted_3D_Box.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Tilted 3D Box
        - * @description Use mobile to tilt a box
        + * @name 기울어진 3D상자
        + * @description 모바일 기기를 이용해 상자를 기울게 만듭니다.
          */
         function setup() {
           createCanvas(displayWidth, displayHeight, WEBGL);
        diff --git a/src/data/examples/ko/90_Hello_P5/01_shapes.js b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        index 5196abef4a..308d10ed3e 100644
        --- a/src/data/examples/ko/90_Hello_P5/01_shapes.js
        +++ b/src/data/examples/ko/90_Hello_P5/01_shapes.js
        @@ -1,24 +1,24 @@
         /*
        - * @name Simple Shapes
        - * @description This examples includes a circle, square, triangle, and a flower.
        + * @name 간단한 도형들
        + * @description 이 예제는 원, 사각형, 삼각형, 그리고 꽃 모양을 포함합니다.
          */
         function setup() {
        -  // Create the canvas
        +  // 캔버스 만들기
           createCanvas(720, 400);
           background(200);
         
        -  // Set colors
        +  // 색상 설정하기
           fill(204, 101, 192, 127);
           stroke(127, 63, 120);
         
        -  // A rectangle
        +  // 사각형 한 개
           rect(40, 120, 120, 40);
        -  // An ellipse
        +  // 타원 한 개
           ellipse(240, 240, 80, 80);
        -  // A triangle
        +  // 삼각형 한 개
           triangle(300, 100, 320, 100, 310, 80);
         
        -  // A design for a simple flower
        +  // 간단한 꽃 그리기
           translate(580, 200);
           noStroke();
           for (let i = 0; i < 10; i ++) {
        diff --git a/src/data/examples/ko/90_Hello_P5/02_interactivity.js b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        index 2822149bcf..95c1733fec 100644
        --- a/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        +++ b/src/data/examples/ko/90_Hello_P5/02_interactivity.js
        @@ -1,18 +1,18 @@
         /*
        - * @name Interactivity 1
        + * @name 인터랙티비티 1
          * @frame 720,425
        - * @description The circle changes color when you click on it.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.
        - * </em></p>
        + * @description 원을 클릭하면 색상이 바뀝니다.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>.
        + * </em>를 추가해야 됩니다.</p>
          */
         
        -// for red, green, and blue color values
        +// 빨강(r), 초록(g), 파랑(b) 색상값들
         let r, g, b;
         
         function setup() {
           createCanvas(720, 400);
        -  // Pick colors randomly
        +  // 임의의 색상 고르기
           r = random(255);
           g = random(255);
           b = random(255);
        @@ -20,19 +20,19 @@ function setup() {
         
         function draw() {
           background(127);
        -  // Draw a circle
        +  // 원 그리기
           strokeWeight(2);
           stroke(r, g, b);
           fill(r, g, b, 127);
           ellipse(360, 200, 200, 200);
         }
         
        -// When the user clicks the mouse
        +// 사용자가 마우스를 클릭했을 때,
         function mousePressed() {
        -  // Check if mouse is inside the circle
        +  // 마우스가 원의 안쪽에 있는지 확인하기
           let d = dist(mouseX, mouseY, 360, 200);
           if (d < 100) {
        -    // Pick new random color values
        +    // 새로운 임의의 색상 고르기
             r = random(255);
             g = random(255);
             b = random(255);
        diff --git a/src/data/examples/ko/90_Hello_P5/03_interactivity.js b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        index 08af063d3b..6a64eec90a 100644
        --- a/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        +++ b/src/data/examples/ko/90_Hello_P5/03_interactivity.js
        @@ -1,20 +1,20 @@
         /*
        - * @name Interactivity 2
        + * @name 인터랙티비티 2
          * @frame 720,425
        - * @description The circle changes color when you move the slider.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
        + * @description 슬라이더를 움직이면 원의 색상이 바뀝니다.
        + * 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가해야 됩니다.
          */
         
        -// A HTML range slider
        +// HTML 범위 슬라이더
         let slider;
         
         function setup() {
           createCanvas(720, 400);
        -  // hue, saturation, and brightness
        +  // 색조(H), 채도(S), 밝기(B)
           colorMode(HSB, 255);
        -  // slider has a range between 0 and 255 with a starting value of 127
        +  // 슬라이더의 범위를 0부터 255까지로, 그 시작값을 127로 설정하기
           slider = createSlider(0, 255, 127);
         }
         
        @@ -22,7 +22,7 @@ function draw() {
           background(127);
           strokeWeight(2);
         
        -  // Set the hue according to the slider
        +  // 슬라이더에 따라 채도 설정하기
           stroke(slider.value(), 255, 255);
           fill(slider.value(), 255, 255, 127);
           ellipse(360, 200, 200, 200);
        diff --git a/src/data/examples/ko/90_Hello_P5/04_animate.js b/src/data/examples/ko/90_Hello_P5/04_animate.js
        index 7c87da3a24..f746dd15ea 100644
        --- a/src/data/examples/ko/90_Hello_P5/04_animate.js
        +++ b/src/data/examples/ko/90_Hello_P5/04_animate.js
        @@ -1,13 +1,13 @@
         /*
        - * @name Animation
        - * @description The circle moves.
        + * @name 애니메이션
        + * @description 원이 움직입니다.
          */
        -// Where is the circle
        +// 원의 위치를 알기 위해
         let x, y;
         
         function setup() {
           createCanvas(720, 400);
        -  // Starts in the middle
        +  // 화면 가운데에서 시작하기
           x = width / 2;
           y = height;
         }
        @@ -15,17 +15,17 @@ function setup() {
         function draw() {
           background(200);
           
        -  // Draw a circle
        +  // 원 그리기
           stroke(50);
           fill(100);
           ellipse(x, y, 24, 24);
           
        -  // Jiggling randomly on the horizontal axis
        +  // 가로축에서 무작위로 흔들리기
           x = x + random(-1, 1);
        -  // Moving up at a constant speed
        +  // 일정 속도로 위를 향해 움직이기
           y = y - 1;
           
        -  // Reset to the bottom
        +  // 화면 하단으로 리셋
           if (y < 0) {
             y = height;
           }
        diff --git a/src/data/examples/ko/90_Hello_P5/04_flocking.js b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        index 93c5cd6b2f..a5b5c9600b 100644
        --- a/src/data/examples/ko/90_Hello_P5/04_flocking.js
        +++ b/src/data/examples/ko/90_Hello_P5/04_flocking.js
        @@ -1,15 +1,16 @@
         /*
        - * @name Flocking
        - * @description Demonstration of <a href="http://www.red3d.com/cwr/">Craig Reynolds' "Flocking" behavior</a>.<br>
        - * (Rules: Cohesion, Separation, Alignment.)<br>
        - * From <a href="http://natureofcode.com">natureofcode.com</a>.
        + * @name 플로킹
        + * @description 크레이그 레이놀즈(Craig Reynolds)의
        + * <a href="http://www.red3d.com/cwr/">"군집(Flocking)" 행위</a>를 묘사합니다.<br>
        + * (규칙: 응집, 분리, 정렬)<br>
        + * (출처: <a href="http://natureofcode.com">natureofcode.com</a>).
          */
         let boids = [];
         
         function setup() {
           createCanvas(720, 400);
         
        -  // Add an initial set of boids into the system
        +  // 시스템에 초기 개체(boid) 더하기
           for (let i = 0; i < 100; i++) {
             boids[i] = new Boid(random(width), random(height));
           }
        @@ -17,22 +18,22 @@ function setup() {
         
         function draw() {
           background(51);
        -  // Run all the boids
        +  // 모든 개체 실행하기
           for (let i = 0; i < boids.length; i++) {
             boids[i].run(boids);
           }
         }
         
        -// Boid class
        -// Methods for Separation, Cohesion, Alignment added
        +// Boid 클래스
        +// Separation(분리), Cohesion(응집), Alignment(정렬)을 위한 메소드 추가하기
         class Boid {
           constructor(x, y) {
             this.acceleration = createVector(0, 0);
             this.velocity = p5.Vector.random2D();
             this.position = createVector(x, y);
             this.r = 3.0;
        -    this.maxspeed = 3;    // Maximum speed
        -    this.maxforce = 0.05; // Maximum steering force
        +    this.maxspeed = 3;    // 최고 속도
        +    this.maxforce = 0.05; // 최고 조타력
           }
         
           run(boids) {
        @@ -42,51 +43,51 @@ class Boid {
             this.render();
           }
           
        -  // Forces go into acceleration
        +  // Force는 acceleration에 담깁니다.
           applyForce(force) {
             this.acceleration.add(force);
           }
           
        -  // We accumulate a new acceleration each time based on three rules
        +  // 세 가지 규칙을 기반으로 새로운 accerlation(가속도)를 축적합니다.
           flock(boids) {
        -    let sep = this.separate(boids); // Separation
        -    let ali = this.align(boids);    // Alignment
        -    let coh = this.cohesion(boids); // Cohesion
        -    // Arbitrarily weight these forces
        +    let sep = this.separate(boids); // 분리
        +    let ali = this.align(boids);    // 정렬
        +    let coh = this.cohesion(boids); // 응집
        +    // 세 힘들을 임의로 가중하기
             sep.mult(2.5);
             ali.mult(1.0);
             coh.mult(1.0);
        -    // Add the force vectors to acceleration
        +    // 가속도에 force 벡터 더하기
             this.applyForce(sep);
             this.applyForce(ali);
             this.applyForce(coh);
           }
           
        -  // Method to update location
        +  // 위치 업데이트를 위한 메소드
           update() {
        -    // Update velocity
        +    // 속도 업데이트
             this.velocity.add(this.acceleration);
        -    // Limit speed
        +    // 속도 제한
             this.velocity.limit(this.maxspeed);
             this.position.add(this.velocity);
        -    // Reset acceleration to 0 each cycle
        +    // 매 사이클마다 acceleration을 0으로 리셋하기
             this.acceleration.mult(0);
           }
           
        -  // A method that calculates and applies a steering force towards a target
        -  // STEER = DESIRED MINUS VELOCITY
        +  // 목표점을 향한 조타력을 계산하고 적용하는 메소드
        +  // STEER(조타력) = DESIRED(목표점) - VELOCITY(속도)
           seek(target) {
             let desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
        -    // Normalize desired and scale to maximum speed
        +  // desired를 표준화하고 최대 속도로 조정
             desired.normalize();
             desired.mult(this.maxspeed);
             // Steering = Desired minus Velocity
             let steer = p5.Vector.sub(desired, this.velocity);
        -    steer.limit(this.maxforce); // Limit to maximum steering force
        +    steer.limit(this.maxforce); // 최대 조타력으로 제한
             return steer;
           }
           
        -  // Draw boid as a circle
        +  // 개체(boid)를 원형으로 그리기
           render() {
             fill(127, 127);
             stroke(200);
        @@ -101,33 +102,33 @@ class Boid {
             if (this.position.y > height + this.r) this.position.y = -this.r;
           }
           
        -  // Separation
        -  // Method checks for nearby boids and steers away
        +  // 분리 Seperation
        +  // 인근의 개체를 확인하고 이로부터 거리를 유지하며 조타하게 만드는 메소드
           separate(boids) {
             let desiredseparation = 25.0;
             let steer = createVector(0, 0);
             let count = 0;
        -    // For every boid in the system, check if it's too close
        +    // 매 개체가 시스템에 생성될 때마다, 서로 너무 가까운 위치에 있는지 여부를 확인
             for (let i = 0; i < boids.length; i++) {
               let d = p5.Vector.dist(this.position, boids[i].position);
        -      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
        +      // 만약 그 거리가 0보다 크고 임의의 값보다 작다면(0은 개체의 현위치)
               if ((d > 0) && (d < desiredseparation)) {
        -        // Calculate vector pointing away from neighbor
        +        // 인근의 개체로부터 떨어진 지점을 향하는 벡터 계산
                 let diff = p5.Vector.sub(this.position, boids[i].position);
                 diff.normalize();
        -        diff.div(d); // Weight by distance
        +        diff.div(d); // 거리에 따른 가중
                 steer.add(diff);
        -        count++; // Keep track of how many
        +        count++; // 개체수 카운트
               }
             }
        -    // Average -- divide by how many
        +    // 평균 -- 얼마로 나눌 것인가
             if (count > 0) {
               steer.div(count);
             }
           
        -    // As long as the vector is greater than 0
        +    // 벡터가 0보다 크다면,
             if (steer.mag() > 0) {
        -      // Implement Reynolds: Steering = Desired - Velocity
        +      // 레이놀즈의 공식 Steering = Desired - Velocity을 적용한다.
               steer.normalize();
               steer.mult(this.maxspeed);
               steer.sub(this.velocity);
        @@ -136,8 +137,8 @@ class Boid {
             return steer;
           }
           
        -  // Alignment
        -  // For every nearby boid in the system, calculate the average velocity
        +  // 배열 Alignment
        +  // 서로 인근에 있는 모든 개체에 대한 평균 속도 계산
           align(boids) {
             let neighbordist = 50;
             let sum = createVector(0, 0);
        @@ -161,22 +162,22 @@ class Boid {
             }
           }
           
        -  // Cohesion
        -  // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
        +  // 응집 Cohesion
        +  // 서로 인근에 있는 모든 개체의 평균 위치값(예: 중앙)에 대해, 이 지점을 향한 조타 벡터값 계산
           cohesion(boids) {
             let neighbordist = 50;
        -    let sum = createVector(0, 0); // Start with empty vector to accumulate all locations
        +    let sum = createVector(0, 0); // 빈 벡터값으로 시작하여 모든 위치들을 축적
             let count = 0;
             for (let i = 0; i < boids.length; i++) {
               let d = p5.Vector.dist(this.position, boids[i].position);
               if ((d > 0) && (d < neighbordist)) {
        -        sum.add(boids[i].position); // Add location
        +        sum.add(boids[i].position); // 위치 추가
                 count++;
               }
             }
             if (count > 0) {
               sum.div(count);
        -      return this.seek(sum); // Steer towards the location
        +      return this.seek(sum); // 해당 위치를 향해 조타
             } else {
               return createVector(0, 0);
             }
        diff --git a/src/data/examples/ko/90_Hello_P5/05_weather.js b/src/data/examples/ko/90_Hello_P5/05_weather.js
        index 321ce86acb..b415a3c4d7 100644
        --- a/src/data/examples/ko/90_Hello_P5/05_weather.js
        +++ b/src/data/examples/ko/90_Hello_P5/05_weather.js
        @@ -1,35 +1,35 @@
         /*
        - * @name Weather
        + * @name 날씨
          * @frame 720,280
        - * @description This example grabs JSON weather data from apixu.com.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
        + * @description 이 예제는 apixu.com로부터 JSON 날씨 데이터를 받아옵니다.
        + * 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom 라이브러리</a>
        + * 를 추가해야 됩니다.
         */
         
        -// A wind direction vector
        +// 풍향 벡터
         let wind;
        -// Circle position
        +// 원의 위치
         let position;
         
         function setup() {
           createCanvas(720, 200);
        -  // Request the data from apixu.com
        +  // apixu.com에 데이터 요청하기
           let url = 'https://api.apixu.com/v1/current.json?key=513d8003c8b348f1a2461629162106&q=NYC';
           loadJSON(url, gotWeather);
        -  // Circle starts in the middle
        +  // 화면의 가운데에서 원그리기 시작
           position = createVector(width/2, height/2);
        -  // wind starts as (0,0)
        +  // 바람은 (0,0)에서 시작
           wind = createVector();
         }
         
         function draw() {
           background(200);
         
        -  // This section draws an arrow pointing in the direction of wind
        +  // 이 섹션에서는 풍향을 나타내는 화살표를 그립니다.
           push();
           translate(32, height - 32);
        -  // Rotate by the wind's angle
        +  // 바람의 각도에 따라 회전하기
           rotate(wind.heading() + PI/2);
           noStroke();
           fill(255);
        @@ -44,7 +44,7 @@ function draw() {
           triangle(0, -18, -6, -10, 6, -10);
           pop();
           
        -  // Move in the wind's direction
        +  // 풍향에 따라 움직이기
           position.add(wind);
           
           stroke(0);
        @@ -59,15 +59,15 @@ function draw() {
         
         function gotWeather(weather) {
           
        -  // Get the angle (convert to radians)
        +  // 각도 받아오기 (래디언으로 변환)
           let angle = radians(Number(weather.current.wind_degree));
        -  // Get the wind speed
        +  // 풍속 받아오기
           let windmag = Number(weather.current.wind_mph);
           
        -  // Display as HTML elements
        +  // HTML요소로 화면에 보이기
           let temperatureDiv = createDiv(floor(weather.current.temp_f) + '&deg;');
           let windDiv = createDiv("WIND " + windmag + " <small>MPH</small>");
           
        -  // Make a vector
        +  // 벡터 생성하기
           wind = p5.Vector.fromAngle(angle);
         }
        diff --git a/src/data/examples/ko/90_Hello_P5/06_drawing.js b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        index 2450401328..db309cbd67 100644
        --- a/src/data/examples/ko/90_Hello_P5/06_drawing.js
        +++ b/src/data/examples/ko/90_Hello_P5/06_drawing.js
        @@ -1,15 +1,15 @@
         /*
        -* @name Drawing
        -* @description Generative painting program.
        +* @name 드로잉
        +* @description 제너레이티브 페인팅 프로그램입니다.
         */
         
        -// All the paths
        +// 모든 경로
         let paths = [];
        -// Are we painting?
        +// 지금 페인팅을 하고 있나요?
         let painting = false;
        -// How long until the next circle
        +// 다음 원까지 걸리는 시간
         let next = 0;
        -// Where are we now and where were we?
        +// 현재 및 이전 위치
         let current;
         let previous;
         
        @@ -22,36 +22,36 @@ function setup() {
         function draw() {
           background(200);
           
        -  // If it's time for a new point
        +  // 새로운 점을 만들어 봅시다.
           if (millis() > next && painting) {
         
        -    // Grab mouse position      
        +    // 마우스 위치 받아오기     
             current.x = mouseX;
             current.y = mouseY;
         
        -    // New particle's force is based on mouse movement
        +    // 새로운 파티클의 힘은 마우스의 움직임에 기반을 둡니다.
             let force = p5.Vector.sub(current, previous);
             force.mult(0.05);
         
        -    // Add new particle
        +    // 새로운 파티클 더하기
             paths[paths.length - 1].add(current, force);
             
        -    // Schedule next circle
        +    // 다음 원의 시간 정하기 
             next = millis() + random(100);
         
        -    // Store mouse values
        +    // 더 많은 마우스값 저장하기
             previous.x = current.x;
             previous.y = current.y;
           }
         
        -  // Draw all paths
        +  // 모든 경로 그리기
           for( let i = 0; i < paths.length; i++) {
             paths[i].update();
             paths[i].display();
           }
         }
         
        -// Start it up
        +// 시작하기
         function mousePressed() {
           next = 0;
           painting = true;
        @@ -60,12 +60,12 @@ function mousePressed() {
           paths.push(new Path());
         }
         
        -// Stop
        +// 정지
         function mouseReleased() {
           painting = false;
         }
         
        -// A Path is a list of particles
        +// Path(경로)는 파티클들의 목록입니다.
         class Path {
           constructor() {
             this.particles = [];
        @@ -73,25 +73,25 @@ class Path {
           }
         
           add(position, force) {
        -    // Add a new particle with a position, force, and hue
        +    // 새로운 파티클을 그 위치, 힘, 색조값과 함께 추가하기
             this.particles.push(new Particle(position, force, this.hue));
           }
           
        -  // Display plath
        +  // 파티클 길이 화면에 보이기
           update() {  
             for (let i = 0; i < this.particles.length; i++) {
               this.particles[i].update();
             }
           }  
           
        -  // Display plath
        +  // 파티클 길이 화면에 보이기
           display() {    
        -    // Loop through backwards
        +    // 뒤로 반복하기
             for (let i = this.particles.length - 1; i >= 0; i--) {
        -      // If we shold remove it
        +      // 만약 제거해야 된다면,
               if (this.particles[i].lifespan <= 0) {
                 this.particles.splice(i, 1);
        -      // Otherwise, display it
        +      // 그렇지 않다면, 화면에 보이기
               } else {
                 this.particles[i].display(this.particles[i+1]);
               }
        @@ -100,7 +100,7 @@ class Path {
           }  
         }
         
        -// Particles along the path
        +// 경로 위 파티클들
         class Particle {
           constructor(position, force, hue) {
             this.position = createVector(position.x, position.y);
        @@ -118,13 +118,13 @@ class Particle {
             this.lifespan--;
           }
         
        -  // Draw particle and connect it with a line
        -  // Draw a line to another
        +  // 파티클을 그리고 선으로 잇기
        +  // 다른 파티클을 향해 선그리기
           display(other) {
             stroke(0, this.lifespan);
             fill(0, this.lifespan/2);    
             ellipse(this.position.x,this.position.y, 8, 8);    
        -    // If we need to draw a line
        +    // 선을 그려야 한다면,
             if (other) {
               line(this.position.x, this.position.y, other.position.x, other.position.y);
             }
        diff --git a/src/data/examples/ko/90_Hello_P5/07_song.js b/src/data/examples/ko/90_Hello_P5/07_song.js
        index 5e4337b7c9..2c3bbd65ab 100644
        --- a/src/data/examples/ko/90_Hello_P5/07_song.js
        +++ b/src/data/examples/ko/90_Hello_P5/07_song.js
        @@ -1,15 +1,14 @@
         /*
        - * @name Song
        + * @name 노래
          * @frame 720, 430
        - * @description Play a song.
        - * You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound
        - * library</a> for this example to work in your own project.
        + * @description 노래를 재생하세요.
        + * <p><em><span class="small"> 로컬 프로젝트에서 이 예제를 실행하려면, 
        + * <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.Sound 라이브러리</a>.
        + * </em>를 추가해야 됩니다.</p>
          */
        -// The midi notes of a scale
        +// MIDI 음계의 음표들
         let notes = [ 60, 62, 64, 65, 67, 69, 71];
         
        -// For automatically playing the song
         let index = 0;
         let song = [
           { note: 4, duration: 400, display: "D" },
        @@ -31,7 +30,7 @@ function setup() {
           div.id("instructions");
           let button = createButton("play song automatically.");
           button.parent("instructions");
        -  // Trigger automatically playing
        +  // 자동 재생 트리거하기
           button.mousePressed(function() {
             if (!autoplay) {
               index = 0;
        @@ -39,20 +38,20 @@ function setup() {
             }
           });
         
        -  // A triangle oscillator
        +  // 삼각형 오실레이터
           osc = new p5.TriOsc();
        -  // Start silent
        +  // 무음 시작
           osc.start();
           osc.amp(0);
         }
         
        -// A function to play a note
        +// 음표를 재생하기 위한 함수
         function playNote(note, duration) {
           osc.freq(midiToFreq(note));
        -  // Fade it in
        +  // 음표를 페이드인하기
           osc.fade(0.5,0.2);
         
        -  // If we sest a duration, fade it out
        +  // 만약 재생 시간을 설정한다면, 페이드 아웃
           if (duration) {
             setTimeout(function() {
               osc.fade(0,0.2);
        @@ -62,30 +61,30 @@ function playNote(note, duration) {
         
         function draw() {
         
        -  // If we are autoplaying and it's time for the next note
        +  // 만약 현재 자동 재생 중이고 다음 음표를 재생할 때가 되었다면,
           if (autoplay && millis() > trigger){
             playNote(notes[song[index].note], song[index].duration);
             trigger = millis() + song[index].duration;
        -    // Move to the next note
        +    // 다음 음표로 이동하기
             index ++;
        -  // We're at the end, stop autoplaying.
        +  // 끝에 다다랐다면, 자동 재생 중지
           } else if (index >= song.length) {
             autoplay = false;
           }
         
         
        -  // Draw a keyboard
        +  // 키보드 그리기
         
        -  // The width for each key
        +  // 각 건반의 너비
           let w = width / notes.length;
           for (let i = 0; i < notes.length; i++) {
             let x = i * w;
        -    // If the mouse is over the key
        +    // 마우스가 건반 위에 있다면,
             if (mouseX > x && mouseX < x + w && mouseY < height) {
        -      // If we're clicking
        +      // 마우스를 클릭 중이라면,
               if (mouseIsPressed) {
                 fill(100,255,200);
        -      // Or just rolling over
        +      // 또는 마우스가 건반 위를 롤오버 중이라면,
               } else {
                 fill(127);
               }
        @@ -93,27 +92,27 @@ function draw() {
               fill(200);
             }
         
        -    // Or if we're playing the song, let's highlight it too
        +    // 또는, 노래가 재생 중이라면 하이라이트를 줍니다.  
             if (autoplay && i === song[index-1].note) {
               fill(100,255,200);
             }
         
        -    // Draw the key
        +    // 건반 그리기
             rect(x, 0, w-1, height-1);
           }
         
         }
         
        -// When we click
        +// 클릭하면,
         function mousePressed(event) {
           if(event.button == 0 && event.clientX < width && event.clientY < height) {
        -    // Map mouse to the key index
        +    // 건반 인덱스에 마우스를 매핑하기
             let key = floor(map(mouseX, 0, width, 0, notes.length));
             playNote(notes[key]);
           }
         }
         
        -// Fade it out when we release
        +// 마우스 버튼을 놓으면 페이드 아웃하기
         function mouseReleased() {
           osc.fade(0,0.5);
         }
        diff --git a/src/data/examples/zh-Hans/00_Structure/00_Coordinates.js b/src/data/examples/zh-Hans/00_Structure/00_Coordinates.js
        index 2325be60df..5c58c6200a 100644
        --- a/src/data/examples/zh-Hans/00_Structure/00_Coordinates.js
        +++ b/src/data/examples/zh-Hans/00_Structure/00_Coordinates.js
        @@ -1,6 +1,6 @@
         /*
          * @name 坐标
        - * @description 绘制到屏幕上的所有形状都有一个指定为坐标的位置。所有的坐标都是以像素为单位,以距原点的距离来衡量的。原点 [0,0] 是窗口左上角的坐标,右下角的坐标是 [宽度-, 高度-1] 。
        + * @description 绘制到屏幕上的所有形状都有一个指定为坐标的位置。所有的坐标都是以像素为单位,以距原点的距离来衡量的。原点 [0,0] 是窗口左上角的坐标,右下角的坐标是 [宽度-1, 高度-1] 。
          */
         function setup() {
           // 制作一个 720 像素宽 400 像素高的画布。
        diff --git a/src/data/examples/zh-Hans/05_Image/00_Load_and_Display_Image.js b/src/data/examples/zh-Hans/05_Image/00_Load_and_Display_Image.js
        index 9824b68d46..59b19f0c9e 100644
        --- a/src/data/examples/zh-Hans/05_Image/00_Load_and_Display_Image.js
        +++ b/src/data/examples/zh-Hans/05_Image/00_Load_and_Display_Image.js
        @@ -1,22 +1,20 @@
         /*
        - * @name Load and Display Image
        - * @description Images can be loaded and displayed to the screen at their
        - * actual size or any other size.
        - * <p><em><span class="small"> To run this example locally, you will need an 
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 加载(Load)和显示(Display)图像
        + * @description 图像可以以原图大小或自定义大小被加载和显示。
        + * <p><em><span class="small">要在本地运行此范例,您需要一个图像文件,并运行在<a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器</a>上。</span></em></p>
         
          */
        -let img; // Declare variable 'img'.
        +let img; // 声明变量 'img'
         
         function setup() {
           createCanvas(720, 400);
        -  img = loadImage('assets/moonwalk.jpg'); // Load the image
        +  img = loadImage('assets/moonwalk.jpg'); // 加载图像
         }
         
         function draw() {
        -  // Displays the image at its actual size at point (0,0)
        +  // 在坐标(0, 0),显示原图大小的图像 
           image(img, 0, 0);
        -  // Displays the image at point (0, height/2) at half size
        +  // 在坐标(0, 高度/2),显示一半原图大小的图像
           image(img, 0, height / 2, img.width / 2, img.height / 2);
         }
        diff --git a/src/data/examples/zh-Hans/05_Image/01_Background_Image.js b/src/data/examples/zh-Hans/05_Image/01_Background_Image.js
        index 80a63e461a..56961d73b8 100644
        --- a/src/data/examples/zh-Hans/05_Image/01_Background_Image.js
        +++ b/src/data/examples/zh-Hans/05_Image/01_Background_Image.js
        @@ -1,19 +1,16 @@
         /*
        - * @name Background Image
        - * @description This example presents the fastest way to load a
        - * background image. To load an image as the background,
        - * it must be the same width and height as the program.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 背景图像
        + * @description 此范例展示了最快加载背景图像的方法。
        + * 若需将一张图像作为背景,它必须和程序有相同的宽度和高度。
        + * <p><em><span class="small">要在本地运行此示例,您需要一个图像文件,并运行在<a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器</a>上。</span></em></p>
          */
         let bg;
         let y = 0;
         
         function setup() {
        -  // The background image must be the same size as the parameters
        -  // into the createCanvas() method. In this program, the size of
        -  // the image is 720x400 pixels.
        +  // 背景图像的大小必须和 createCanvas() 函数中的参数一样。
        +  // 该图像大小为 720x400 像素。
           bg = loadImage('assets/moonwalk.jpg');
           createCanvas(720, 400);
         }
        diff --git a/src/data/examples/zh-Hans/05_Image/02_Transparency.js b/src/data/examples/zh-Hans/05_Image/02_Transparency.js
        index 39cb96bb6a..db8141aa46 100644
        --- a/src/data/examples/zh-Hans/05_Image/02_Transparency.js
        +++ b/src/data/examples/zh-Hans/05_Image/02_Transparency.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Transparency
        - * @description Move the pointer left and right across the image to change its
        - * position. This program overlays one image over another by modifying the
        - * alpha value of the image with the tint() function.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 透明度
        + * @description 左右移动指针(光标)来改变图像位置
        + * 此程序为一张图像叠加在另一张上,通过tint() 函数来改变它的透明度值(alpha value)。
        + * <p><em><span class="small">要在本地运行此范例,您需要一个图像文件,并运行在<a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器</a>上。</span></em></p>
          */
         let img;
         let offset = 0;
        @@ -13,13 +11,13 @@ let easing = 0.05;
         
         function setup() {
           createCanvas(720, 400);
        -  img = loadImage('assets/moonwalk.jpg'); // Load an image into the program
        +  img = loadImage('assets/moonwalk.jpg'); // 加载图像
         }
         
         function draw() {
        -  image(img, 0, 0); // Display at full opacity
        +  image(img, 0, 0); // 完全不透明
           let dx = mouseX - img.width / 2 - offset;
           offset += dx * easing;
        -  tint(255, 127); // Display at half opacity
        +  tint(255, 127); // 半透明
           image(img, offset, 0);
         }
        diff --git a/src/data/examples/zh-Hans/05_Image/03_Alpha_Mask.js b/src/data/examples/zh-Hans/05_Image/03_Alpha_Mask.js
        index 0e57e3533c..6e9f5ab201 100644
        --- a/src/data/examples/zh-Hans/05_Image/03_Alpha_Mask.js
        +++ b/src/data/examples/zh-Hans/05_Image/03_Alpha_Mask.js
        @@ -1,22 +1,22 @@
         /*
        - * @name Alpha Mask
        - * @description Loads a "mask" for an image to specify the transparency in
        - * different parts of the image. The two images are blended together using
        - * the mask() method of p5.Image.
        - * <p><em><span class="small"> To run this example locally, you will need two
        - * image files, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 透明度遮罩 (Alpha Mask)
        + * @description 在图像上加载一个遮罩来改变图像中不同位置的透明度。
        + * 通过拍p5.Image 中的mask() 函数来混合两张图像(图像和遮罩)。
        + * <p><em><span class="small">要在本地运行此范例,您需要一个图像文件,并运行在<a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器</a>上。</span></em></p>
          */
         let img;
         let imgMask;
         
         function preload() {
        +  // 加载图像及图像遮罩
           img = loadImage('assets/moonwalk.jpg');
           imgMask = loadImage('assets/mask.png');
         }
         
         function setup() {
           createCanvas(720, 400);
        +  // mask() 函数将图像遮罩覆盖在图像上
           img.mask(imgMask);
           imageMode(CENTER);
         }
        diff --git a/src/data/examples/zh-Hans/05_Image/04_Create_Image.js b/src/data/examples/zh-Hans/05_Image/04_Create_Image.js
        index 481f4b0ce4..f9e6a1ee0e 100644
        --- a/src/data/examples/zh-Hans/05_Image/04_Create_Image.js
        +++ b/src/data/examples/zh-Hans/05_Image/04_Create_Image.js
        @@ -1,20 +1,25 @@
         /*
        - * @name Create Image
        - * @description The createImage() function provides a fresh buffer of pixels to
        - * play with. This example creates an image gradient.
        + * @name 创建图像
        + * @description createImage() 函数能让我们巧妙地操控一个像素缓冲区。 此范例创建了一个渐变图像。
          */
        -let img; // Declare variable 'img'.
        +let img; // 声明变量 'img'
         
         function setup() {
           createCanvas(720, 400);
        +  // 设置图像大小 230x230 像素
           img = createImage(230, 230);
        +
        +  // 将显示窗口的像素资料加载到 pixels[] 数组里
        +  // 这函数必须在读写 pixels[] 之前被调用
           img.loadPixels();
           for (let x = 0; x < img.width; x++) {
             for (let y = 0; y < img.height; y++) {
               let a = map(y, 0, img.height, 255, 0);
        +      // 使用 set() 设置该位置像素的颜色
               img.set(x, y, [0, 153, 204, a]);
             }
           }
        +  // 使用 set() 后,必须调用updatePixels() 以使改变生效
           img.updatePixels();
         }
         
        diff --git a/src/data/examples/zh-Hans/05_Image/05_Pointillism.js b/src/data/examples/zh-Hans/05_Image/05_Pointillism.js
        index e256756c9e..3e524f4276 100644
        --- a/src/data/examples/zh-Hans/05_Image/05_Pointillism.js
        +++ b/src/data/examples/zh-Hans/05_Image/05_Pointillism.js
        @@ -1,34 +1,43 @@
         /*
        - * @name Pointillism
        - * @description By Dan Shiffman. Mouse horizontal location controls size of
        - * dots. Creates a simple pointillist effect using ellipses colored according
        - * to pixels in an image.
        - * <p><em><span class="small"> To run this example locally, you will need an
        - * image file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">
        - * local server</a>.</span></em></p>
        + * @name 点画(Pointillism)
        + * @description 作者:Dan Shiffman。
        + * 鼠标水平位置控制点的大小,由左到右对应由小到大的点。
        + * 通过带有原图像素颜色的椭圆创建出一副简单的点画。
        + * <p><em><span class="small">要在本地运行此范例,您需要一个图像文件,并运行在<a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器</a>上。</span></em></p>
          */
        +// 声明变量 'img', 'smallPoint', 'largePoing'
         let img;
         let smallPoint, largePoint;
         
         function preload() {
        +  // 加载图像
           img = loadImage('assets/moonwalk.jpg');
         }
         
         function setup() {
           createCanvas(720, 400);
        +  // 设置最小点宽度为 4,最大点宽度为 40
           smallPoint = 4;
           largePoint = 40;
           imageMode(CENTER);
           noStroke();
        +  // 设置背景颜色为白色
           background(255);
           img.loadPixels();
         }
         
         function draw() {
        +  // map() 函数根据鼠标水平位置,
        +  // 将其在 [0, 画布宽度] 的数值对应到 [最小点宽度, 最大点宽度] ([4,40]) 之中,
        +  // 对应的数值即为点的大小
           let pointillize = map(mouseX, 0, width, smallPoint, largePoint);
        +  // 随机生成坐标 (x, y)
           let x = floor(random(img.width));
           let y = floor(random(img.height));
        +  // 得到图像中坐标 (x, y) 的颜色
           let pix = img.get(x, y);
        +  // fill(灰度值,透明度值)
           fill(pix, 128);
           ellipse(x, y, pointillize, pointillize);
         }
        diff --git a/src/data/examples/zh-Hans/07_Color/00_Hue.js b/src/data/examples/zh-Hans/07_Color/00_Hue.js
        index bb1e02ed95..68cc84c57c 100644
        --- a/src/data/examples/zh-Hans/07_Color/00_Hue.js
        +++ b/src/data/examples/zh-Hans/07_Color/00_Hue.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Hue
        - * @description Hue is the color reflected from or transmitted through an
        - * object and is typically referred to as the name of the color (red, blue,
        - * yellow, etc.) Move the cursor vertically over each bar to alter its hue.
        + * @name 色调
        + * @description 色调是从物件反射或透过物件传播得到的颜色,
        + * 通常指颜色的名字(红色,蓝色,黄色等)。
        + * 将光标在每个条形上垂直移动以更改其色调。
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/zh-Hans/07_Color/01_Saturation.js b/src/data/examples/zh-Hans/07_Color/01_Saturation.js
        index 7394cf7dbf..da8c42c364 100644
        --- a/src/data/examples/zh-Hans/07_Color/01_Saturation.js
        +++ b/src/data/examples/zh-Hans/07_Color/01_Saturation.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Saturation
        - * @description Saturation is the strength or purity of the color and
        - * represents the amount of gray in proportion to the hue. A "saturated"
        - * color is pure and an "unsaturated" color has a large percentage of gray.
        - * Move the cursor vertically over each bar to alter its saturation.
        + * @name 饱和度
        + * @description 饱和度是颜色的强度或者纯度,代表与色调成比例的灰色量。
        + * “饱和”的颜色是纯色;“不饱和”的颜色含有很大比例的灰色。
        + * 将光标在每个条形上垂直移动以更改其饱和度。
          */
         const barWidth = 20;
         let lastBar = -1;
        diff --git a/src/data/examples/zh-Hans/07_Color/02_Brightness.js b/src/data/examples/zh-Hans/07_Color/02_Brightness.js
        index 17f29af7f2..41a66e8ad9 100644
        --- a/src/data/examples/zh-Hans/07_Color/02_Brightness.js
        +++ b/src/data/examples/zh-Hans/07_Color/02_Brightness.js
        @@ -1,9 +1,11 @@
         /*
        - * @name Brightness
        - * @description By Dan Shiffman. This program adjusts the brightness of a part
        - * of the image by calculating the distance of each pixel to the mouse.
        - * <p><em><span class="small"> To run this example locally, you will need
        - * at least an image file and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @name 亮度
        + * @description 作者 Dan Shiffman。
        + * 此程序通过计算每个像素距离光标的距离调整图像的局部亮度。
        + * <p><em><span class="small">
        + * 要在本地运行此范例,您需要至少一个图像文件,并运行在
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">
        + * 本地伺服器 </a>上。</span></em></p>
          */
         let img;
         
        @@ -21,19 +23,19 @@ function setup() {
         function draw() {
           for (let x = 0; x < img.width; x++) {
             for (let y = 0; y < img.height; y++) {
        -      // Calculate the 1D location from a 2D grid
        +      // 通过 2D 网格计算1D位置
               let loc = (x + y * img.width) * 4;
        -      // Get the R,G,B values from image
        +      // 从图像里获取 R,G,B 数值
               let r, g, b;
               r = img.pixels[loc];
        -      // Calculate an amount to change brightness based on proximity to the mouse
        +      // 根据距离光标的距离计算亮度改变的量
               let maxdist = 50;
               let d = dist(x, y, mouseX, mouseY);
               let adjustbrightness = (255 * (maxdist - d)) / maxdist;
               r += adjustbrightness;
        -      // Constrain RGB to make sure they are within 0-255 color range
        +      // 限制 RGB 以确保它们在 0-255 的颜色范围内
               r = constrain(r, 0, 255);
        -      // Make a new color and set pixel in the window
        +      // 创建一个新颜色,并在窗口里设置像素
               //color c = color(r, g, b);
               let pixloc = (y * width + x) * 4;
               pixels[pixloc] = r;
        diff --git a/src/data/examples/zh-Hans/07_Color/03_Color_Variables.js b/src/data/examples/zh-Hans/07_Color/03_Color_Variables.js
        index 2151681561..25d8149693 100644
        --- a/src/data/examples/zh-Hans/07_Color/03_Color_Variables.js
        +++ b/src/data/examples/zh-Hans/07_Color/03_Color_Variables.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Color Variables
        - * @description (Homage to Albers.) This example creates variables for colors
        - * that may be referred to in the program by a name, rather than a number.
        + * @name 颜色变量
        + * @description (向 Albers 致敬。) 此范例为颜色们建立了变量。
        + * 这样它们可以在程序中以名字指代,而非数字。
          */
         function setup() {
           createCanvas(710, 400);
        @@ -12,8 +12,8 @@ function setup() {
           let middle = color(204, 153, 0);
           let outside = color(153, 51, 0);
         
        -  // These statements are equivalent to the statements above.
        -  // Programmers may use the format they prefer.
        +  // 以下语句与上面的语句等效。
        +  // 程序员可以选择他们喜欢的格式。
           //let inside = color('#CC6600');
           //let middle = color('#CC9900');
           //let outside = color('#993300');
        diff --git a/src/data/examples/zh-Hans/07_Color/04_Relativity.js b/src/data/examples/zh-Hans/07_Color/04_Relativity.js
        index 010ef7489f..ea4a4f9fc6 100644
        --- a/src/data/examples/zh-Hans/07_Color/04_Relativity.js
        +++ b/src/data/examples/zh-Hans/07_Color/04_Relativity.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Relativity
        - * @description Each color is perceived in relation to other colors. The top
        - * and bottom bars each contain the same component colors, but a different
        - * display order causes individual colors to appear differently.
        + * @name 相对性
        + * @description 我们对每个颜色的感知都是相对于其他颜色而言的。
        + * 上半部分和下半部分的条形具有相同的颜色构成,但是他们呈现每个颜色的顺序不同,
        + * 让同一个颜色看起来也不一样。
          */
         let a, b, c, d, e;
         
        @@ -14,7 +14,7 @@ function setup() {
           c = color(42, 106, 105);
           d = color(165, 89, 20);
           e = color(146, 150, 127);
        -  noLoop(); // Draw only one time
        +  noLoop(); // 只画一次
         }
         
         function draw() {
        diff --git a/src/data/examples/zh-Hans/07_Color/05_Linear_Gradient.js b/src/data/examples/zh-Hans/07_Color/05_Linear_Gradient.js
        index a99dcbbdf7..2593d790c2 100644
        --- a/src/data/examples/zh-Hans/07_Color/05_Linear_Gradient.js
        +++ b/src/data/examples/zh-Hans/07_Color/05_Linear_Gradient.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Linear Gradient
        - * @description The lerpColor() function is useful for interpolating between
        - * two colors.
        + * @name 线性渐变
        + * @description lerpColor() 函数可用于在两个颜色之间插值。
          */
        -// Constants
        +// 常量
         const Y_AXIS = 1;
         const X_AXIS = 2;
         let b1, b2, c1, c2;
        @@ -11,7 +10,7 @@ let b1, b2, c1, c2;
         function setup() {
           createCanvas(710, 400);
         
        -  // Define colors
        +  // 定义颜色
           b1 = color(255);
           b2 = color(0);
           c1 = color(204, 102, 0);
        @@ -21,10 +20,10 @@ function setup() {
         }
         
         function draw() {
        -  // Background
        +  // 背景
           setGradient(0, 0, width / 2, height, b1, b2, X_AXIS);
           setGradient(width / 2, 0, width / 2, height, b2, b1, X_AXIS);
        -  // Foreground
        +  // 前景
           setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
           setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
         }
        @@ -33,7 +32,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
           noFill();
         
           if (axis === Y_AXIS) {
        -    // Top to bottom gradient
        +    // 从上到下的渐变
             for (let i = y; i <= y + h; i++) {
               let inter = map(i, y, y + h, 0, 1);
               let c = lerpColor(c1, c2, inter);
        @@ -41,7 +40,7 @@ function setGradient(x, y, w, h, c1, c2, axis) {
               line(x, i, x + w, i);
             }
           } else if (axis === X_AXIS) {
        -    // Left to right gradient
        +    // 从左到右的渐变
             for (let i = x; i <= x + w; i++) {
               let inter = map(i, x, x + w, 0, 1);
               let c = lerpColor(c1, c2, inter);
        diff --git a/src/data/examples/zh-Hans/07_Color/06_Radial_Gradient.js b/src/data/examples/zh-Hans/07_Color/06_Radial_Gradient.js
        index 51e1f37404..bde099a6ff 100644
        --- a/src/data/examples/zh-Hans/07_Color/06_Radial_Gradient.js
        +++ b/src/data/examples/zh-Hans/07_Color/06_Radial_Gradient.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Radial Gradient
        - * @description Draws a series of concentric circles to create a gradient
        - * from one color to another.
        + * @name 径向渐变
        + * @description 绘制一系列同心圆,创造出从一个颜色到另一个颜色到渐变效果。
          */
         let dim;
         
        diff --git a/src/data/examples/zh-Hans/07_Color/07_Lerp_Color.js b/src/data/examples/zh-Hans/07_Color/07_Lerp_Color.js
        index 471a2df17e..2cbb6ffc8d 100644
        --- a/src/data/examples/zh-Hans/07_Color/07_Lerp_Color.js
        +++ b/src/data/examples/zh-Hans/07_Color/07_Lerp_Color.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Lerp Color
        - * @description Loop random shapes,
        - * lerp color from red to blue.
        + * @name 插值颜色
        + * @description 随机循环形状,颜色从红色到蓝色。
          */
         function setup() {
           createCanvas(720, 400);
        diff --git a/src/data/examples/zh-Hans/08_Math/00_incrementdecrement.js b/src/data/examples/zh-Hans/08_Math/00_incrementdecrement.js
        index 026f146769..abf5b039ff 100644
        --- a/src/data/examples/zh-Hans/08_Math/00_incrementdecrement.js
        +++ b/src/data/examples/zh-Hans/08_Math/00_incrementdecrement.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Increment Decrement
        - * @description Writing "a++" is equivalent to "a = a + 1".
        - * Writing "a--" is equivalent to "a = a - 1".
        + * @name 增量/减量
        + * @description "a++" 等于 "a = a + 1"。 "a--" 等于 "a = a - 1"。
          */
         let a;
         let b;
        diff --git a/src/data/examples/zh-Hans/08_Math/01_operatorprecedence.js b/src/data/examples/zh-Hans/08_Math/01_operatorprecedence.js
        index 175054f692..57fd22bf21 100644
        --- a/src/data/examples/zh-Hans/08_Math/01_operatorprecedence.js
        +++ b/src/data/examples/zh-Hans/08_Math/01_operatorprecedence.js
        @@ -1,24 +1,20 @@
         /*
        - * @name Operator Precedence
        - * @description If you don't explicitly state the order in which an
        - * expression is evaluated, they are evaluated based on the operator
        - * precedence. For example, in the statement "4+2*8", the 2 will
        - * first be multiplied by 8 and then the result will be added to 4.
        - * This is because the "*" has a higher precedence than the "+". To avoid
        - * ambiguity in reading the program, it is recommended that is statement
        - * is written as "4+(2*8)". The order of evaluation can be controlled
        - * through placement of parenthesis in the code. A table of operator
        - * precedence follows below.
        + * @name 操作符优先级
        + * @description 如果没有明确地指明表达式求值的次序,表达式将根据操作符的优先级来求值。
        + * 例如,在 "4+2*8" 的语句中, 2 会先乘 8,其结果再加上 4。
        + * 这是因为 "*" 的优先级比 "+" 的高。
        + * 为了避免读取程序时的模凌两可,建议将该语句写成 "4+(2*8)"。
        + * 在代码中加上括号可以控制求值的次序。
        + * 以下是操作符优先级列表。
          */
        -// The highest precedence is at the top of the list and
        -// the lowest is at the bottom.
        -// Multiplicative: * / %
        -// Additive: + -
        -// Relational: < > <= >=
        -// Equality: == !=
        -// Logical AND: &&
        -// Logical OR: ||
        -// Assignment: = += -= *= /= %=
        +// 最高级(最先执行)的位于列表上方,最低级(最后执行)的位于下方。
        +// 乘法: * / %
        +// 加法: + -
        +// 比较: < > <= >=
        +// 相等: == !=
        +// 逻辑与 (AND): &&
        +// 逻辑或 (OR): ||
        +// 赋值: = += -= *= /= %=
         function setup() {
           createCanvas(710, 400);
           background(51);
        @@ -27,25 +23,23 @@ function setup() {
         
           stroke(204);
           for (let i = 0; i < width - 20; i += 4) {
        -    // The 30 is added to 70 and then evaluated
        -    // if it is greater than the current value of "i"
        -    // For clarity, write as "if (i > (30 + 70)) {"
        +    // 30 和 70 先相加,其结果再和现在的 i 值比较大小
        +    // 更清楚的写法是:"if (i > (30 + 70)) {"
             if (i > 30 + 70) {
               line(i, 0, i, 50);
             }
           }
         
           stroke(255);
        -  // The 2 is multiplied by the 8 and the result is added to the 4
        -  // For clarity, write as "rect(5 + (2 * 8), 0, 90, 20);"
        +  // 2 和 8 先相乘,其结果再加 4
        +  // 更清楚的写法是:"rect(5 + (2 * 8), 0, 90, 20);"
           rect(4 + 2 * 8, 52, 290, 48);
           rect((4 + 2) * 8, 100, 290, 49);
         
           stroke(153);
           for (let i = 0; i < width; i += 2) {
        -    // The relational statements are evaluated
        -    // first, and then the logical AND statements and
        -    // finally the logical OR. For clarity, write as:
        +    // 先算关系表达式,再是逻辑与 (AND),最后是逻辑或 (OR)
        +    // 更清楚的写法是: 
             // "if(((i > 20) && (i < 50)) || ((i > 100) && (i < width-20))) {"
             if ((i > 20 && i < 50) || (i > 100 && i < width - 20)) {
               line(i, 151, i, height - 1);
        diff --git a/src/data/examples/zh-Hans/08_Math/02_distance1d.js b/src/data/examples/zh-Hans/08_Math/02_distance1d.js
        index 7005d3a17b..c75eabd6c5 100644
        --- a/src/data/examples/zh-Hans/08_Math/02_distance1d.js
        +++ b/src/data/examples/zh-Hans/08_Math/02_distance1d.js
        @@ -1,7 +1,6 @@
         /*
        - * @name Distance 1D
        - * @description Move the mouse left and right to control
        - * the speed and direction of the moving shapes.
        + * @name 一维间距
        + * @description 左右移动鼠标来控制移动形状的速度和方向。
          */
         let xpos1;
         let xpos2;
        diff --git a/src/data/examples/zh-Hans/08_Math/03_distance2d.js b/src/data/examples/zh-Hans/08_Math/03_distance2d.js
        index baba8a3f86..c9c956d931 100644
        --- a/src/data/examples/zh-Hans/08_Math/03_distance2d.js
        +++ b/src/data/examples/zh-Hans/08_Math/03_distance2d.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Distance 2D
        - * @description Move the mouse across the image to obscure
        - * and reveal the matrix. Measures the distance from the mouse
        - * to each square and sets the size proportionally.
        + * @name 二维间距
        + * @description 在图片上移动鼠标来遮盖并显示矩阵。
        + * 测量鼠标到每个正方形的距离,并按比例设置大小。
          */
         let max_distance;
         
        diff --git a/src/data/examples/zh-Hans/08_Math/04_sine.js b/src/data/examples/zh-Hans/08_Math/04_sine.js
        index 810d8a27be..9ddbef561c 100644
        --- a/src/data/examples/zh-Hans/08_Math/04_sine.js
        +++ b/src/data/examples/zh-Hans/08_Math/04_sine.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Sine
        - * @description Smoothly scaling size with the sin() function.
        + * @name 正弦
        + * @description 使用 sin() 函数平滑地缩放大小。
          */
         let diameter;
         let angle = 0;
        @@ -18,7 +18,7 @@ function draw() {
           let d1 = 10 + (sin(angle) * diameter) / 2 + diameter / 2;
           let d2 = 10 + (sin(angle + PI / 2) * diameter) / 2 + diameter / 2;
           let d3 = 10 + (sin(angle + PI) * diameter) / 2 + diameter / 2;
        -
        +  
           ellipse(0, height / 2, d1, d1);
           ellipse(width / 2, height / 2, d2, d2);
           ellipse(width, height / 2, d3, d3);
        diff --git a/src/data/examples/zh-Hans/08_Math/05_sincosine.js b/src/data/examples/zh-Hans/08_Math/05_sincosine.js
        index 82e9e42cf7..900df8b666 100644
        --- a/src/data/examples/zh-Hans/08_Math/05_sincosine.js
        +++ b/src/data/examples/zh-Hans/08_Math/05_sincosine.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Sine Cosine
        - * @description Linear movement with sin() and cos().
        - * Numbers between 0 and PI*2 (TWO_PI which angles roughly 6.28)
        - * are put into these functions and numbers between -1 and 1 are returned.
        - * These values are then scaled to produce larger movements.
        + * @name 正弦余弦
        + * @description sin() 函数和 cos() 函数的线性运动。
        + * 将 0 到 PI*2 (TWO_PI 的角度大致是 6.28) 之间的数字放进这些函数将返回 -1 到 1 之间的数字。
        + * 然后这些数字将缩放以产生更大的运动。
          */
         let angle1 = 0;
         let angle2 = 0;
        diff --git a/src/data/examples/zh-Hans/08_Math/06_sinewave.js b/src/data/examples/zh-Hans/08_Math/06_sinewave.js
        index f52d7b1368..a1dd4fb4de 100644
        --- a/src/data/examples/zh-Hans/08_Math/06_sinewave.js
        +++ b/src/data/examples/zh-Hans/08_Math/06_sinewave.js
        @@ -1,16 +1,16 @@
         /*
        - * @name Sine Wave
        - * @description Render a simple sine wave.
        - * Original by Daniel Shiffman.
        + * @name 正弦波
        + * @description 渲染一个简单的正弦波。
        + * 作者:Daniel Shiffman
          */
         
        -let xspacing = 16; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let theta = 0.0; // Start angle at 0
        -let amplitude = 75.0; // Height of wave
        -let period = 500.0; // How many pixels before the wave repeats
        -let dx; // Value for incrementing x
        -let yvalues; // Using an array to store height values for the wave
        +let xspacing = 16; // 每个水平位置的距离
        +let w; // 波的宽度
        +let theta = 0.0; // 初始角度为 0
        +let amplitude = 75.0; // 波的高度
        +let period = 500.0; // 波在重复前的像素个数
        +let dx; // x 的增量
        +let yvalues; // 保存波的高度的数组
         
         function setup() {
           createCanvas(710, 400);
        @@ -26,11 +26,10 @@ function draw() {
         }
         
         function calcWave() {
        -  // Increment theta (try different values for
        -  // 'angular velocity' here)
        +  // theta 增量(尝试赋予 ‘角速度’ 不同的数值)
           theta += 0.02;
         
        -  // For every x value, calculate a y value with sine function
        +  // 对于每一个 x 值,使用正弦函数计算 y 值
           let x = theta;
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = sin(x) * amplitude;
        @@ -41,7 +40,7 @@ function calcWave() {
         function renderWave() {
           noStroke();
           fill(255);
        -  // A simple way to draw the wave with an ellipse at each location
        +  // 在波上的每个位置画椭圆
           for (let x = 0; x < yvalues.length; x++) {
             ellipse(x * xspacing, height / 2 + yvalues[x], 16, 16);
           }
        diff --git a/src/data/examples/zh-Hans/08_Math/07_additivewave.js b/src/data/examples/zh-Hans/08_Math/07_additivewave.js
        index a23ea41d43..bf14652432 100644
        --- a/src/data/examples/zh-Hans/08_Math/07_additivewave.js
        +++ b/src/data/examples/zh-Hans/08_Math/07_additivewave.js
        @@ -1,19 +1,17 @@
         /*
        - * @name Additive Wave
        - * @description Create a more complex wave by adding two waves together.
        - * Original by Daniel Shiffman
        + * @name 加性波
        + * @description 通过相加两个波来绘制一个更复杂的波。
        + * 作者:Daniel Shiffman
          */
        -let xspacing = 8; // Distance between each horizontal location
        -let w; // Width of entire wave
        -let maxwaves = 4; // total # of waves to add together
        +let xspacing = 8; // 每个水平位置的距离
        +let w; // 波的宽度
        +let maxwaves = 4; // 相加的波的总数
         
         let theta = 0.0;
        -let amplitude = new Array(maxwaves); // Height of wave
        -// Value for incrementing X, to be calculated
        -// as a function of period and xspacing
        +let amplitude = new Array(maxwaves); // 波的高度
        +// x 的增量值,根据周期和水平位置距离来计算
         let dx = new Array(maxwaves);
        -// Using an array to store height values
        -// for the wave (not entirely necessary)
        +// 用数组保存波的高度(不完全需要)
         let yvalues;
         
         function setup() {
        @@ -24,7 +22,7 @@ function setup() {
         
           for (let i = 0; i < maxwaves; i++) {
             amplitude[i] = random(10, 30);
        -    let period = random(100, 300); // Num pixels before wave repeats
        +    let period = random(100, 300); // 波在重复前的像素个数
             dx[i] = (TWO_PI / period) * xspacing;
           }
         
        @@ -38,20 +36,19 @@ function draw() {
         }
         
         function calcWave() {
        -  // Increment theta (try different values
        -  // for 'angular velocity' here
        +  // theta 增量(尝试赋予 ‘角速度’ 不同的数值)
           theta += 0.02;
         
        -  // Set all height values to zero
        +  // 所有高度设为 0
           for (let i = 0; i < yvalues.length; i++) {
             yvalues[i] = 0;
           }
         
        -  // Accumulate wave height values
        +  // 累积波的高度
           for (let j = 0; j < maxwaves; j++) {
             let x = theta;
             for (let i = 0; i < yvalues.length; i++) {
        -      // Every other wave is cosine instead of sine
        +      // 正弦余弦交替
               if (j % 2 === 0) yvalues[i] += sin(x) * amplitude[j];
               else yvalues[i] += cos(x) * amplitude[j];
               x += dx[j];
        @@ -60,7 +57,7 @@ function calcWave() {
         }
         
         function renderWave() {
        -  // A simple way to draw the wave with an ellipse at each location
        +  // 在波上的每个位置画椭圆
           noStroke();
           fill(255, 50);
           ellipseMode(CENTER);
        diff --git a/src/data/examples/zh-Hans/08_Math/08_polartocartesian.js b/src/data/examples/zh-Hans/08_Math/08_polartocartesian.js
        index 1cab4cd202..c1116d3121 100644
        --- a/src/data/examples/zh-Hans/08_Math/08_polartocartesian.js
        +++ b/src/data/examples/zh-Hans/08_Math/08_polartocartesian.js
        @@ -1,12 +1,11 @@
         /*
          * @name PolarToCartesian
        - * @description Convert a polar coordinate (r,theta)
        - * to cartesian (x,y): x = rcos(theta) y = rsin(theta)
        - * Original by Daniel Shiffman.
        + * @description 转换极坐标 (r,theta) 到笛卡尔坐标 (x,y): x = rcos(theta) y = rsin(theta)。
        + * 作者:Daniel Shiffman
          */
         let r;
         
        -// Angle and angular velocity, accleration
        +// 角度,角速度,角加速度
         let theta;
         let theta_vel;
         let theta_acc;
        @@ -14,7 +13,7 @@ let theta_acc;
         function setup() {
           createCanvas(710, 400);
         
        -  // Initialize all values
        +  // 初始化所有值
           r = height * 0.45;
           theta = 0;
           theta_vel = 0;
        @@ -24,21 +23,21 @@ function setup() {
         function draw() {
           background(0);
         
        -  // Translate the origin point to the center of the screen
        +  // 将原点设为屏幕中心
           translate(width/2, height/2);
         
        -  // Convert polar to cartesian
        +  // 转换极坐标到笛卡尔坐标
           let x = r * cos(theta);
           let y = r * sin(theta);
         
        -  // Draw the ellipse at the cartesian coordinate
        +  // 在笛卡尔坐标系上画椭圆
           ellipseMode(CENTER);
           noStroke();
           fill(200);
           ellipse(x, y, 32, 32);
         
        -  // Apply acceleration and velocity to angle
        -  // (r remains static in this example)
        +  // 应用加速度和速度到角度上
        +  // (此示例中 r 保持静态)
           theta_vel += theta_acc;
           theta += theta_vel;
         }
        diff --git a/src/data/examples/zh-Hans/08_Math/09_arctangent.js b/src/data/examples/zh-Hans/08_Math/09_arctangent.js
        index cc90d4499b..493f0426f9 100644
        --- a/src/data/examples/zh-Hans/08_Math/09_arctangent.js
        +++ b/src/data/examples/zh-Hans/08_Math/09_arctangent.js
        @@ -1,6 +1,7 @@
         /*
        - * @name Arctangent
        - * @description Move the mouse to change the direction of the eyes.<br>The atan2() function computes the angle from each eye to the cursor.
        + * @name 反正切
        + * @description 移动鼠标来改变眼球的方向。<br>
        + * atan2() 函数计算每个眼球到鼠标的角度。
          */
         let e1, e2, e3;
         
        diff --git a/src/data/examples/zh-Hans/08_Math/10_Interpolate.js b/src/data/examples/zh-Hans/08_Math/10_Interpolate.js
        index 27ec95ef92..eefc644450 100644
        --- a/src/data/examples/zh-Hans/08_Math/10_Interpolate.js
        +++ b/src/data/examples/zh-Hans/08_Math/10_Interpolate.js
        @@ -1,11 +1,9 @@
         /*
        - * @name Linear Interpolation
        + * @name 线性插值
          * @frame 720, 400
        - * @description Move the mouse across the screen and the symbol will follow.
        - * Between drawing each frame of the animation, the ellipse moves part
        - * of the distance (0.05) from its current position toward the cursor using
        - * the lerp() function.
        - * This is the same as the Easing under input only with lerp() instead..
        + * @description 在屏幕上移动鼠标,圆会跟着移动。
        + * 在动画绘制的每一帧之间,lerp() 函数会使圆从其当前位置向光标移动一部分距离(0.05)。
        + * 这和在 Input 中的 <a href ="https://p5js.org/zh-Hans/examples/input-easing.html">Easing</a> 范例一样,只是使用了 lerp() 函数。
          */
         
         let x = 0;
        @@ -19,12 +17,11 @@ function setup() {
         function draw() {
           background(51);
         
        -  // lerp() calculates a number between two numbers at a specific increment.
        -  // The amt parameter is the amount to interpolate between the two values
        -  // where 0.0 equal to the first point, 0.1 is very near the first point, 0.5
        -  // is half-way in between, etc.
        +  // lerp() 函数计算在特定增量下两个数值之间的数字
        +  // amt 参数为两个值之间的插值量
        +  // 0.0 为第一个值,0.1 为非常接近第一个值,0.5 为两者之间,等等
         
        -  // Here we are moving 5% of the way to the mouse location each frame
        +  // 这里我们每帧移动 5% 至鼠标的距离
           x = lerp(x, mouseX, 0.05);
           y = lerp(y, mouseY, 0.05);
         
        diff --git a/src/data/examples/zh-Hans/08_Math/11_doubleRandom.js b/src/data/examples/zh-Hans/08_Math/11_doubleRandom.js
        index efdc6f1163..2fcc2a7752 100644
        --- a/src/data/examples/zh-Hans/08_Math/11_doubleRandom.js
        +++ b/src/data/examples/zh-Hans/08_Math/11_doubleRandom.js
        @@ -1,9 +1,8 @@
         /*
        - * @name Double Random
        + * @name 双重随机
          * @frame 720,400 (optional)
        - * @description Using two random() calls and the point()
        - * function to create an irregular sawtooth line.
        - * Original by by Ira Greenberg.
        + * @description 调用两个 random() 函数和一个 point() 函数来绘制一个不规则的锯齿线。
        + * 作者:Ira Greenberg
          */
         let totalPts = 300;
         let steps = totalPts + 1;
        diff --git a/src/data/examples/zh-Hans/08_Math/12_random.js b/src/data/examples/zh-Hans/08_Math/12_random.js
        index 6475297be5..a66b9bcdb6 100644
        --- a/src/data/examples/zh-Hans/08_Math/12_random.js
        +++ b/src/data/examples/zh-Hans/08_Math/12_random.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Random
        - * @description Random numbers create the basis of this image.
        - * Each time the program is loaded the result is different.
        + * @name 随机
        + * @description 随机数创建了此图像的基础。
        + * 每次加载程序将产生不同的结果。
          */
         function setup() {
           createCanvas(710, 400);
        @@ -12,6 +12,7 @@ function setup() {
         
         function draw() {
           for (let i = 0; i < width; i++) {
        +  	// 随机在 0-255 之间取数
             let r = random(255);
             stroke(r);
             line(i, 0, i, height);
        diff --git a/src/data/examples/zh-Hans/08_Math/13_noise1D.js b/src/data/examples/zh-Hans/08_Math/13_noise1D.js
        index 1e76feb448..d2e34e578e 100644
        --- a/src/data/examples/zh-Hans/08_Math/13_noise1D.js
        +++ b/src/data/examples/zh-Hans/08_Math/13_noise1D.js
        @@ -1,6 +1,6 @@
         /*
        - * @name Noise1D
        - * @description Using 1D Perlin Noise to assign location.
        + * @name 一维噪声 (Noise1D)
        + * @description 调用一维柏林噪声来指定位置。
          */
         let xoff = 0.0;
         let xincrement = 0.01;
        @@ -12,20 +12,20 @@ function setup() {
         }
         
         function draw() {
        -  // Create an alpha blended background
        +  // 创建一个透明度 (alpha) 混合背景
           fill(0, 10);
           rect(0, 0, width, height);
         
        -  //float n = random(0,width);  // Try this line instead of noise
        +  //let n = random(0,width);  // 尝试用这一行代替 noise()
         
        -  // Get a noise value based on xoff and scale
        -  // it according to the window's width
        +  // 基于 xoff 和 scale 得到一个噪声值
        +  // 并根据窗口宽度进行缩放
           let n = noise(xoff) * width;
         
        -  // With each cycle, increment xoff
        +  // 每一轮增加 xoff
           xoff += xincrement;
         
        -  // Draw the ellipse at the value produced by perlin noise
        +  // 绘制由柏林噪声产生的数值的椭圆
           fill(200);
           ellipse(n, height / 2, 64, 64);
         }
        diff --git a/src/data/examples/zh-Hans/08_Math/14_noisewave.js b/src/data/examples/zh-Hans/08_Math/14_noisewave.js
        index df1b1e0a24..ba3fbaea91 100644
        --- a/src/data/examples/zh-Hans/08_Math/14_noisewave.js
        +++ b/src/data/examples/zh-Hans/08_Math/14_noisewave.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Noise Wave
        - * @description Using Perlin Noise to generate a wave-like pattern.
        - * Original by Daniel Shiffman.
        + * @name 噪声波
        + * @description 调用柏林噪声来产生波状图案。 
        + * 作者:Daniel Shiffman
          */
        -let yoff = 0.0; // 2nd dimension of perlin noise
        +let yoff = 0.0; // 柏林噪声的第二维度
         
         function setup() {
           createCanvas(710, 400);
        @@ -13,28 +13,28 @@ function draw() {
           background(51);
         
           fill(255);
        -  // We are going to draw a polygon out of the wave points
        +  // 我们将从波点中绘制一个多边形
           beginShape();
         
        -  let xoff = 0; // Option #1: 2D Noise
        -  // let xoff = yoff; // Option #2: 1D Noise
        +  let xoff = 0; // 选项 1: 2D 噪声
        +  // let xoff = yoff; // 选项 2: 1D 噪声
         
        -  // Iterate over horizontal pixels
        +  // 迭代所有水平像素
           for (let x = 0; x <= width; x += 10) {
        -    // Calculate a y value according to noise, map to
        +    // 根据noise() 和 map() 函数计算一个 y 值
         
        -    // Option #1: 2D Noise
        +    // 选项 1: 2D 噪声
             let y = map(noise(xoff, yoff), 0, 1, 200, 300);
         
        -    // Option #2: 1D Noise
        +    // 选项 2: 1D 噪声
             // let y = map(noise(xoff), 0, 1, 200,300);
         
        -    // Set the vertex
        +    // 设置顶点
             vertex(x, y);
        -    // Increment x dimension for noise
        +    // 增加噪声的 x 维度
             xoff += 0.05;
           }
        -  // increment y dimension for noise
        +  // 增加噪声的 y 维度
           yoff += 0.01;
           vertex(width, height);
           vertex(0, height);
        diff --git a/src/data/examples/zh-Hans/08_Math/15_Noise2D.js b/src/data/examples/zh-Hans/08_Math/15_Noise2D.js
        index 2aec0d5690..769cc54909 100644
        --- a/src/data/examples/zh-Hans/08_Math/15_Noise2D.js
        +++ b/src/data/examples/zh-Hans/08_Math/15_Noise2D.js
        @@ -1,7 +1,7 @@
         /*
        - * @name Noise2D
        + * @name 二维噪声 (Noise2D)
          * @frame 710,400 (optional)
        - * @description Create a 2D noise with different parameters.
        + * @description 使用不同参数创建一个二维噪声。
          *
          */
         
        @@ -14,27 +14,27 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Draw the left half of image
        +  // 绘制左半边图像
           for (let y = 0; y < height - 30; y++) {
             for (let x = 0; x < width / 2; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // 像素所使用的八度数和衰退因数的 noiceDetail
               noiseDetail(2, 0.2);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  // Draw the right half of image
        +  // 绘制右半边图像
           for (let y = 0; y < height - 30; y++) {
             for (let x = width / 2; x < width; x++) {
        -      // noiceDetail of the pixels octave count and falloff value
        +      // 像素所使用的八度数和衰退因数的 noiceDetail
               noiseDetail(5, 0.5);
               noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
               stroke(noiseVal * 255);
               point(x, y);
             }
           }
        -  //Show the details of two partitions
        +  // 显示左右两分区的详细信息
           textSize(18);
           fill(255, 255, 255);
           text('Noice2D with 2 octaves and 0.2 falloff', 10, 350);
        diff --git a/src/data/examples/zh-Hans/08_Math/16_Noise3D.js b/src/data/examples/zh-Hans/08_Math/16_Noise3D.js
        index 94bd75841d..7923d6699a 100644
        --- a/src/data/examples/zh-Hans/08_Math/16_Noise3D.js
        +++ b/src/data/examples/zh-Hans/08_Math/16_Noise3D.js
        @@ -1,42 +1,42 @@
         /*
        - * @name Noise3D
        + * @name 三维噪声 (Noise3D)
          * @frame 710,400 (optional)
        - * @description Using 3D noise to create simple animated texture.
        + * @description 使用三维噪声创建简单的动画纹理。
          */
         
         let noiseVal;
        -//Increment x by 0.01
        +// x 增加 0.01
         let x_increment = 0.01;
        -//Increment z by 0.02 every draw() cycle
        +// 每一个 draw() 的周期,z 增加 0.02
         let z_increment = 0.02;
         
        -//Offset values
        +// 偏移值
         let z_off, y_off, x_off;
         
         function setup() {
        -  //Create the Canvas
        +  // 创建画布
           createCanvas(640, 360);
        -  //Define frame rate
        +  // 定义每一秒应该显示的影格数
           frameRate(20);
        -  //Initial value of z_off
        +  // 初始 z_off
           z_off = 0;
         }
         
         function draw() {
           x_off = 0;
           y_off = 0;
        -  //Make the background black
        +  // 设置黑色背景
           background(0);
        -  //Adjust the noice detail
        +  // 调整噪声细节
           noiseDetail(8, 0.65);
         
        -  //For each x,y calculate noice value
        +  // 对于每一个 x,y 计算噪声值
           for (let y = 0; y < height; y++) {
             x_off += x_increment;
             y_off = 0;
         
             for (let x = 0; x < width; x++) {
        -      //Calculate and Draw each pixel
        +      // 计算和绘制每一个像素
               noiseVal = noise(x_off, y_off, z_off);
               stroke(noiseVal * 255);
               y_off += x_increment;
        diff --git a/src/data/examples/zh-Hans/08_Math/17_Randomchords.js b/src/data/examples/zh-Hans/08_Math/17_Randomchords.js
        index 7b583bf660..84f5c693de 100644
        --- a/src/data/examples/zh-Hans/08_Math/17_Randomchords.js
        +++ b/src/data/examples/zh-Hans/08_Math/17_Randomchords.js
        @@ -1,34 +1,33 @@
         /*
        - * @name Random Chords
        - * @description Accumulates random chords of a circle. Each chord in translucent
        - * so they accumulate to give the illusion of a shaded sphere.
        - * Contributed by Aatish Bhatia, inspired by <a href ="http://inconvergent.net/">Anders Hoff</a>
        + * @name 随机弦
        + * @description 累积一个圆的随机弦。每个弦都是半透明的,所以它们累积起来会造成阴影球面的错觉。
        + * 贡献于 Aatish Bhatia,灵感来源于 <a href ="http://inconvergent.net/">Anders Hoff</a>
          */
         function setup() {
           createCanvas(400, 400);
           background(255, 255, 255);
         
        -  // translucent stroke using alpha value
        +  // 使用透明度值的半透明外形线
           stroke(0, 0, 0, 15);
         }
         
         function draw() {
        -  // draw two random chords each frame
        +  // 每一帧绘制两个随机弦
           randomChord();
           randomChord();
         }
         
         function randomChord() {
        -  // find a random point on a circle
        +  // 在圆上随机找一个点
           let angle1 = random(0, 2 * PI);
           let xpos1 = 200 + 200 * cos(angle1);
           let ypos1 = 200 + 200 * sin(angle1);
         
        -  // find another random point on the circle
        +  // 在圆上随机找另一个点
           let angle2 = random(0, 2 * PI);
           let xpos2 = 200 + 200 * cos(angle2);
           let ypos2 = 200 + 200 * sin(angle2);
         
        -  // draw a line between them
        +  // 在两点之间绘制一条直线
           line(xpos1, ypos1, xpos2, ypos2);
         }
        diff --git a/src/data/examples/zh-Hans/08_Math/18_Map.js b/src/data/examples/zh-Hans/08_Math/18_Map.js
        index a7b4d86058..6ed777b6b1 100644
        --- a/src/data/examples/zh-Hans/08_Math/18_Map.js
        +++ b/src/data/examples/zh-Hans/08_Math/18_Map.js
        @@ -1,10 +1,8 @@
         /*
        - * @name Map
        - * @description Use the map() function to take any number and scale it to a
        - * new number that is more useful for the project that you are working on.
        - * For example, use the numbers from the mouse position to control the size or color of a shape.
        - * In this example, the mouse’s x-coordinate (numbers between 0 and 360) are scaled to new numbers
        - * to define the color and size of a circle.
        + * @name 映射 (Map)
        + * @description 调用 map() 函数将任意数值缩放至一个对于现在程序更有用的新数值。
        + * 例如,使用鼠标的位置来控制形状的大小或颜色。
        + * 此范例中,鼠标的 x 坐标( 0-360 之间的数字)将被缩放为新数值,用于设定圆的颜色和大小。
          */
         function setup() {
           createCanvas(640, 400);
        @@ -13,9 +11,9 @@ function setup() {
         
         function draw() {
           background(0);
        -  // Scale the mouseX value from 0 to 640 to a range between 0 and 175
        +  // 将 mouseX 的数值从 0-640 缩放至 0-175 的范围内
           let c = map(mouseX, 0, width, 0, 175);
        -  // Scale the mouseX value from 0 to 640 to a range between 40 and 300
        +  // 将 mouseX 的数值从 0-640 to 缩放至 40-300 的范围内
           let d = map(mouseX, 0, width, 40, 300);
           fill(255, c, 0);
           ellipse(width/2, height/2, d, d);
        diff --git a/src/data/examples/zh-Hans/08_Math/19_parametricEquation.js b/src/data/examples/zh-Hans/08_Math/19_parametricEquation.js
        index 83c1a3c336..423400d4ae 100644
        --- a/src/data/examples/zh-Hans/08_Math/19_parametricEquation.js
        +++ b/src/data/examples/zh-Hans/08_Math/19_parametricEquation.js
        @@ -1,44 +1,43 @@
         /*
        - * @name Parametric Equations
        - * @description A parametric equation is where x and y
        - * coordinates are both written in terms of another letter. This is
        - * called a parameter and is usually given in the letter t or θ.
        - * The inspiration was taken from the YouTube channel of Alexander Miller.
        + * @name 参数方程
        + * @description 参数方程是 x 和 y 坐标都用另外的字母表示。
        + * 这被称为参数并且通常以字母 t 或 θ 给出。
        + * 灵感来源于 Alexander Miller 油管频道。
          */
         
         function setup(){
           createCanvas(720,400);
         }
         
        -// the parameter at which x and y depends is usually taken as either t or symbol of theta
        +// x 和 y 所依靠的参数通常被视为 t 或者 theta 的符号
         let t = 0;
         function draw(){
           background('#fff');
           translate(width/2,height/2);
           stroke('#0f0f0f');
           strokeWeight(1.5);
        -  //loop for adding 100 lines
        +  // 迭代来增加 100 条直线
           for(let i = 0;i<100;i++){
             line(x1(t+i),y1(t+i),x2(t+i)+20,y2(t+i)+20);
           }
           t+=0.15;
         }
        -// function to change initial x co-ordinate of the line
        +// 改变直线的初始 x 坐标
         function x1(t){
           return sin(t/10)*125+sin(t/20)*125+sin(t/30)*125;
         }
         
        -// function to change initial y co-ordinate of the line
        +// 改变直线的初始 y 坐标
         function y1(t){
           return cos(t/10)*125+cos(t/20)*125+cos(t/30)*125;
         }
         
        -// function to change final x co-ordinate of the line
        +// 改变直线的最终 x 坐标
         function x2(t){
           return sin(t/15)*125+sin(t/25)*125+sin(t/35)*125;
         }
         
        -// function to change final y co-ordinate of the line
        +// 改变直线的最终 y 坐标
         function y2(t){
           return cos(t/15)*125+cos(t/25)*125+cos(t/35)*125;
         }
        \ No newline at end of file
        diff --git a/src/data/examples/zh-Hans/10_Interaction/10_Tickle.js b/src/data/examples/zh-Hans/10_Interaction/10_Tickle.js
        index 006ce49caa..82b76bdbda 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/10_Tickle.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/10_Tickle.js
        @@ -1,14 +1,14 @@
         /*
          * @name Tickle
        - * @description The word "tickle" jitters when the cursor hovers over.
        - * Sometimes, it can be tickled off the screen.
        + * @description "tickle" 这个单词会在光标移至它时抖动。
        + * 有时还会抖出屏幕。
          */
         let message = 'tickle',
           font,
        -  bounds, // holds x, y, w, h of the text's bounding box
        +  bounds, // 存储文本框的 x, y, w, h 值
           fontsize = 60,
           x,
        -  y; // x and y coordinates of the text
        +  y; // 文本的 x 和 y 坐标
         
         function preload() {
           font = loadFont('assets/SourceSansPro-Regular.otf');
        @@ -17,11 +17,11 @@ function preload() {
         function setup() {
           createCanvas(710, 400);
         
        -  // set up the font
        +  // 设置字体
           textFont(font);
           textSize(fontsize);
         
        -  // get the width and height of the text so we can center it initially
        +  // 获取文本的宽度和高度,以便我们可以首先将其居中
           bounds = font.textBounds(message, 0, 0, fontsize);
           x = width / 2 - bounds.w / 2;
           y = height / 2 - bounds.h / 2;
        @@ -30,12 +30,12 @@ function setup() {
         function draw() {
           background(204, 120);
         
        -  // write the text in black and get its bounding box
        +  // 写出黑色的文本并获取其文本框
           fill(0);
           text(message, x, y);
           bounds = font.textBounds(message, x, y, fontsize);
         
        -  // check if the mouse is inside the bounding box and tickle if so
        +  // 检查鼠标是否在文本框里;如果在文本框内,抖动文本
           if (
             mouseX >= bounds.x &&
             mouseX <= bounds.x + bounds.w &&
        diff --git a/src/data/examples/zh-Hans/10_Interaction/20_Follow1.js b/src/data/examples/zh-Hans/10_Interaction/20_Follow1.js
        index df0902cc09..290cec5a16 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/20_Follow1.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/20_Follow1.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Follow 1
        + * @name 跟随 1
          * @frame 710,400
        - * @description A line segment is pushed and pulled by the cursor.
        - * Based on code from Keith Peters.
        + * @description 被光标拉扯的一条线段。
        + * 基于 Keith Peters 的代码。
          */
         let x = 100,
           y = 100,
        diff --git a/src/data/examples/zh-Hans/10_Interaction/21_Follow2.js b/src/data/examples/zh-Hans/10_Interaction/21_Follow2.js
        index ebb87cb2ca..4d5c7e2aa5 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/21_Follow2.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/21_Follow2.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Follow 2
        + * @name 跟随 2
          * @frame 710,400
        - * @description A two-segmented arm follows the cursor position. The relative
        - * angle between the segments is calculated with atan2() and the position
        - * calculated with sin() and cos(). Based on code from Keith Peters.
        + * @description 跟随光标移动的两段式手臂。
        + * 两个手臂之间的相对角度是用 atan2() 计算的,位置是用 sin() 和 cos() 计算的。
        + * 基于 Keith Peters 的代码。
          */
         let x = [0, 0],
           y = [0, 0],
        diff --git a/src/data/examples/zh-Hans/10_Interaction/22_Follow3.js b/src/data/examples/zh-Hans/10_Interaction/22_Follow3.js
        index 79878f8f2c..155bf2783f 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/22_Follow3.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/22_Follow3.js
        @@ -1,9 +1,9 @@
         /*
        - * @name Follow 3
        + * @name 跟随 3
          * @frame 710,400
        - * @description A segmented line follows the mouse. The relative angle from
        - * each segment to the next is calculated with atan2() and the position of
        - * the next is calculated with sin() and cos(). Based on code from Keith Peters.
        + * @description 随鼠标移动的一条分段式线条。
        + * 每段之间的相对角度是用 atan2() 计算的,位置是用 sin() 和 cos() 计算的。
        + * 基于 Keith Peters 的代码。
          */
         let x = [],
           y = [],
        diff --git a/src/data/examples/zh-Hans/10_Interaction/23_snake.js b/src/data/examples/zh-Hans/10_Interaction/23_snake.js
        index ac56aa3fd3..e72105780a 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/23_snake.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/23_snake.js
        @@ -1,17 +1,16 @@
         /*
        - * @name Snake game
        - * @description The famous snake game! Once you click run, click anywhere
        - * inside the black area, and control the snake using i j k and l. Don't let
        - * the snake hit itself or the wall!<br>
        - * Example created by <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta
        + * @name 贪吃蛇
        + * @description 著名的贪吃蛇游戏!点击 run 后,在黑色区域里任意点击, 
        + * 使用 i j k 和 l 控制蛇。注意不要让蛇碰到自己或者墙。<br>
        + * 由 <a href='https://github.com/prashantgupta24' target='_blank'>Prashant Gupta 创作的范例
          */
         
        -// the snake is divided into small segments, which are drawn and edited on each 'draw' call
        +// 蛇被分为几小段,在每次调用 draw() 时进行绘制和编辑
         let numSegments = 10;
         let direction = 'right';
         
        -const xStart = 0; //starting x coordinate for snake
        -const yStart = 250; //starting y coordinate for snake
        +const xStart = 0; // 蛇的初始 x 坐标
        +const yStart = 250; //蛇的初始 y 坐标
         const diff = 10;
         
         let xCor = [];
        @@ -50,15 +49,12 @@ function draw() {
         }
         
         /*
        - The segments are updated based on the direction of the snake.
        - All segments from 0 to n-1 are just copied over to 1 till n, i.e. segment 0
        - gets the value of segment 1, segment 1 gets the value of segment 2, and so on,
        - and this results in the movement of the snake.
        -
        - The last segment is added based on the direction in which the snake is going,
        - if it's going left or right, the last segment's x coordinate is increased by a
        - predefined value 'diff' than its second to last segment. And if it's going up
        - or down, the segment's y coordinate is affected.
        + 根据蛇的方向更新每个小段。
        + 从 0 至 n-1 的所有片段都被复制到 1 至 n,也就是说,段 0 获取 段 1 的值,
        + 段 1 获取 段 2 的值,以此类推。因此,蛇就会动起来了。
        +
        + 最后一小段根据蛇运动的方向添加。如果蛇在左后移动,最后一小段的 x 坐标值将比倒数第二小段
        + 增加预定义值 "diff";如果上下移动,则更改其 y 坐标值。
         */
         function updateSnakeCoordinates() {
           for (let i = 0; i < numSegments - 1; i++) {
        @@ -86,9 +82,8 @@ function updateSnakeCoordinates() {
         }
         
         /*
        - I always check the snake's head position xCor[xCor.length - 1] and
        - yCor[yCor.length - 1] to see if it touches the game's boundaries
        - or if the snake hits itself.
        + 检查蛇头的位置 xCor[xCor.length - 1] 和 yCor[yCor.length - 1] 来看它是否
        + 碰到边界或者自己。
         */
         function checkGameStatus() {
           if (
        @@ -105,8 +100,7 @@ function checkGameStatus() {
         }
         
         /*
        - If the snake hits itself, that means the snake head's (x,y) coordinate
        - has to be the same as one of its own segment's (x,y) coordinate.
        + 如果蛇碰到自己,说明蛇头的 (x,y) 坐标和它自身的小段之一的 (x,y) 坐标相同。
         */
         function checkSnakeCollision() {
           const snakeHeadX = xCor[xCor.length - 1];
        @@ -119,9 +113,8 @@ function checkSnakeCollision() {
         }
         
         /*
        - Whenever the snake consumes a fruit, I increment the number of segments,
        - and just insert the tail segment again at the start of the array (basically
        - I add the last segment again at the tail, thereby extending the tail)
        + 蛇每吃一个水果,小段的数量就会增加,然后将尾段插入数组的开头
        + (将最后一个小段再次添加到尾部,从而延长了尾部)
         */
         function checkForFruit() {
           point(xFruit, yFruit);
        @@ -137,9 +130,8 @@ function checkForFruit() {
         
         function updateFruitCoordinates() {
           /*
        -    The complex math logic is because I wanted the point to lie
        -    in between 100 and width-100, and be rounded off to the nearest
        -    number divisible by 10, since I move the snake in multiples of 10.
        +    这里的数学逻辑是因为我希望这个点位于 100 和 width-100 之间,并四舍五入到
        +    10 的倍数 ,因为蛇以 10 的倍数移动。
           */
         
           xFruit = floor(random(10, (width - 100) / 10)) * 10;
        diff --git a/src/data/examples/zh-Hans/10_Interaction/24_Wavemaker.js b/src/data/examples/zh-Hans/10_Interaction/24_Wavemaker.js
        index 26d29ee0b2..18c8639868 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/24_Wavemaker.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/24_Wavemaker.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Wavemaker
        - * @description This illustrates how waves (like water waves) emerge
        - * from particles oscillating in place. Move your mouse to direct the wave.
        - * Contributed by Aatish Bhatia, inspired by <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a> by Dave Whyte.
        + * @name 造波器
        + * @description 此范例说明了波(如水波)是如何在粒子摆动中产生的。
        + * 移动鼠标以引导波浪。
        + * 由 Aatish Bhatia 贡献,灵感来自 Dave Whyte 的 <a href="https://beesandbombs.tumblr.com/post/45513650541/orbiters">Orbiters</a>。
          */
         
         let t = 0; // time variable
        @@ -14,24 +14,24 @@ function setup() {
         }
         
         function draw() {
        -  background(10, 10); // translucent background (creates trails)
        +  background(10, 10); // 半透明背景(创建足迹)
         
        -  // make a x and y grid of ellipses
        +  // 创建 x 和 y 网格上的椭圆 
           for (let x = 0; x <= width; x = x + 30) {
             for (let y = 0; y <= height; y = y + 30) {
        -      // starting point of each circle depends on mouse position
        +      // 每个圆的初始位置取决于鼠标位置
               const xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true);
               const yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true);
        -      // and also varies based on the particle's location
        +      // 也根据粒子的位置变化 
               const angle = xAngle * (x / width) + yAngle * (y / height);
         
        -      // each particle moves in a circle
        +      // 每个粒子绕圈运动 
               const myX = x + 20 * cos(2 * PI * t + angle);
               const myY = y + 20 * sin(2 * PI * t + angle);
         
        -      ellipse(myX, myY, 10); // draw particle
        +      ellipse(myX, myY, 10); // 绘制粒子
             }
           }
         
        -  t = t + 0.01; // update time
        +  t = t + 0.01; // 更新时间
         }
        diff --git a/src/data/examples/zh-Hans/10_Interaction/25_reach1.js b/src/data/examples/zh-Hans/10_Interaction/25_reach1.js
        index 7982061aac..d85f4f9025 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/25_reach1.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/25_reach1.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 1
        + * @name 延伸 1
          * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 手臂随鼠标的位置移动,使用 atan2() 计算角度。
        + * 基于 Keith Peters 的代码。
          */
         let segLength = 80,
           x,
        diff --git a/src/data/examples/zh-Hans/10_Interaction/26_reach2.js b/src/data/examples/zh-Hans/10_Interaction/26_reach2.js
        index 4d6ea72174..a086231b62 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/26_reach2.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/26_reach2.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 2
        + * @name 延伸 2
          * @frame 710,400
        - * @description The arm follows the position of the mouse by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 手臂随鼠标的位置移动,使用 atan2() 计算角度。
        + * 基于 Keith Peters 的代码。
          */
         let numSegments = 10,
           x = [],
        @@ -23,8 +23,8 @@ function setup() {
           strokeWeight(20);
           stroke(255, 100);
         
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        +  x[x.length - 1] = width / 2; // // 设置基础 x 坐标 
        +  y[x.length - 1] = height; // 设置基础 y 坐标
         }
         
         function draw() {
        diff --git a/src/data/examples/zh-Hans/10_Interaction/27_reach3.js b/src/data/examples/zh-Hans/10_Interaction/27_reach3.js
        index 32739138b3..2d971864a0 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/27_reach3.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/27_reach3.js
        @@ -1,8 +1,8 @@
         /*
        - * @name Reach 3
        + * @name 延伸 3
          * @frame 710,400
        - * @description The arm follows the position of the ball by calculating the
        - * angles with atan2(). Based on code from Keith Peters.
        + * @description 手臂随球的位置移动,使用 atan2() 计算角度。
        + * 基于 Keith Peters 的代码。
          */
         let numSegments = 8,
           x = [],
        @@ -28,8 +28,8 @@ function setup() {
           stroke(255, 100);
           noFill();
         
        -  x[x.length - 1] = width / 2; // Set base x-coordinate
        -  y[x.length - 1] = height; // Set base y-coordinate
        +  x[x.length - 1] = width / 2; // 设置基础 x 坐标 
        +  y[x.length - 1] = height; // 设置基础 y 坐标
         }
         
         function draw() {
        diff --git a/src/data/examples/zh-Hans/10_Interaction/28_ArduinoSensor.js b/src/data/examples/zh-Hans/10_Interaction/28_ArduinoSensor.js
        index 6e994c330a..1b23ed2ed4 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/28_ArduinoSensor.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/28_ArduinoSensor.js
        @@ -1,36 +1,34 @@
         /*
        - * @name Arduino sensor data via WebJack
        - * @description WebJack is a way to read data from an Arduino (and other sources)
        - * using audio -- it basically turns your Arduino into an audio modem.
        - * 
        + * @name 通过 WebJack 读取 Arduino 传感器数据
        + * @description WebJack 是使用音频从 Arduino(和其他来源)
        + * 读取数据的方式 -- 它基本上将 Arduino 变成了音频调制解调器。
        + *
          * https://github.com/publiclab/webjack
        - * 
        - * Note: WebJack and p5-webjack libraries must be added to your index.html as follows:
        + *
        + * 注: WebJack 和 p5-webjack 库必须以以下方式添加到 index.html:
          * <pre><code class="language-markup">&lt;script src="https://webjack.io/dist/webjack.js">&lt;/script></code></pre>
          * <pre><code class="language-markup">&lt;script src="https://jywarren.github.io/p5-webjack/lib.js">&lt;/script></code></pre>
        - * 
        - * Working example: https://editor.p5js.org/jywarren/sketches/rkztwSt8M
        - * 
        - * Testing audio: https://www.youtube.com/watch?v=GtJW1Dlt3cg
        - * Load this sketch onto an Arduino: 
        + *
        + * 实例: https://editor.p5js.org/jywarren/sketches/rkztwSt8M
        + *
        + * 测试音频: https://www.youtube.com/watch?v=GtJW1Dlt3cg
        + * 将此草图加载到 Arduino:
          * https://create.arduino.cc/editor/jywarren/023158d8-be51-4c78-99ff-36c63126b554/preview
        - * Arduino will output audio from pin 3 + ground. Use microphone or an audio cable.
        + * 从引脚 3 + 地引脚(GND)输出音频。请使用使用麦克风或音频线。
          */
         
        -function setup() { 
        +function setup() {
           createCanvas(400, 400);
           noStroke();
           fill('#ff00aa22');
           receiveSensorData(handleData);
        -} 
        +}
         
         function handleData(data) {
        +  console.log(data); // 打出数据
        +  // data[0] 是第一个值, data[1] 是第二个, 以此类推.
         
        -  console.log(data); // output the values to log
        -  // data[0] is the 1st value, data[1] 2nd, etc.
        -
        -  // draw stuff! Browse http://p5js.org/reference/
        +  // 绘制! 参考 http://p5js.org/reference/
           background('#ddd');
        -  ellipse(100, 200, data[0]+10, data[0]+10);
        -
        +  ellipse(100, 200, data[0] + 10, data[0] + 10);
         }
        diff --git a/src/data/examples/zh-Hans/10_Interaction/29_kaleidoscope.js b/src/data/examples/zh-Hans/10_Interaction/29_kaleidoscope.js
        index 2593d1143a..b4f445fc60 100644
        --- a/src/data/examples/zh-Hans/10_Interaction/29_kaleidoscope.js
        +++ b/src/data/examples/zh-Hans/10_Interaction/29_kaleidoscope.js
        @@ -1,47 +1,52 @@
         /*
        - * @name Kaleidoscope
        - * @description A kaleidoscope is an optical instrument with two or more reflecting surfaces tilted to each other in an angle. This example tries to replicate the behavior of a kaleidoscope. Set the number of reflections at the symmetry variable and start drawing on the screen. Adjust the brush size with the help of the slider. The clear screen as it says clears the screen. The save button will download a .jpg file of the art that you have created.
        + * @name 万花筒
        + * @description 万花筒是一个光学仪器,具有两个或多个互相倾斜的反射面。
        + * 此范例尝试模仿万花筒的效果。
        + * 通过 symmetry 变量设定反射的数量,并开始在屏幕上绘制。
        + * 通过 slider 调整画笔的大小。
        + * clearScreen(),顾名思义,清空屏幕。
        + * save 按钮将你绘制的艺术品以 .jpg 的文件格式下载下来。
          */
        -// Symmetry corresponding to the number of reflections. Change the number for different number of reflections 
        -let symmetry = 6;   
        +// Symmetry 指反射的次数。更改此数值以改变反射的次数。 
        +let symmetry = 6;
         
         let angle = 360 / symmetry;
         let saveButton, clearButton, mouseButton, keyboardButton;
         let slider;
         
        -function setup() { 
        +function setup() {
           createCanvas(710, 710);
           angleMode(DEGREES);
           background(127);
         
        -  // Creating the save button for the file
        +  // 制作保存文件的按钮
           saveButton = createButton('save');
           saveButton.mousePressed(saveFile);
         
        -  // Creating the clear screen button
        +  // 制作清空屏幕的按钮
           clearButton = createButton('clear');
           clearButton.mousePressed(clearScreen);
         
        -  // Creating the button for Full Screen
        +  // 制作全屏按钮 
           fullscreenButton = createButton('Full Screen');
           fullscreenButton.mousePressed(screenFull);
         
        -  // Setting up the slider for the thickness of the brush
        +  // 设置 slider 以改变笔刷的粗细 
           brushSizeSlider = createButton('Brush Size Slider');
           sizeSlider = createSlider(1, 32, 4, 0.1);
         }
         
        -// Save File Function
        +// 保存文件函数
         function saveFile() {
           save('design.jpg');
         }
         
        -// Clear Screen function
        +// 清空屏幕函数 
         function clearScreen() {
           background(127);
         }
         
        -// Full Screen Function
        +// 全屏函数 
         function screenFull() {
           let fs = fullscreen();
           fullscreen(!fs);
        @@ -55,7 +60,7 @@ function draw() {
             let my = mouseY - height / 2;
             let pmx = pmouseX - width / 2;
             let pmy = pmouseY - height / 2;
        -    
        +
             if (mouseIsPressed) {
               for (let i = 0; i < symmetry; i++) {
                 rotate(angle);
        diff --git a/src/data/examples/zh-Hans/11_Objects/01_Objects.js b/src/data/examples/zh-Hans/11_Objects/01_Objects.js
        index 79f10d3295..009c6b4dd5 100644
        --- a/src/data/examples/zh-Hans/11_Objects/01_Objects.js
        +++ b/src/data/examples/zh-Hans/11_Objects/01_Objects.js
        @@ -1,15 +1,14 @@
         /*
        - * @name Objects
        - * @description Create a Jitter class, instantiate an object,
        - * and move it around the screen. Adapted from Getting Started with
        - * Processing by Casey Reas and Ben Fry.
        + * @name 物件 (Objects)
        + * @description 创建一个 Jitter 类, 实例化一个物件,并且在屏幕上移动。
        + * 改编自 Processing 入门,作者:Casey Reas 和 Ben Fry
          */
         
        -let bug; // Declare object
        +let bug; // 声明物件
         
         function setup() {
           createCanvas(710, 400);
        -  // Create object
        +  // 创造物件
           bug = new Jitter();
         }
         
        @@ -19,7 +18,7 @@ function draw() {
           bug.display();
         }
         
        -// Jitter class
        +// Jitter 类
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/zh-Hans/11_Objects/02_Multiple_Objects.js b/src/data/examples/zh-Hans/11_Objects/02_Multiple_Objects.js
        index b57e9209e2..2268530df0 100644
        --- a/src/data/examples/zh-Hans/11_Objects/02_Multiple_Objects.js
        +++ b/src/data/examples/zh-Hans/11_Objects/02_Multiple_Objects.js
        @@ -1,17 +1,16 @@
         /*
        - * @name Multiple Objects
        - * @description Create a Jitter class, instantiate multiple objects,
        - * and move it around the screen.
        + * @name 多个物件
        + * @description 创建一个 Jitter 类,实例化多个物件,并且在屏幕上移动。
          */
         
        -let bug1; // Declare objects
        +let bug1; // 声明物件
         let bug2;
         let bug3;
         let bug4;
         
         function setup() {
           createCanvas(710, 400);
        -  // Create object
        +  // 创造物件
           bug1 = new Jitter();
           bug2 = new Jitter();
           bug3 = new Jitter();
        @@ -30,7 +29,7 @@ function draw() {
           bug4.display();
         }
         
        -// Jitter class
        +// Jitter 类
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/zh-Hans/11_Objects/03_Objects_Array.js b/src/data/examples/zh-Hans/11_Objects/03_Objects_Array.js
        index ccc5406037..3e6c383566 100644
        --- a/src/data/examples/zh-Hans/11_Objects/03_Objects_Array.js
        +++ b/src/data/examples/zh-Hans/11_Objects/03_Objects_Array.js
        @@ -1,14 +1,13 @@
         /*
        - * @name Array of Objects
        - * @description Create a Jitter class, instantiate an array of objects
        - * and move them around the screen.
        + * @name 物件数组
        + * @description 创建一个 Jitter 类,实例化多个物件,并且在屏幕上移动。
          */
         
        -let bugs = []; // array of Jitter objects
        +let bugs = []; // Jitter 物件的数组
         
         function setup() {
           createCanvas(710, 400);
        -  // Create objects
        +  // 创造物件
           for (let i = 0; i < 50; i++) {
             bugs.push(new Jitter());
           }
        @@ -22,7 +21,7 @@ function draw() {
           }
         }
         
        -// Jitter class
        +// Jitter 类
         class Jitter {
           constructor() {
             this.x = random(width);
        diff --git a/src/data/examples/zh-Hans/11_Objects/03_Objects_Optional_Arguments.js b/src/data/examples/zh-Hans/11_Objects/03_Objects_Optional_Arguments.js
        index 2796774489..cc6ddc879f 100644
        --- a/src/data/examples/zh-Hans/11_Objects/03_Objects_Optional_Arguments.js
        +++ b/src/data/examples/zh-Hans/11_Objects/03_Objects_Optional_Arguments.js
        @@ -1,8 +1,7 @@
         /*
        - * @name Objects 2
        - * @description Ported from example by hbarragan. Move the cursor across the
        - * image to change the speed and positions of the geometry. The class MRect
        - * defines a group of lines.
        + * @name 物件 2
        + * @description 转自 hbarragan 的范例。在图像上移动光标以更改几何图形的速度和位置。
        + * MRect 类定义了一组线。
          */
         
         let r1, r2, r3, r4;
        @@ -33,12 +32,12 @@ function draw() {
         
         class MRect {
           constructor(iw, ixp, ih, iyp, id, it) {
        -    this.w = iw; // single bar width
        -    this.xpos = ixp; // rect xposition
        -    this.h = ih; // rect height
        -    this.ypos = iyp; // rect yposition
        -    this.d = id; // single bar distance
        -    this.t = it; // number of bars
        +    this.w = iw; // 单线条宽度
        +    this.xpos = ixp; // rect x 值
        +    this.h = ih; // rect 高度
        +    this.ypos = iyp; // rect y 值
        +    this.d = id; // 单线条间距
        +    this.t = it; // 单线条数量
           }
         
           move(posX, posY, damping) {
        diff --git a/src/data/examples/zh-Hans/11_Objects/04_Inheritance.js b/src/data/examples/zh-Hans/11_Objects/04_Inheritance.js
        index 32b6a630e3..fd4681e71a 100644
        --- a/src/data/examples/zh-Hans/11_Objects/04_Inheritance.js
        +++ b/src/data/examples/zh-Hans/11_Objects/04_Inheritance.js
        @@ -1,9 +1,8 @@
        -/* @name Inheritance
        - * @description A class can be defined using another class as a
        - * foundation. In object-oriented programming terminology, one class can
        - * inherit fields and methods from another. An object that inherits from
        - * another is called a subclass, and the object it inherits from is called
        - * a superclass. A subclass extends the superclass.
        +/* @name 继承 (Inheritance)
        + * @description 可以用一个类作为基础来定义另一个类。在面向对象的编程术语中,
        + * 一个类可以继承另一个类的字段 (fields) 和方法 (methods)。
        + * 从另一个物件继承了的物件称为子类 (subclass),其继承的物件称为基类 (superclass)。
        + * 子类扩展基类。
          */
         let spots, arm;
         
        diff --git a/src/data/examples/zh-Hans/11_Objects/05_Composite_Objects.js b/src/data/examples/zh-Hans/11_Objects/05_Composite_Objects.js
        index 00fc969241..f680925995 100644
        --- a/src/data/examples/zh-Hans/11_Objects/05_Composite_Objects.js
        +++ b/src/data/examples/zh-Hans/11_Objects/05_Composite_Objects.js
        @@ -1,7 +1,6 @@
        -/* @name Composite Objects
        - * @description An object can include several other objects.
        - * Creating such composite objects is a good way to use the principles
        - * of modularity and build higher levels of abstraction within a program.
        +/* @name 复合物件
        + * @description 一个物件可以包含多个其他物件。
        + * 创造复合物件是使用模块性和程序中构建更高级别的抽象的好方法。
          */
         let er1, er2;
         
        diff --git a/src/data/examples/zh-Hans/15_Instance_Mode/01_Instantiating.js b/src/data/examples/zh-Hans/15_Instance_Mode/01_Instantiating.js
        index 0c4bc70751..592f0a3dcf 100644
        --- a/src/data/examples/zh-Hans/15_Instance_Mode/01_Instantiating.js
        +++ b/src/data/examples/zh-Hans/15_Instance_Mode/01_Instantiating.js
        @@ -1,17 +1,16 @@
         /*
        - * @name Instantiation
        - * @description Create a p5 instance, which keeps all variables
        - * out of the global scope of your page.
        + * @name 创建实例
        + * @description 创建一个 p5 实例,以便让所有变量在全局作用域之外。
          */
        -let sketch = function(p) {
        +let sketch = function (p) {
           let x = 100;
           let y = 100;
         
        -  p.setup = function() {
        +  p.setup = function () {
             p.createCanvas(700, 410);
           };
         
        -  p.draw = function() {
        +  p.draw = function () {
             p.background(0);
             p.fill(255);
             p.rect(x, y, 50, 50);
        @@ -20,7 +19,7 @@ let sketch = function(p) {
         
         let myp5 = new p5(sketch);
         
        -// Compare to "global mode"
        +// “全局模式” 作为对照
         // let x = 100;
         // let y = 100;
         
        diff --git a/src/data/examples/zh-Hans/15_Instance_Mode/02_Instance_Container.js b/src/data/examples/zh-Hans/15_Instance_Mode/02_Instance_Container.js
        index 9675fdeaaf..3b901c7348 100644
        --- a/src/data/examples/zh-Hans/15_Instance_Mode/02_Instance_Container.js
        +++ b/src/data/examples/zh-Hans/15_Instance_Mode/02_Instance_Container.js
        @@ -1,16 +1,14 @@
         /*
          * @norender
        - * @name Instance Container
        - * @description Optionally, you can specify a default container for the canvas
        - * and any other elements to append to with a second argument. You can give the
        - * ID of an element in your html, or an html node itself.
        + * @name 实例容器
        + * @description 第二个参数可以是你指定作为画布的默认容器,也可以是任何
        + 你想要添加此 p5 实例容器至的元素。可以是带 ID 的 html 元素, 也可以是 html 节点本身。
          *
        - * Here are three different options for selecting a container
        - * DOM element. All DOM elements (canvas, buttons, divs, etc) created by p5
        - * will be attached to the DOM element specified as the second argument to the
        - * p5() call.
        + * 以下列举了三种选择 DOM 元素作为容器的方法。 
        + * 所有由 p5 创建的 DOM 元素(画布,按钮,div 等)都会被添加到指定的 DOM 元素上,
        + * 这个指定元素就是调用 p5() 时传递的第二个参数。
          */
        -<!-- pass in the ID of the container element -->
        +<!-- 传递容器元素的 ID -->
         <!DOCTYPE html>
         <head>
           <script src='p5.js'></script>
        @@ -30,7 +28,7 @@
         </html>
         
         
        -<!-- pass in a pointer to the container element -->
        +<!-- 传递指向容器元素的指标 -->
         <!DOCTYPE html>
         <head>
           <script src='p5.js'></script>
        @@ -50,8 +48,7 @@
         </html>
         
         
        -<!-- create an element, attach it to the body,
        -and pass in a pointer -->
        +<!-- 创建一个元素,添加至 body 并传递指标 -->
         <!DOCTYPE html>
         <head>
           <script src='p5.js'></script>
        @@ -72,8 +69,7 @@ and pass in a pointer -->
         </html>
         
         
        -<!-- create an element, pass in a pointer,
        -and attach it to the body -->
        +<!-- 创建一个元素,传递指针并添加到 body -->
         <!DOCTYPE html>
         <head>
           <script src='p5.js'></script>
        diff --git a/src/data/examples/zh-Hans/16_Dom/03_Input_Button.js b/src/data/examples/zh-Hans/16_Dom/03_Input_Button.js
        index 5ec69a29ed..d3aaf9cc42 100644
        --- a/src/data/examples/zh-Hans/16_Dom/03_Input_Button.js
        +++ b/src/data/examples/zh-Hans/16_Dom/03_Input_Button.js
        @@ -1,9 +1,6 @@
         /*
          * @name Input and Button
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Input text and click the button to see it affect the the canvas.
        + * @description Input text and click the button to see it affect the the canvas.
          */
         let input, button, greeting;
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/04_Slider.js b/src/data/examples/zh-Hans/16_Dom/04_Slider.js
        index 0582953c37..6cb48ced1c 100644
        --- a/src/data/examples/zh-Hans/16_Dom/04_Slider.js
        +++ b/src/data/examples/zh-Hans/16_Dom/04_Slider.js
        @@ -1,9 +1,6 @@
         /*
          * @name Slider
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Move the sliders to control the R, G, B values of the background.
        + * @description Move the sliders to control the R, G, B values of the background.
          */
         let rSlider, gSlider, bSlider;
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/07_Modify_DOM.js b/src/data/examples/zh-Hans/16_Dom/07_Modify_DOM.js
        index c784755f29..9ac89b7595 100644
        --- a/src/data/examples/zh-Hans/16_Dom/07_Modify_DOM.js
        +++ b/src/data/examples/zh-Hans/16_Dom/07_Modify_DOM.js
        @@ -1,10 +1,8 @@
         /*
          * @name Modifying the DOM
          * @frame 710,300
        - * @description <p>Create DOM elements and modify their properties every time
        - * draw() is called. You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.</p>
        + * @description Create DOM elements and modify their properties every time
        + * draw() is called.
          */
         let dancingWords = [];
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/08_Video.js b/src/data/examples/zh-Hans/16_Dom/08_Video.js
        index 45454f006b..8786bb4cde 100644
        --- a/src/data/examples/zh-Hans/16_Dom/08_Video.js
        +++ b/src/data/examples/zh-Hans/16_Dom/08_Video.js
        @@ -1,11 +1,8 @@
         /*
          * @name Video
          * @frame 710,250
        - * @description <p>Load a video with multiple formats and toggle between playing
        + * @description Load a video with multiple formats and toggle between playing
          * and paused with a button press.
        - * <p><em><span class="small"> To run this example locally, you will need at least
        - * one video file, and the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.</span></em></p>
          */
         let playing = false;
         let fingers;
        diff --git a/src/data/examples/zh-Hans/16_Dom/09_Video_Canvas.js b/src/data/examples/zh-Hans/16_Dom/09_Video_Canvas.js
        index 8664921d2b..2a59151e06 100644
        --- a/src/data/examples/zh-Hans/16_Dom/09_Video_Canvas.js
        +++ b/src/data/examples/zh-Hans/16_Dom/09_Video_Canvas.js
        @@ -1,9 +1,8 @@
         /*
          * @name Video Canvas
        - * @description <p>Load a video with multiple formats and draw it to the canvas.</p>
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @description Load a video with multiple formats and draw it to the canvas.
        + * To run this example locally, you will need a running 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/10_Video_Pixels.js b/src/data/examples/zh-Hans/16_Dom/10_Video_Pixels.js
        index ba7dcf0638..9169e37a3d 100644
        --- a/src/data/examples/zh-Hans/16_Dom/10_Video_Pixels.js
        +++ b/src/data/examples/zh-Hans/16_Dom/10_Video_Pixels.js
        @@ -1,10 +1,9 @@
         /*
          * @name Video Pixels
          * @frame 320,240
        - * @description <p>Load a video, manipulate its pixels and draw to canvas.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p>
        + * @description Load a video, manipulate its pixels and draw to canvas.
        + * To run this example locally, you will need a running 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
          */
         let fingers;
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/11_Capture.js b/src/data/examples/zh-Hans/16_Dom/11_Capture.js
        index 42733754a3..4e22e6afef 100644
        --- a/src/data/examples/zh-Hans/16_Dom/11_Capture.js
        +++ b/src/data/examples/zh-Hans/16_Dom/11_Capture.js
        @@ -1,13 +1,12 @@
         /*
          * @name Video Capture
          * @frame 710,240
        - * @description <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * at least one video file, and a running <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.</span></em></p><br><br>
        - * Capture video from the webcam and display
        + * @description Capture video from the webcam and display
          * on the canvas as well with invert filter. Note that by
          * default the capture feed shows up, too. You can hide the
          * feed by uncommenting the capture.hide() line.
        + * To run this example locally, you will need a running 
        + * <a href="https://github.com/processing/p5.js/wiki/Local-server">local server</a>.
          */
         let capture;
         
        diff --git a/src/data/examples/zh-Hans/16_Dom/12_Drop.js b/src/data/examples/zh-Hans/16_Dom/12_Drop.js
        index c35f7f554e..a36665e460 100644
        --- a/src/data/examples/zh-Hans/16_Dom/12_Drop.js
        +++ b/src/data/examples/zh-Hans/16_Dom/12_Drop.js
        @@ -1,9 +1,6 @@
         /*
          * @name Drop
        - * @description You will need to include the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.<br><br>
        - * Drag an image file onto the canvas to see it displayed.
        + * @description Drag an image file onto the canvas to see it displayed.
          */
         
         function setup() {
        diff --git a/src/data/examples/zh-Hans/22_Advanced_Data/01_Load_Saved_Table.js b/src/data/examples/zh-Hans/22_Advanced_Data/01_Load_Saved_Table.js
        new file mode 100644
        index 0000000000..8536abcccc
        --- /dev/null
        +++ b/src/data/examples/zh-Hans/22_Advanced_Data/01_Load_Saved_Table.js
        @@ -0,0 +1,110 @@
        +/*
        + * @name Load Saved Table
        + * @description Create a Bubble class, instantiate multiple bubbles using data from
        + * a csv file, and display results on the screen.
        + *  Because the web browsers differ in where they save files, we do not make use of
        + * 
        + * Based on Daniel Shiffman's <a href="https://processing.org/examples/loadsavetable.html">LoadSaveTable Example</a> for Processing.
        + */
        +
        +// Bubble class
        +class Bubble {
        +  constructor(x, y, diameter, name) {
        +    this.x = x;
        +    this.y = y;
        +    this.diameter = diameter;
        +    this.radius = diameter / 2;
        +    this.name = name;
        +
        +    this.over = false;
        +  }
        +
        +  // Check if mouse is over the bubble
        +  rollover(px, py) {
        +    let d = dist(px, py, this.x, this.y);
        +    this.over = d < this.radius;
        +  }
        +
        +  // Display the Bubble
        +  display() {
        +    stroke(0);
        +    strokeWeight(0.8);
        +    noFill();
        +    ellipse(this.x, this.y, this.diameter, this.diameter);
        +    if (this.over) {
        +      fill(0);
        +      textAlign(CENTER);
        +      text(this.name, this.x, this.y + this.radius + 20);
        +    }
        +  }
        +}
        +
        +let table; // Global object to hold results from the loadTable call
        +let bubbles = []; // Global array to hold all bubble objects
        +
        +// Put any asynchronous data loading in preload to complete before "setup" is run
        +function preload() {
        +  table = loadTable("assets/bubbles.csv", "header");
        +}
        +
        +// Convert saved Bubble data into Bubble Objects
        +function loadData() {
        +  const bubbleData = table.getRows();
        +  // The size of the array of Bubble objects is determined by the total number of rows in the CSV
        +  const length = table.getRowCount();
        +
        +  for (let i = 0; i < length; i++) {
        +    // Get position, diameter, name,
        +    const x = bubbleData[i].getNum("x");
        +    const y = bubbleData[i].getNum("y");
        +    const diameter = bubbleData[i].getNum("diameter");
        +    const name = bubbleData[i].getString("name");
        +
        +    // Put object in array
        +    bubbles.push(new Bubble(x, y, diameter, name));
        +  }
        +}
        +
        +// Create a new Bubble each time the mouse is clicked.
        +function mousePressed() {
        +  // Create a new row
        +  let row = table.addRow();
        +
        +  let name = "New Bubble";
        +  let diameter = random(40, 80);
        +
        +  // Set the values of that row
        +  row.setNum("x", mouseX);
        +  row.setNum("y", mouseY);
        +  row.setNum("diameter", diameter);
        +  row.setString("name", name);
        +
        +  bubbles.push(new Bubble(mouseX, mouseY, diameter, name));
        +
        +  // If the table has more than 10 rows
        +  if (table.getRowCount() > 10) {
        +    // Delete the oldest row
        +    table.removeRow(0);
        +    bubbles.shift();
        +  }
        +}
        +
        +function setup() {
        +  createCanvas(640, 360);
        +  loadData();
        +}
        +
        +function draw() {
        +  background(255);
        +
        +  // Display all bubbles
        +  for (let i = 0; i < bubbles.length; i++) {
        +    bubbles[i].display();
        +    bubbles[i].rollover(mouseX, mouseY);
        +  }
        +
        +  // Label directions at bottom
        +  textAlign(LEFT);
        +  fill(0);
        +  text("Click to add bubbles.", 10, height - 10);
        +}
        diff --git a/src/data/examples/zh-Hans/90_Hello_P5/02_interactivity.js b/src/data/examples/zh-Hans/90_Hello_P5/02_interactivity.js
        index 2822149bcf..5bc6687440 100644
        --- a/src/data/examples/zh-Hans/90_Hello_P5/02_interactivity.js
        +++ b/src/data/examples/zh-Hans/90_Hello_P5/02_interactivity.js
        @@ -2,9 +2,6 @@
          * @name Interactivity 1
          * @frame 720,425
          * @description The circle changes color when you click on it.
        - * <p><em><span class="small"> To run this example locally, you will need the
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>.
        - * </em></p>
          */
         
         // for red, green, and blue color values
        diff --git a/src/data/examples/zh-Hans/90_Hello_P5/03_interactivity.js b/src/data/examples/zh-Hans/90_Hello_P5/03_interactivity.js
        index 08af063d3b..6ab965cbe9 100644
        --- a/src/data/examples/zh-Hans/90_Hello_P5/03_interactivity.js
        +++ b/src/data/examples/zh-Hans/90_Hello_P5/03_interactivity.js
        @@ -2,9 +2,6 @@
          * @name Interactivity 2
          * @frame 720,425
          * @description The circle changes color when you move the slider.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
          */
         
         // A HTML range slider
        diff --git a/src/data/examples/zh-Hans/90_Hello_P5/05_weather.js b/src/data/examples/zh-Hans/90_Hello_P5/05_weather.js
        index 321ce86acb..ddcb10a21a 100644
        --- a/src/data/examples/zh-Hans/90_Hello_P5/05_weather.js
        +++ b/src/data/examples/zh-Hans/90_Hello_P5/05_weather.js
        @@ -2,9 +2,6 @@
          * @name Weather
          * @frame 720,280
          * @description This example grabs JSON weather data from apixu.com.
        - * You will need to include the 
        - * <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom library</a>
        - * for this example to work in your own project.
         */
         
         // A wind direction vector
        diff --git a/src/data/ko.txt b/src/data/ko.txt
        deleted file mode 100644
        index ced7f1a8fe..0000000000
        --- a/src/data/ko.txt
        +++ /dev/null
        @@ -1,633 +0,0 @@
        -Skip-To-Content: "Skip to content"
        -Language-Settings: "Language Settings"
        -Sidebar-Title: "Site Navigation"
        -Home: "홈"
        -Editor: "Editor"
        -Download: "다운로드"
        -Start: "시작하기"
        -Reference: "레퍼런스"
        -Libraries: "라이브러리"
        -Learn: "학습"
        -Examples: "예제"
        -Books: "관련 책"
        -Community: "커뮤니티"
        -Contribute: "기여하기"
        -Forum: "포럼"
        -
        -footerxh1: "Credits"
        -footer1: "p5.js는 "
        -footer2: "에 의해 설립되고 커뮤니티 구성원들에 의해 개발되었으며 "
        -footer3: " 과 "
        -footer4: "의 후원을 받았습니다. 아이덴티티, 그래픽디자인 : "
        -
        -tagline1: "Processing의 즐거움에 JavaScript의 매력을 곱하다"
        -tagline2: "Processing의 간명함에 JavaScript의 유연성을 곱하다"
        -tagline3: "Processing의 직관성에 JavaScript의 강력함을 곱하다"
        -tagline4: "Processing의 창조성에 JavaScript의 활력을 곱하다"
        -tagline5: "Processing 커뮤니티에 JavaScript 커뮤니티를 곱하다"
        -tagline6: "Processing의 강력함에 JavaScript의 범용성을 곱하다"
        -
        -home:
        -  start-creating: "Start creating with the p5 Editor!"
        -  p1xh1: "Hello!"
        -  p1x1: "p5.js is a JavaScript library for creative coding, with a focus on making coding accessible and inclusive for artists, designers, educators, beginners, and anyone else! p5.js is free and open-source because we believe software, and the tools to learn it, should be accessible to everyone."
        -  p1x2: "Using the metaphor of a sketch, p5.js has a full set of drawing functionality. However, you’re not limited to your drawing canvas. You can think of your whole browser page as your sketch, including HTML5 objects for text, input, video, webcam, and sound."
        -  p2xh2: "Community"
        -  p2x1: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
        -  p2x2: "p5.js is an interpretation of "
        -  p2x3: " for today’s web. We hold events and operate with support from the "
        -  p2x4: "."
        -  p2x5: "Learn more about "
        -  p2x6: "our community"
        -  p2x7: "."
        -
        -  p3xh2: "Get Started"
        -  p3xp1: "Make your first sketch in the "
        -  p3xp2: ". Learn more about sketching with p5.js on the "
        -  p3xp3: "Get Started page"
        -  p3xp4: " and everything you can do in the "
        -  p3xp5: "Reference"
        -  p3xp6: "."
        -
        -  p4xh2: "Get Involved"
        -  p4xp1: "There are many ways to contribute to p5.js:"
        -  p4xp2: "Involvement Options"
        -  p4xp3: "Share something you've made!"
        -  p4xp4: "Teach a workshop or class."
        -  p4xp5: "Organize a meet-up."
        -  p4xp6: "Contribute to the codebase."
        -
        -  sketch_by: "by"
        -  sketch_info: "Homepage sketch adapted from work by 9th grader Grace Obergfell"
        -  sketch_info_link: "CC Fest NYC on June 8, a free and inclusive coding event for students and teachers"
        -
        -copyright:
        -  copyright-title: "Copyright Information"
        -  copyright1: "The p5.js library is free software; you can redistribute it and/or modify it under the terms of the "
        -  copyright2: " as published by the Free Software Foundation, version 2.1."
        -  copyright3: "The Reference for the language is under a "
        -  copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited."
        -
        -get started:
        -  get-started-title: "시작하기"
        -  get-started1: "본 페이지는 p5.js 프로젝트를 셋업하고 나의 첫 스케치를 만드는 방법을 소개합니다."
        -  get-started2: ""
        -  get-started3: "p5.js 웹에디터"
        -  get-started4: "를 사용한다면, 아래 두 항목를 생략하고 이곳으로 건너뛰세요:"
        -  get-started5: "첫 스케치 만들기"
        -  download-title: "다운로드, 파일 셋업"
        -  download1: "가장 쉬운 방법은 "
        -  download2: "p5.js complete"
        -  download3: "와 함께 제공되는 빈 예제파일을 이용하는 것입니다."
        -  download4: "index.html 파일을 살펴보세요. index.html 파일이 p5.js 링크를 포함하고 있죠? 만약 빠른 로딩을 위해 압축된 간략 버전을 이용하고 싶다면, 아래와 같이 p5.js 링크를 p5.min.js로 변경하면 됩니다."
        -  download5: "혹은, 온라인에 저장된 p5.js 파일에 링크를 하는 방법도 있습니다. p5.js의 모든 버전은 CDN (Content Delivery Network)에 저장되어 있으며, 버전들의 히스토리는 이곳에서 보실 수 있습니다: "
        -  download6: ". 이 방법을 따르는 경우, 링크를 다음과 같이 변경하세요:"
        -  download7: "아래는 HTML 페이지 샘플입니다:"
        -  download8: "위 HTML 페이지 템플릿을 코드펜(codepen)에 붙여넣어 프로젝트를 시작하는 것도 한 방법입니다: "
        -  download9: "."
        -  environment-title: "개발환경"
        -  environment1: "어떠한 것이든, 당신이 선호하는 "
        -  environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor"
        -  environment2: "코드 에디터"
        -  environment3: "를 사용하면 됩니다. 아래에 "
        -  environment4: "에서 세팅하는 경우에 대한 설명이 있습니다. "
        -  environment5: " 과 "
        -  environment6: "또한 추천할만한 에디터입니다. 당신이 스크린리더 유저인데 p5 웹에디터를 이용하지 않는다면, 다음의 에디터들을 고려해보세요: "
        -  environment7: " 나 "
        -  environment8: "먼저, Sublime 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, 당신의 html 파일과 js 파일이 위치한 폴더를 선택하세요. 폴더 이름과 폴더에 포함된 파일 리스트가 왼쪽 사이드바에 보일 것입니다"
        -  environment9: "sketch.js 파일을 선택하면, 오른쪽 편집 영역에서 파일이 열립니다. "
        -  environment10: "Sublime 에디터에서 p5 템플릿 코드를 편집중인 화면"
        -  environment11: "index.html 파일을 브라우저에서 열어볼까요? 파일 관리 시스템에서 index.html 파일을 더블클릭하거나 브라우저 주소창에 다음을 입력하세요:"
        -  environment12: "file:///the/file/path/to/your/html"
        -  environment13: ""
        -  your-first-sketch-title: "나의 첫 스케치"
        -  your-first-sketch-intro1: "Processing 사용자라면, 다음의 페이지를 읽어보세요: "
        -  your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  your-first-sketch-intro3: "Processing에서 p5.js로 이전하기 튜토리얼"
        -  your-first-sketch-intro4: "에디터에 다음을 입력하세요:"
        -  your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다. \"왼쪽 위 모서리에서 아래로 50px, 오른쪽으로 50px 떨어진 위치를 중심으로 하는 타원을 그린다. 타원의 폭과 높이는 동일하게 80px로 한다.\""
        -  your-first-sketch3: "스케치 저장 후, 브라우저 페이지에서 새로고침을 해보세요. 입력한 코드에 문제가 없는 한, 다음과 같은 화면을 보실겁니다:"
        -  your-first-sketch4: "주의: 스크린리더를 사용하는 경우, p5 웹에디터에서 Accessibile Outputs를 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: "
        -  your-first-sketch5: "스크린리더에서 p5를 사용하는 방법"
        -  your-first-sketch6: ", "
        -  your-first-sketch7: "접근성 라이브러리란?"
        -  your-first-sketch8: "캔버스에 폭과 높이가 50인 타원이 x 80, y 80의 위치에 그려져있다"
        -  your-first-sketch9: "코드를 제대로 입력하지 않았다면, 화면에 아무것도 나타나지 않을 수 있습니다. 이러한 경우, 예제 코드를 정확하게 따라 썼는지 확인하세요. 숫자는 괄호 안에 포함하되 각 숫자는 쉼표로 구분해야 하고, 각 라인은 세미콜론을 끝나야 합니다."
        -  your-first-sketch10: "프로그래밍을 시작할 때 가장 어려운 것 중 하나는 문법이 매우 까다롭다는 점입니다. 브라우저는 사용자가 의미하는 바가 무엇인지 이해할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감합니다. 처음에는 이런 점들이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바스크립트 '콘솔'을 제공합니다. 크롬의 경우, 보기 > 개발자 > 자바스크립트 콘솔을 클릭해 '콘솔'을 활성화하할 수 있습니다."
        -  your-first-sketch11: "이제 한층 더 재미있는 스케치를 만들 차례입니다다. 지난 예제의 코드를 삭제하고 다음의 코드를 입력해 보세요:"
        -  your-first-sketch12: "이 프로그램은 폭이 640px이고 높이가 480인 캔버스를 생성하고, 마우스 커서 위치에서 흰 원을 그리기 시작합니다. 마우스 버튼을 누르고 있을 때는 원의 색이 검정색으로 바뀝니다. 마우스 위치에 대한 설명은 추후에 더 하기로 하고, 일단 여기서는 코드를 실행하고 마우스를 움직이고 클릭하며 스케치의 변화를 살펴보세요."
        -  your-first-sketch13: "캔버스에 마우스 궤적을 따라 여러개의 원이 그려져있다"
        -  first-sketch-heading1: "Code snippet with ellipse"
        -  first-sketch-heading2: "Note for screenreader users"
        -  first-sketch-heading3: "Code snippet with interaction"
        -  what-next-title: "다음 단계"
        -  processing-transition1: "Processing을 p5.js로 전환하려면 어떻게 해야하며, 둘이 어떻게 다른지 궁금하다면, "
        -  processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  processing-transition3: "Processing에서 p5.js로 이전하기 튜토리얼"
        -  processing-transition4: "을 읽어보세요."
        -  reference1: "p5.js에 대한 전체 다큐멘테이션을 보려면, "
        -  reference2: "레퍼런스"
        -  reference3: "를 읽어보세요."
        -  learn1: "더 많은 정보가 필요하다면, "
        -  learn2: "학습"
        -  learn3: " 페이지와 "
        -  learn4: "예제"
        -  learn5: " 페이지를 살펴보세요."
        -  learn6: "스크린리더에서 p5를 사용하고 싶다면, 다음 페이지를 읽어보세요: "
        -  learn7: "스크린리더에서 p5 사용하기 튜토리얼"
        -  book1: "Parts of this tutorial were adapted from the book, Getting Started with p5.js, by Lauren McCarthy, Casey Reas, and Ben Fry, O'Reilly / Make. Copyright © 2015. All rights reserved."
        -
        -download:
        -  Download: "Download"
        -  download-intro: "Welcome! While titled \"Download\" this page actually contains a collection of links to either download the library or begin working with it online. We've tried to order things to reflect what a beginner might want first, to resources that more experienced programmers may be looking for."
        -  editor-title: "Editor"
        -  p5.js-editor: "p5.js Editor"
        -  p5.js-editor-intro: "This link redirects you to the p5.js Editor online so you can begin using p5.js immediately."
        -  editor-includes: "Start coding using the p5.js Editor, no setup required!"
        -  complete-library-title: "Complete Library"
        -  complete-library-intro1: "This is a download containing the p5.js library file, the p5.sound addon, and an example project. It does not contain an editor. See "
        -  complete-library-intro2: "Get Started"
        -  complete-library-intro3: " to learn how to setup a p5.js project."
        -  p5.js-complete: "p5.js complete"
        -  includes-1: "Includes:"
        -  includes-2: "p5.js, p5.sound.js, and an example project"
        -  includes-3: "Version "
        -  single-files-title: "Single Files"
        -  single-files-intro: "These are downloads or links to the p5.js library file. No additional contents are included."
        -  single-file: "Single file: "
        -  p5.js-uncompressed: "Full uncompressed version"
        -  compressed: "Compressed version"
        -  link: "Link: "
        -  statically-hosted-file: "Statically hosted file"
        -  etc-title: "Github Resources"
        -  older-releases: "Previous versions (older releases and changelog)"
        -  github-repository: "Code repository (GitHub)"
        -  report-bugs: "Report issues, bugs, and errors"
        -  supported-browsers: "Supported browsers "
        -
        -  support-title: "Support p5.js!"
        -  support-options: "Support Options"
        -  support-1: "p5.js is free, open-source software. We want to make our community as open and inclusive as possible. You can support this work by "
        -  support-2: "becoming a member"
        -  support-3: " of the Processing Foundation as an individual, a studio, or an educational institution. You can also "
        -  support-4: "make a donation"
        -  support-5: " without purchasing a membership."
        -  support-6: "Individual"
        -  support-7: "$25"
        -  support-8: "Studio"
        -  support-9: "$250"
        -  support-10: "Educational Institution"
        -  support-11: "$5/student or $500"
        -  support-12: "Your membership supports software development (for p5.js, Processing, Processing.py, Processing for Android and ARM devices, education resources like code examples and tutorials, "
        -  support-13: "Fellowships"
        -  support-14: ", and "
        -  support-15: "community events"
        -  support-16: ". We need your help!"
        -  support-17: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)"
        -  support-18: "Processing Fellow Saskia Freeke is organizing Code Liberation x Processing workshops in London (Image credit: Code Liberation Foundation)"
        -  support-19: "Learning to Teach, Teaching to Learn conference with SFPC (Image credit: Kira Simon-Kennedy)"
        -  support-20: "Processing Foundation Fellow Cassie Tarakajian's workshop at Code Art Miami (Image credit: Christian Arévalo Photography)"
        -  support-21: "Taeyoon Choi and ASL interpretor at Signing Coders p5.js workshop (Image credit: Taeyoon Choi)"
        -  support-22: "Google Summer of Code kickoff (Image credit: Taeyoon Choi)"
        -  support-23: "Processing Foundation Fellow Cassie Tarakajian's workshop at Code Art Miami (Image credit: Christian Arévalo Photography)"
        -  support-24: "Luisa Pereira and Yeseul Song helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        -  support-25: "p5.js Contributors Conference at CMU STUDIO for Creative Inquiry in Pittsburgh (Image credit: Taeyoon Choi)"
        -  support-26: "Processing Fellow Digital Citizens Lab hosts a panel on STEM teaching at the International Center of Photography (Image credit: International Center of Photography)"
        -  support-27: "Participants at p5.js workshop in Santiago, Chile, led by Aarón Montoya-Moraga (Image credit: Aarón Montoya-Moraga.)"
        -  support-28: "Claire Kearney-Volpe helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        -  support-29: "Processing Foundation Fellow DIY Girls run a creative coding program in Los Angeles (Image credit: DIY Girls)"
        -  support-30: "Processing Fellow Digital Citizens Lab"
        -  support-31: "Bicoastal p5.js meetup at UCLA DMA and NYU ITP"
        -  support-32: "The Processing Foundation"
        -  support-33: " was founded in 2012 after more than a decade of work with the original Processing software. The Foundation’s mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources."
        -  support-17-alt: ""
        -  support-18-alt: ""
        -  support-19-alt: ""
        -  support-20-alt: ""
        -  support-21-alt: ""
        -  support-22-alt: ""
        -  support-23-alt: ""
        -  support-24-alt: ""
        -  support-25-alt: ""
        -  support-26-alt: ""
        -  support-27-alt: ""
        -  support-28-alt: ""
        -  support-29-alt: ""
        -  support-30-alt: ""
        -  support-30-alt: ""
        -  support-31-alt: ""
        -
        -learn:
        -  learn-title: "학습"
        -  learn1: "These tutorials provide more in-depth or step-by-step overviews of particular topics. Check out the "
        -  learn2: "examples page"
        -  learn3: "to see short demonstrations of various p5.js topics."
        -  introduction-to-p5js-title: "Introduction to p5.js"
        -  hello-p5js-title: "Hello p5.js"
        -  hello-p5js: "This short video will introduce you to the library and what you can do with it."
        -  getting-started-title: "Getting Started"
        -  getting-started: "Welcome to p5.js! <br> This introduction covers the basics of setting up a p5.js project."
        -  p5js-overview-title: "p5.js overview"
        -  p5js-overview: "An overview of the main features of p5.js."
        -  p5js-processing-title: "p5.js and Processing"
        -  p5js-processing: "The main differences between the two, and how to convert from one to the other."
        -  p5-screen-reader-title: "p5 with a screen reader"
        -  p5-screen-reader: "Setting up p5 so that it can be used easily with a screen reader."
        -  using-local-server-title: "Using a local server"
        -  using-local-server: "How to set up a local server on Mac OSX, Windows, or Linux."
        -  connecting-p5js-title: "Connecting p5.js"
        -  creating-libraries-title: "Creating libraries"
        -  creating-libraries: "Creating p5.js addon libraries."
        -  nodejs-and-socketio-title: "node.js and socket.io"
        -  nodejs-and-socketio: "Using a node.js server with p5.js, communication via socket.io."
        -  programming-topics-title: "Programming topics"
        -  beyond-the-canvas-title: "Beyond the canvas"
        -  beyond-the-canvas: "Creating and manipulating elements on the page beyond the canvas."
        -  3d-webgl-title: "3D/WebGL"
        -  3d-webgl: "Developing advanced graphics applications in p5.js using WEBGL mode."
        -  color-title: "Color"
        -  color: "An introduction to digital color."
        -  coordinate-system-and-shapes-title: "Coordinate System and Shapes"
        -  coordinate-system-and-shapes: "Drawing simple shapes and using the coordinate system."
        -  interactivity-title: "Interactivity"
        -  interactivity: "Introduction to interactivity with the mouse and keyboard."
        -  program-flow-title: "Program Flow"
        -  program-flow: "Introduction to controlling program flow in p5.js."
        -  curves-title: "Curves"
        -  curves: "An introduction to the three types of curves in p5.js: arcs, spline curves, and Bézier curves."
        -  becoming-a-better-programmer-title: "Becoming a better programmer"
        -  debugging-title: "Debugging"
        -  debugging: "Field guide to debugging for everyone."
        -  optimizing-title: "Optimizing p5.js code for performance"
        -  optimizing: "A tutorial of tips and tricks for optimizing your code to make it run faster and smoother."
        -  test-driven-development-title: "Unit testing and test driven development"
        -  test-driven-development: "Save yourself from agony on install day. What is unit testing and how to use it? By Andy Timmons."
        -  contributing-to-the-community-title: "Contributing to the community"
        -  development-title: "Development"
        -  development: "Getting started and overview for contributing to development."
        -  looking-inside-title: "Looking inside p5"
        -  looking-inside: "A friendly intro to the file structure and tools for p5.js development, by Luisa Pereira."
        -  writing-tutorial-title: "Writing a tutorial"
        -  writing-tutorial: "A guide to writing a p5.js programming tutorial."
        -  writing-a-tutorial-title: "Guide to contributing p5.js tutorials"
        -  writing-a-tutorial-author: "This tutorial was written by Tega Brain."
        -  writing-a-tutorial-1: "We invite educators, contributors and general enthusiasts to contribute p5js tutorials. The p5js project makes creative coding and open source development more accessible to a diverse community and we are excited to publish tutorials on all aspects of the development process. Our learning materials so far include guides on learning p5, programming technique and how to contribute to an open source project."
        -  writing-a-tutorial-2: "We welcome new written tutorial contributions and this guide outlines the steps of how to propose, prepare and contribute."
        -  writing-a-tutorial-how-start-title: "How to get started:"
        -  writing-a-tutorial-how-start-1: "Check that your proposed topic has not already been covered. There is "
        -  writing-a-tutorial-how-start-2: "a working spreadsheet here"
        -  writing-a-tutorial-how-start-3: "that outlines in progress tutorials. If your topic is listed as in progress, perhaps you can add to work being done and contribute to preparing existing work for publication so please reach out to us."
        -  writing-a-tutorial-how-start-4: "If your topic is not already covered and is not listed as in progress, please write a few sentences on what you propose to cover and email us this description at education@p5js.org."
        -  writing-a-tutorial-how-prepare-title: "How to prepare a p5js tutorial for publication online:"
        -  writing-a-tutorial-how-prepare-1: "When your tutorial is ready for publication, please follow these steps to prepare your content for the p5js website."
        -  writing-a-tutorial-how-prepare-2: "Prepare the content of your tutorial as a tutorial-name.hbs file with "
        -  writing-a-tutorial-how-prepare-3: "this basic structure"
        -  writing-a-tutorial-how-prepare-4: ". As is shown in this file, it must contain a header as shown below:"
        -  writing-a-tutorial-how-prepare-5: "The folder containing your tutorial will be placed in the 'tutorials' folder of the p5js site. The file called index.hbs is the "
        -  writing-a-tutorial-how-prepare-6: "p5.js tutorials landing page,"
        -  writing-a-tutorial-how-prepare-7: " and the test-tutorial.hbs file is the test tutorial."
        -  writing-a-tutorial-how-prepare-8: "All content should go in the:"
        -  writing-a-tutorial-how-prepare-9: "tags on the page, with formatting defined by the &lt;h1&gt; and &lt;h2&gt; tags, the &lt;p&gt; paragraph tags as is done shown on the"
        -  writing-a-tutorial-how-prepare-10: "test tutorial page."
        -  writing-a-tutorial-how-prepare-11: "If your tutorial contains images, they are to be placed in the assets folder of the p5 site, in the location src/assets/learn/test-tutorial/images as shown below."
        -  writing-a-tutorial-how-prepare-12: "To correctly format code in the html of the page use the tag:"
        -  writing-a-tutorial-embedding-title: "Embedding p5.js sketches"
        -  writing-a-tutorial-embedding-1: "Using p5js means you can illustrate your tutorial with animated, interactive or editable code examples to demonstrate programming concepts. Your examples should be prepared as p5.js sketches and can be embedded into the tutorial in two ways."
        -  writing-a-tutorial-embedding-2: "If the example is to be editable like in "
        -  writing-a-tutorial-embedding-3: "the reference pages"
        -  writing-a-tutorial-embedding-4: " of the p5js site, the p5 sketch should be embedded into the html page using the p5js widget. Follow "
        -  writing-a-tutorial-embedding-5: "this guide "
        -  writing-a-tutorial-embedding-6: "on how to embed p5js sketches using the widget written by "
        -  writing-a-tutorial-embedding-7: ". You can also see this in action on the"
        -  writing-a-tutorial-embedding-8: " test tutorial page"
        -  writing-a-tutorial-embedding-9: "."
        -  writing-a-tutorial-embedding-10: "If the example is to be animated and/or interactive but not editable. The p5.js sketch should be embedded into the page as an iframe as described below."
        -  writing-a-tutorial-iframe-title: "Embed a p5 sketch using an iframe"
        -  writing-a-tutorial-iframe-1: "An iframe is like creating a window through which you can see another page, sandboxed from the rest of your page. In this case it will be a window to the index.html containing your p5.js sketch. "
        -  writing-a-tutorial-iframe-2: "Put your p5 sketches in the /src/assets/learn folder of the site, in a folder labelled with the name of your sketch as shown in the screenshot. This is where all the images and p5 sketches linked by iframe should be stored."
        -  writing-a-tutorial-iframe-3: "In the subfolders containing your p5 examples there should be a sketch.js file and the embed.html file for the sketch. "
        -  writing-a-tutorial-iframe-4: "Make sure your embed.html file has the correct paths to the p5 libraries of the site. If your file structure is the same as above, the path to the p5.js library should be \"../../../js/p5.min.js\"."
        -  writing-a-tutorial-iframe-5: "You can then embed the p5js index files as iframes in the .hbs file that contains your tutorial content. The embed code for the iframe would then be: "
        -  writing-a-tutorial-iframe-6: "Styling for the iframe (this could directly into the post or in a stylesheet):  "
        -  writing-a-tutorial-iframe-7: "Here you can see the naked sketch running: "
        -  writing-a-tutorial-iframe-8: "And here it is embedded in the p5 site using the code below:  "
        -  writing-a-tutorial-iframe-9: "One thing to note is that you need to manually set the size of the iframe, so it works best if things are a standard size."
        -  writing-a-tutorial-iframe-10: "Also note that the links to the p5.js library files do not happen from the .eps page with all the tutorial content. Instead they will be located in the html page that is rendering your sketch (in this case, called embed.html)."
        -  writing-a-tutorial-iframe-11: "More information on embedding p5.js sketches can be found "
        -  writing-a-tutorial-embed-iframe-12: "here."
        -  writing-a-tutorial-finishing-title: "Finishing up"
        -  writing-a-tutorial-finishing-1: "Once your have finished writing your tutorial and your content has been given the thumbs up. Fork the p5.js website repository, prepare your content as described above and then issue a pull request to the p5.js website repository so we can publish your contribution!"
        -  writing-a-tutorial-finishing-2: "Thank you!"
        -  color-description1: "This tutorial is from the book Learning Processing by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to P5 by Kelly Chang. If you see any errors or have comments, "
        -  color-description2: " please let us know."
        -  color-title: "Color"
        -  color-p1x1: "In the digital world, when we want to talk about a color, precision is required. Saying \"Hey, can you make that circle bluish-green?\" will not do. Color, rather, is defined as a range of numbers. Let's start with the simplest case: black & white or grayscale. 0 means black, 255 means white. In between, every other number—50, 87, 162, 209, and so on—is a shade of gray ranging from black to white."
        -  color-p2x1: "By adding the "
        -  color-p2x2: " and "
        -  color-p2x3: " functions before something is drawn, we can set the color of any given shape. There is also the function "
        -  color-p2x4: ", which sets a background color for the window. Here's an example."
        -  color-code1: "background(255);    // Setting the background to white \n stroke(0);          // Setting the outline (stroke) to black \n fill(150);          // Setting the interior of a shape (fill) to grey \n rect(50,50,75,100); // Drawing the rectangle"
        -  color-p3x1: "Stroke or fill can be eliminated with the functions: "
        -  color-p3x2: " and "
        -  color-p3x3: ". Our instinct might be to say \"stroke(0)\" for no outline, however, it is important to remember that 0 is not \"nothing\", but rather denotes the color black. Also, remember not to eliminate both—with "
        -  color-p3x4: " and "
        -  color-p3x5: ", nothing will appear!"
        -  color-p4x1: "In addition, if we draw two shapes, p5.js will always use the most recently specified stroke and fill, reading the code from top to bottom."
        -  color-rgb-title: "RGB Color"
        -  color-rgb-p1x1: "Remember finger painting? By mixing three \"primary\" colors, any color could be generated. Swirling all colors together resulted in a muddy brown. The more paint you added, the darker it got. Digital colors are also constructed by mixing three primary colors, but it works differently from paint. First, the primaries are different: red, green, and blue (i.e., \"RGB\" color). And with color on the screen, you are mixing light, not paint, so the mixing rules are different as well."
        -  color-rgb-li1: "Red + Green = Yellow"
        -  color-rgb-li2: "Red + Blue = Purple"
        -  color-rgb-li3: "Green + Blue = Cyan (blue-green)"
        -  color-rgb-li4: "Red + Green + Blue = White"
        -  color-rgb-li5: "No colors = Black"
        -  color-rgb-p2x1: "This assumes that the colors are all as bright as possible, but of course, you have a range of color available, so some red plus some green plus some blue equals gray, and a bit of red plus a bit of blue equals dark purple. While this may take some getting used to, the more you program and experiment with RGB color, the more it will become instinctive, much like swirling colors with your fingers. And of course you can't say \"Mix some red with a bit of blue,\" you have to provide an exact amount. As with grayscale, the individual color elements are expressed as ranges from 0 (none of that color) to 255 (as much as possible), and they are listed in the order R, G, and B. You will get the hang of RGB color mixing through experimentation, but next we will cover some code using some common colors."
        -  color-transparency-title: "Color Transparency"
        -  color-transparency-p1x1: "In addition to the red, green, and blue components of each color, there is an additional optional fourth component, referred to as the color's \"alpha\". Alpha means transparency and is particularly useful when you want to draw elements that appear partially see-through on top of one another. The alpha values for an image are sometimes referred to collectively as the \"alpha channel\" of an image."
        -  color-transparency-p2x1: "It is important to realize that pixels are not literally transparent, this is simply a convenient illusion that is accomplished by blending colors. Behind the scenes, p5.js takes the color numbers and adds a percentage of one to a percentage of another, creating the optical perception of blending. (If you are interested in programming \"rose-colored\" glasses, this is where you would begin.)"
        -  color-transparency-p3x1: "Alpha values also range from 0 to 255, with 0 being completely transparent (i.e., 0% opaque) and 255 completely opaque (i.e., 100% opaque)."
        -  color-custom-ranges-title: "Custom Color Ranges"
        -  color-custom-ranges-p1x1: "RGB color with ranges of 0 to 255 is not the only way you can handle color in p5.js, in fact, it allows us to think about color any way we like. For example, you might prefer to think of color as ranging from 0 to 100 (like a percentage). You can do this by specifying a custom "
        -  color-custom-ranges-p2x1: "The above function says: \"OK, we want to think about color in terms of red, green, and blue. The range of RGB values will be from 0 to 100.\""
        -  color-custom-ranges-p3x1: "Although it is rarely convenient to do so, you can also have different ranges for each color component:"
        -  color-custom-ranges-p4x1: "Now we are saying \"Red values go from 0 to 100, green from 0 to 500, blue from 0 to 10, and alpha from 0 to 255.\""
        -  color-custom-ranges-p5x1: "Finally, while you will likely only need RGB color for all of your programming needs, you can also specify colors in the HSB (hue, saturation, and brightness) mode. Without getting into too much detail, HSB color works as follows:"
        -  color-custom-ranges-li1x1: "Hue"
        -  color-custom-ranges-li1x2: "—The color type, ranges from 0 to 255 by default."
        -  color-custom-ranges-li2x1: "Saturation"
        -  color-custom-ranges-li2x2: "—The vibrancy of the color, 0 to 255 by default."
        -  color-custom-ranges-li3x1: "Brightness"
        -  color-custom-ranges-li3x2: "—The, well, brightness of the color, 0 to 255 by default."
        -  color-custom-ranges-p6x1: "With "
        -  color-custom-ranges-p6x2: " you can set your own ranges for these values. Some prefer a range of 0-360 for hue (think of 360 degrees on a color wheel) and 0-100 for saturation and brightness (think of 0-100%)."
        -  coordinate-system-description1: "This tutorial is from the book "
        -  coordinate-system-description2: "Learning Processing"
        -  coordinate-system-description3: " by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. It was ported to p5.js by Alex Yixuan Xu. If you see any errors or have comments, please "
        -  coordinate-system-description4: "let us know"
        -  coordinate-system-description5: "."
        -  coordinate-system-description-title: "Coordinate System and Shapes"
        -  coordinate-system-description-p1x1: "Before we begin programming with p5, we must first channel our eighth grade selves, pull out a piece of graph paper, and draw a line. The shortest distance between two points is a good old fashioned line, and this is where we begin, with two points on that graph paper."
        -  coordinate-system-description-p2x1: "The above figure shows a line between point A (1,0) and point B (4,5). If you wanted to direct a friend of yours to draw that same line, you would give them a shout and say \"draw a line from the point one-zero to the point four-five, please.\" Well, for the moment, imagine your friend was a computer and you wanted to instruct this digital pal to display that same line on its screen. The same command applies (only this time you can skip the pleasantries and you will be required to employ a precise formatting). Here, the instruction will look like this:"
        -  coordinate-system-description-p3x1: "Even without having studied the syntax of writing code, the above statement should make a fair amount of sense. We are providing a command (which we will refer to as a \"function\") for the machine to follow entitled \"line.\" In addition, we are specifying some arguments for how that line should be drawn, from point A (1,0) to point B (4,5). If you think of that line of code as a sentence, the function is a verb and the arguments are the objects of the sentence. The code sentence also ends with a semicolon instead of a period."
        -  coordinate-system-description-p4x1: "The key here is to realize that the computer screen is nothing more than a fancier piece of graph paper. Each pixel of the screen is a coordinate - two numbers, an \"x\" (horizontal) and a \"y\" (vertical) - that determines the location of a point in space. And it is our job to specify what shapes and colors should appear at these pixel coordinates."
        -  coordinate-system-description-p5x1: "Nevertheless, there is a catch here. The graph paper from eighth grade (\"Cartesian coordinate system\") placed (0,0) in the center with the y-axis pointing up and the x-axis pointing to the right (in the positive direction, negative down and to the left). The coordinate system for pixels in a computer window, however, is reversed along the y-axis. (0,0) can be found at the top left with the positive direction to the right horizontally and down vertically."
        -  coordinate-system-simple-shapes-title: "Simple Shapes"
        -  coordinate-system-simple-shapes-p1x1: "The vast majority of the programming examples you'll see with p5 are visual in nature. These examples, at their core, involve drawing shapes and setting pixels. Let's begin by looking at four primitive shapes."
        -  coordinate-system-simple-shapes-p2x1: "For each shape, we will ask ourselves what information is required to specify the location and size (and later color) of that shape and learn how p5 expects to receive that information. In each of the diagrams below, we'll assume a window with a width of 100 pixels and height of 100 pixels."
        -  coordinate-system-simple-shapes-p3x1: "A "
        -  coordinate-system-simple-shapes-p3x2: " is the easiest of the shapes and a good place to start. To draw a point, we only need an x and y coordinate."
        -  coordinate-system-simple-shapes-p4x1: "A "
        -  coordinate-system-simple-shapes-p4x2: " isn't terribly difficult either and simply requires two points: (x1,y1) and (x2,y2):"
        -  coordinate-system-simple-shapes-p5x1: "Once we arrive at drawing a "
        -  coordinate-system-simple-shapes-p5x2: ", things become a bit more complicated. In p5, a rectangle is specified by the coordinate for the top left corner of the rectangle, as well as its width and height."
        -  coordinate-system-simple-shapes-p6x1: "A second way to draw a rectangle involves specifying the centerpoint, along with width and height. If we prefer this method, we first indicate that we want to use the "
        -  coordinate-system-simple-shapes-p6x2: " mode before the instruction for the rectangle itself. Note that p5 is case-sensitive."
        -  coordinate-system-simple-shapes-p7x1: "Finally, we can also draw a rectangle with two points (the top left corner and the bottom right corner). The mode here is "
        -  coordinate-system-simple-shapes-p7x2: ". Note this example gives the same result on screen as the example above."
        -  coordinate-system-simple-shapes-p8x1: "Once we have become comfortable with the concept of drawing a rectangle, an "
        -  coordinate-system-simple-shapes-p8x2: " is a snap. In fact, it is identical to "
        -  coordinate-system-simple-shapes-p8x3: " with the difference being that an ellipse is drawn where the bounding box of the rectangle would be. The default mode for "
        -  coordinate-system-simple-shapes-p8x4: " is "
        -  coordinate-system-simple-shapes-p8x5: ", rather than "
        -  coordinate-system-simple-shapes-p8x6: "."
        -  coordinate-system-simple-shapes-p9x1: "Now let's look at what some code with shapes in more complete form, with canvas dimensions of 200 by 200. Note the use of the createCanvas() function to specify the width and height of the canvas."
        -
        -test-tutorial:
        -
        -libraries:
        -  Libraries: "Libraries"
        -  core-libraries: "Core Libraries"
        -  community-libraries: "Community Libraries"
        -  libraries-created-by: "Created by:"
        -  p5.sound: "p5.sound extends p5 with Web Audio functionality including audio input, playback, analysis and synthesis."
        -  p5.accessibility: "p5.accessibility makes the p5 canvas more accessible to people who are blind and visually impaired."
        -  asciiart: "p5.asciiart is a simple and easy to use image - to - ASCII art converter for p5js."
        -  p5.ble: "A Javascript library that enables communication between BLE devices and p5 sketches."
        -  blizard.js: "a library for making DOM manipulation simple"
        -  p5.bots: "With p5.bots you can interact with your Arduino (or other microprocessor) from within the browser. Use sensor data to drive a sketch; use a sketch to drive LEDs, motors, and more! Created by "
        -  p5.clickable: "Event driven, easy-to-use button library for p5.js."
        -  p5.cmyk.js: "CMYK ColorSpace"
        -  p5.collide2D: "p5.collide2D provides tools for calculating collision detection for 2D geometry with p5.js."
        -  p5.createloop: "Create animation loops with noise and GIF exports in one line of code."
        -  p5.dimensions: "p5.dimensions extends p5.js' vector functions to work in any number of dimensions."
        -  p5.EasyCam: "Simple 3D camera control with inertial pan, zoom, and rotate. Major contributions by Thomas Diewald."
        -  p5.experience: "Extensive library for p5.js that adds additional event-listening functionality for creating canvas-based web applications."
        -  p5.func: "p5.func is a p5 extension that provides new objects and utilities for function generation in the time, frequency, and spatial domains."
        -  p5.geolocation: "p5.geolocation provides techniques for acquiring, watching, calculating, and geofencing user locations for p5.js."
        -  p5.gibber: "p5.gibber provides rapid music sequencing and audio synthesis capabilities."
        -  grafica.js: "grafica.js lets you add simple but highly configurable 2D plots to your p5.js sketches."
        -  p5.gui: "p5.gui generates a graphical user interface for your p5.js sketches."
        -  p5.localmessage: "p5.localmessage provides a simple interface to send messages locally from one sketch to another for easy multi-window sketching!"
        -  marching: "Raster to vector conversion, isosurfaces."
        -  mappa: "Mappa provides a set of tools for working with static maps, tile maps, and geo-data. Useful when building geolocation-based visual representations."
        -  ml5.js: "ml5.js builds on Tensorflow.js and provides friendly access to machine learning algorithms and models in the browser."
        -  p5.play: "p5.play provides sprites, animations, input and collision functions for games and gamelike applications."
        -  p5.particle: "The Particle and Fountain objects can be used to create data-driven effects that are defined through user structures or JSON input and user-draw functions."
        -  p5.Riso: "p5.Riso is a library for generating files suitable for Risograph printing. It helps turn your sketches into multi-color prints."
        -  rita.js: "RiTa.js provides a set of natural language processing objects for generative literature."
        -  Rotating Knobs: "Make knobs you can rotate with custom graphics and return value ranges"
        -  p5.scenemanager: "p5.SceneManager helps you create sketches with multiple states / scenes. Each scene is a like a sketch within the main sketch."
        -  p5.screenPosition: "Adds the screenX and screenY functionality from Processing to P5js."
        -  p5.scribble: "Draw 2D primitives in a sketchy look. Created by Janneck Wullschleger, based on a port of the original Processing library "
        -  p5.serial: "p5.serial enables serial communication between devices that support serial (RS-232) and p5 sketches running in the browser."
        -  Shape5: "Shape5 is a 2D primative library for elementary students who are learning to code for the first time."
        -  p5.shape.js: "A library built to add more simple shapes to the p5.js framework."
        -  p5.speech: "p5.speech provides simple, clear access to the Web Speech and Speech Recognition APIs, allowing for the easy creation of sketches that can talk and listen."
        -  p5.start2d.js: "p5 extension for 2D static art using px, mm, cm or inches"
        -  p5.tiledmap: "p5.tiledmap provides drawing and helper functions to include maps in your sketches."
        -  p5.touchgui: "A multi-touch and mouse GUI Library for p5.js."
        -  tramontana: "Tramontana is a platform for easily use many devices (iOS, Android, tramontana Board, ...) to create interactive environments, interactive spaces or just prototype experiences at scale and in space."
        -  vida: "Vida is a simple library that adds camera (or video) based motion detection and blob tracking functionality to p5js."
        -  p5.voronoi: "p5.voronoi provides a set of tools to draw and utilize voronoi diagrams in your p5.js sketches."
        -  p5.3D: "3D Text and Images in WebGL."
        -  using-a-library-title: "Using a library"
        -  using-a-library1: "A p5.js library can be any JavaScript code that extends or adds to the p5.js core functionality. There are two categories of libraries. Core libraries ("
        -  using-a-library2: " and "
        -  using-a-library3: ") are part of the p5.js distribution, while contributed libraries are developed, owned, and maintained by members of the p5.js community."
        -  using-a-library4: "To include a library in your sketch, link it into your HTML file, after you have linked in p5.js. An example HTML file might look like this:"
        -  create-your-own-title: "Create Your Own"
        -  create-your-own1: "p5.js welcomes libraries contributed by others! Check out the"
        -  create-your-own2: "libraries tutorial"
        -  create-your-own3: "for more specifics about how to create one."
        -  create-your-own4: "If you have created a library and would like to have it included on this page, submit this form!"
        -
        -community:
        -  community-title: "Community"
        -  community-statement-title: "p5.js Community Statement"
        -  community-statement1: "p5.js is a community interested in exploring the creation of art and design with technology."
        -  community-statement2: "We are a community of, and in solidarity with, people from every gender identity and expression, sexual orientation, race, ethnicity, language, neuro-type, size, ability, class, religion, culture, subculture, political opinion, age, skill level, occupation, and background. We acknowledge that not everyone has the time, financial means, or capacity to actively participate, but we recognize and encourage involvement of all kinds. We facilitate and foster access and empowerment. We are all learners."
        -  community-statement3: "We like these hashtags: #noCodeSnobs (because we value community over efficiency), #newKidLove (because we all started somewhere), #unassumeCore (because we don't assume knowledge), and #BlackLivesMatter (because of course)."
        -  in-practice-title: "In practice:"
        -  in-practice1: " We are not code snobs. We do not assume knowledge or imply there are things that somebody should know. "
        -  in-practice2: "We insist on actively engaging with requests for feedback regardless of their complexity."
        -  in-practice3: "We welcome newcomers and prioritize the education of others. We strive to approach all tasks with the enthusiasm of a newcomer. Because we believe that newcomers are just as valuable in this effort as experts."
        -  in-practice4: "We consistently make the effort to actively recognize and validate multiple types of contributions."
        -  in-practice5: "We are always willing to offer help or guidance."
        -  in-times-conflict-title: "In times of conflict:"
        -  in-times-conflict1: "We listen."
        -  in-times-conflict2: "We clearly communicate while acknowledging other's feelings."
        -  in-times-conflict3: "We admit when we're wrong, apologize, and accept responsibility for our actions."
        -  in-times-conflict4: "We are continuously seeking to improve ourselves and our community."
        -  in-times-conflict5: "We keep our community respectful and open."
        -  in-times-conflict6: "We make everyone feel heard."
        -  in-times-conflict7: "We are mindful and kind in our interactions."
        -  in-the-future-title: "In the future:"
        -  in-the-future1: "The future is now."
        -  sharing-title: "Sharing"
        -  sharing1: "This statement is licensed under a "
        -  sharing2: "Creative Commons license"
        -  sharing3: ". Please feel free to share and remix with attribution."
        -
        -  contribute-title: "Contribute"
        -  contribute1: "Our community is always looking for enthusiasts to help in all different ways."
        -  develop-title: "Develop."
        -  develop1: "GitHub"
        -  develop2: " is the main place where code is collected, issues are documented, and discussions about code are had. Check out the "
        -  develop3: " development tutorial"
        -  develop4: " to get started, or "
        -  develop5: "create your own library."
        -  document-title: "Document."
        -  document1: " Everyone loves documentation. Help is needed "
        -  document2: "porting examples"
        -  document3: ", and"
        -  document4: " adding documentation"
        -  document5: ", and creating tutorials."
        -  teach-title: "Teach."
        -  teach1: " Teach a workshop, a class, a friend, a collaborator! Tag @p5xjs on Twitter and we will do our best to share what you're doing."
        -  create-title: "Create."
        -  create1: " p5.js is looking for designers, artists, coders, programmers to bring your creative and amazing work to show on the front page and inspire other people. Submit your work to "
        -  create2: "hello@p5js.org"
        -  create3: "."
        -  donate-title: "Donate."
        -  donate1: " p5.js is free and open source and made by artists. Help support the development of p5.js through a donation to the "
        -  donate2: "Processing Foundation"
        -  donate3: "."
        -  contributors-conference-title: "p5.js Contributors Conference"
        -  contributors-conference1: "While most work happens online, we also convene IRL. We've had two contributors conferences held at the "
        -  contributors-conference2: "at Carnegie Mellon University in Pittsburgh, PA. Artists, designers, developers, educators, and got together to advance the p5.js project."
        -  participants-title: "Participants"
        -  support-title: "Support"
        -  support1: "Our contributor conference took place at the"
        -  support2: "at Carnegie Mellon University, an academic laboratory for atypical, anti-disciplinary, and inter-institutional research at the intersections of arts, science, technology, and culture."
        -  support3: "This event was made possible by a grant from the"
        -  support4: "and generous support from the"
        -  support5: "and"
        -  support6: "Thank you!"
        -  mailing-list-title: "Mailing list"
        -  mailing-list-1: "Enter your email address to receive occasional updates from the Processing Foundation."
        -
        -  2015contributors-conference-title: "Contributors Conference 2015"
        -  2015contributors-conference-date: "May 25-31"
        -  2015contributors-conference1: "A group of approximately 30 participants gathered spent a week at the "
        -  2015contributors-conference2: ", advancing the code, documentation, and community outreach tools of the p5.js programming environment. Participants came from as far away as Hong Kong, Seattle, Los Angeles, Boston and New York. Most were working professionals in the fields of creative technology, interaction design, and new-media arts, but the group also included a half-dozen undergraduate and graduate students from Carnegie Mellon’s Schools of Art and Architecture."
        -  2015contributors-conference3: "Photos by Taeyoon Choi"
        -  2015contributors-conference-diversity-title: "Diversity"
        -  2015contributors-conference-diversity1: "Alongside technical development, one of the main focuses of this conference was outreach, community, and diversity. The conference began with a panel"
        -  2015contributors-conference-diversity2: "Diversity: Seven Voices on Race, Gender, Ability &amp; Class for FLOSS and the Internet"
        -  2015contributors-conference-diversity3: ". "
        -  2015contributors-conference-diversity4: "Organized by"
        -  2015contributors-conference-diversity5: "and"
        -  2015contributors-conference-diversity6: ", "
        -  2015contributors-conference-diversity7: "the panel took place Tuesday, 25 May 2015 in Kresge Auditorium at Carnegie Mellon University. Speakers included"
        -  2015contributors-conference-diversity8: "and"
        -  2015contributors-conference-diversity9: "."
        -  2015cc_1: "Diverse group of participants smile and make a p5 sign with their hands"
        -  2015cc_2: "Participants jump, smile and throw their hands in the air on a green lawn"
        -  2015cc_3: "Woman presenting the p5.js community statement from her laptop"
        -  2015cc_4: "Woman expressively speaks into a microphone while two male collaborators look on"
        -  2015cc_5: "Participants attentively smile towards the front of the class"
        -  2015cc_6: "Woman reads about p5.js into a microphone to three female students"
        -  2015cc_7: "Participants sit in a circle around a white board with sticky notes on it while a female student speaks into a microphone"
        -  2015cc_8: "Participants sit around a table looking at each others laptops and compare code "
        -  2015cc_9: "Whiteboard with different colored sticky and written notes about programming "
        -  2015cc_10: "Woman speaking into a microphone about valuing different skill sets while a group of participants with laptops look at her powerpoint in a classroom"
        -  2015cc_11: "Woman speaks at a podium in an auditorium while three participants sit on the stage and another three are skyping in on the stage screen"
        -  2015cc_12: "Overhead view of a classroom with participants working on their laptops"
        -  2015cc_13: "Five people having a discussion in a circle"
        -  2015cc_14: "Five people in a circle with their laptops sharing their notes"
        -  2015cc_15: "Man in a classroom with a microphone speaking out to a group of participants"
        -  2019contributors-conference-title: "Contributors Conference 2019"
        -  2019contributors-conference-date: "August 13-18"
        -  2019contributors-conference1: "An interdisciplinary group of 35 participants gathered at the "
        -  2019contributors-conference2: ", advancing the code, documentation, and community outreach tools and exploring the current landscape of the p5.js programming environment. Comprising a diverse range of participants within the fields of creative technology, interaction design, and new media arts, the conference was aimed at fostering dialogue through a multidisciplinary lens. Working groups focused on several topic areas: Access; Music and Code in Performance; Landscape of Creative Tech; and Internationalization."
        -  2019contributors-conference3: "Videos by Qianqian Ye"
        -  2019contributors-conference4: "Photos by Jacquelyn Johnson"
        -  outputs: "Outputs"
        -  output1: ". An implementation of highly flexible triangle, square, hexagon, and octagon girds for p5.js. Created by Aren Davey."
        -  output2: ". A set of template files for building a multi-device, multiplayer game where multiple clients can connect to a specified host page. Created by L05."
        -  output3: "Experiments using"
        -  output3-1: ", testing early implementations of softCompile, OSC interfacing and added connectivity with demo for MIDI setup. A p5.js collaborative live-coding vj environment! Created by Ted Davis."
        -  output4: "A panel on Blackness and Gender in Virtual Space led by American Artist, with shawné michaelain holloway and LaJuné McMillian."
        -  output5: "Workshops led by Everest Pipkin and Jon Chambers."
        -  output6: "A prototype of a "
        -  output6-1: "notebook interface for p5.js."
        -  output6-2: "Created by Allison Parrish."
        -  output7: "New art installations by Stalgia Grigg, LaJuné McMillian, Aatish Bhatia, and Jon Chambers."
        -  output8: "p5.js Global Contributor's Toolkit."
        -  output8-1: "Created by Aarón Montoya-Moraga, Kenneth Lim, Guillermo Montecinos, Qianqian Ye,  Dorothy R. Santos, and Yasheng She."
        -  output9: "How to write non-violent creative code."
        -  output9-1: " A zine led by Olivia Ross."
        -  output10: "An overhaul of the p5.js website for accessibility. Including updates for screen reader accessibility, and improvements to the home, download, getting started, and reference pages. With contributions from Claire Kearney-Volpe, Sina Bahram, Kate Hollenbach, Olivia Ross, Luis Morales-Navarro, Lauren McCarthy, and Evelyn Masso."
        -  output11: "Collaborative performances by Luisa Pereira, Jun Shern Chan, Shefali Nayak, Sona Lee, Ted Davis, and Carlos Garcia."
        -  output12: "A performance by Natalie Braginsky."
        -  output13: "A design of the p5.js library system for the p5 Editor. Created by Cassie Tarakajian and Luca Damasco."
        -  output14: "Prototypes connecting p5 to other libraries. Created by Alex Yixuan Xu and Lauren Valley."
        -  output15: "A closing campfire circle led by Golan Levin."
        -  2019cc_1: "Man at a podium giving a presentation to the group"
        -  2019cc_2: "Participants sitting at a long table having lunch and a discussion"
        -  2019cc_3: "Participants in a classroom, some working on their laptops, others talking "
        -  2019cc_4: "Classroom of participants working on their laptops"
        -  2019cc_5: "Participants in a meeting in a dark classroom"
        -  2019cc_6: "Woman giving presentation in a classroom of diverse participants"
        -  2019cc_7: "Participants conversing in a busy classroom"
        -  2019cc_8: "Woman with microphone speaking to fellow participants in a classroom"
        -  2019cc_9: "Participant speaks at a podium in front of projected text about the problem with anonymyzing data"
        -  2019cc_10: "Person with a microphone speaking to fellow participants in front of text that reads p5.js will not add any new features except those that increase access"
        -  2019cc_11: "Woman speaking into a microphone talking to fellow participants "
        -  2019cc_12: "A man with a microphone speaking to fellow participants"
        -  2019cc_13: "Participants sit in a classroom towards the speakers listening intently"
        -  2019cc_14: "Classroom of participants facing a speaker listen intently "
        -  2019cc_15: "Woman with microphone speaking to fellow participants with the text sacred boundaries in the projection behind her"
        -  2019cc_16: "Overhead view of participants listening to a panel of people with an image of a 3d rendered man on it "
        -  2019cc_17: "Participants sit around a table with their laptops and observe code on a screen"
        -  2019cc_18: "Woman sitting next to a lifesize teddy bear works on her laptop"
        -  2019cc_19: "Participants standing outside smiling"
        -  2019cc_20: "Four participants standing in a circle conversing"
        -  2019cc_21: "Participants sitting outside eating lunch together"
        -  2019cc_22: "Participants sitting around a large U shaped table looking towards the front of the classroom"
        -  2019cc_23: "Man sitting in front of the classroom speaking energetically into a microphone"
        -  2019cc_24: "Group photo of participants smiling enthusiastically with their hands in the air"
        -  2019cc_25: "Group of people sit around campfire made from four LCD monitors."
        -
        -books:
        -  books-title: "관련 책"
        -
        -examples:
        -  Examples: "예제"
        -  back-examples: "Back to Examples"
        -  Structure: "Structure"
        -  Form: "Form"
        -  Data: "Data"
        -  Arrays: "Arrays"
        -  Control: "Control"
        -  Image: "Image"
        -  Color: "Color"
        -  Math: "Math"
        -  Simulate: "Simulate"
        -  Interaction: "Interaction"
        -  Objects: "Objects"
        -  Lights: "Lights"
        -  Motion: "Motion"
        -  Instance_Mode: "Instance Mode"
        -  Dom: "DOM"
        -  Drawing: "Drawing"
        -  Transform: "Transform"
        -  Typography: "Typography"
        -  3D: "3D"
        -  Input: "Input"
        -  Advanced_Data: "Advanced Data"
        -  Sound: "Sound"
        -  Mobile: "Mobile"
        -  Hello_P5: "Hello p5"
        -
        -reference:
        -  Reference: "레퍼런스"
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 9bc2cafca5..ba7bf89476 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -16,7 +16,7 @@ Contribute: "함께하기"
         Forum: "포럼"
         Showcase: "쇼케이스"
         
        -footerxh1: "Credits"
        +footerxh1: "크레딧"
         footer1: "p5.js는 로렌 맥카시 "
         footer2: " 가 창안하고 협력자 커뮤니티와 함께 개발하였습니다. 지원: 프로세싱 재단 "
         footer3: "과 "
        @@ -67,8 +67,8 @@ copyright:
           copyright-title: "저작권"
           copyright1: "p5.js 라이브러리는 무료 소프트웨어입니다."
           copyright2: " Free Software Foundation의 조항(version 2.1.)에 따라 재배포 및 수정할 수 있습니다."
        -  copyright3: "The Reference for the language is under a "
        -  copyright4: " license which makes it possible to reuse this content for non-commercial purposes if it is credited."
        +  copyright3: "p5.js의 레퍼런스는 "
        +  copyright4: " 라이선스에 속하며, 이 콘텐츠는 크레딧을 인용한다는 전제 하에 비영리 목적을 위해 재사용될 수 있습니다."
         
         get started:
           get-started-title: "시작하기"
        @@ -370,8 +370,8 @@ learn:
           coordinate-system-description-p1x1: "p5로 프로그래밍을 시작하기 전에, 먼저 중학교 2학년 시절의 우리를 떠올리며 연습장에 선 하나를 그려볼까요? 두 개의 점을 그린 뒤 그 사이를 연결하면 하나의 선분이 탄생합니다. 연습장 위 이 두개의 점과 둘간을 연결하는 선. 바로 여기가 우리의 시작점입니다."
           coordinate-system-description-p2x1: "여기 점A(1,0)과 점B(4,5) 사이의 선 하나가 보입니다. 만약 똑같은 선을 친구가 그릴 수 있게하려면 \"1콤마 0에서 시작하는 점에서부터 4콤마 5를 향해 선을 그려죠\"라고 말하겠지요. 이제 그 친구가 컴퓨터라고 가정해볼까요? 우리의 컴퓨터 친구도 똑같은 선을 그리게 하려면 위와 동일한 문장을 입력하면 됩니다. 좀 더 구체적인 형식을 갖춰 컴퓨터 친구에게 말을 건네볼까요?"
           coordinate-system-description-p3x1: "코딩 문법에 대해 익숙하지 않더라도 위 문장의 뜻을 어느정도 감잡을 수 있습니다. 우리는 일명 \"함수\"라 불리는 명령문을 통해 컴퓨터와 대화하는 셈입니다. 여기서 \"line\"은 선을 그리는 함수입니다. 여기에 더해, 우리는 이 함수 내에서 구체적인 인수(argument)를 지시할 수 있습니다. 예를 들어, 점 A (1,0)부터 점 B (4,5)까지라는 인수를 함수 괄호 안에 포함 시킨 것이지요. 코드 한 줄을 하나의 문장으로 본다면, 함수는 동사(verb)이고 인수는 목적어(object)인 셈입니다. 단, 코드는 문장과 달리 마침표가 아니라 \"세미콜론(;)\"으로 끝나는 점 주의하세요!"
        -  coordinate-system-description-p4x1: "컴퓨터 화면은 그저 좀 더 멋진 모양새를 갖춘 연습장과도 같습니다. 화면상의 각 픽셀은 x값(가로)과 y값(세로)이라는 두개의 숫자가 합쳐진, 하나의 좌표값과도 같습니다. 그리고 이 좌표로 화면이라는 공간 내의 위치를 정하지요. 이제 우리는 이 픽셀 좌표값에 모양과 색상을 더하면 됩니다."
        -  coordinate-system-description-p5x1: "*** 한가지 주의사항! 우리가 중학교 2학년 때 배운 \"카테시안 좌표계\"는 (0,0)을 중심에 두고, y축을 그 중심에서 위로, 그리고 x축을 중심으로부터 오른쪽을 향해 뻗어나갑니다(양수일 경우엔 이러하고, 음수일 경우 각각 아래와 왼쪽을 향하지요.) 하지만, 컴퓨터 화면 속 픽셀 좌표계에서의 y축은 그 반대로 적용됩니다. 픽셀 좌표계의 (0,0)은 화면상 좌측 최상단에 위치하고, y값이 증가할 수록 아래를 향해 내려옵니다. x값은 그대로 오른쪽을 향해 증가합니다."
        +  coordinate-system-description-p4x1: "컴퓨터 화면은 그저 좀 더 멋진 모양새를 갖춘 연습장과도 같습니다. 화면상의 각 픽셀은 x값(가로)과 y값(세로)이라는 두개의 숫자가 합쳐진, 하나의 좌표값과도 같습니다. 그리고 이 좌표로 화면이라는 공간 내의 위치를 정하지요. 이제 우리는 이 픽셀 좌표값에 모양과 색상을 더하면 됩니다."  
        +  coordinate-system-description-p5x1: "한가지 주의사항! 우리가 중학교 2학년 때 배운 \"직교 좌표계\"는 (0,0)을 중심에 두고, y축을 그 중심에서 위로, 그리고 x축을 중심으로부터 오른쪽을 향해 뻗어나갑니다(양수일 경우엔 이러하고, 음수일 경우 각각 아래와 왼쪽을 향하지요.) 하지만, 컴퓨터 화면 속 픽셀 좌표계에서의 y축은 그 반대로 적용됩니다. 픽셀 좌표계의 (0,0)은 화면상 좌측 최상단에 위치하고, y값이 증가할 수록 아래를 향해 내려옵니다. x값은 그대로 오른쪽을 향해 증가합니다."
           coordinate-system-simple-shapes-title: "간단한 도형"
           coordinate-system-simple-shapes-p1x1: "여러분이 앞으로 마주할 p5 기반 프로그래밍 예제들은 본질적으로 시각적이고 조형적입니다. 다음 예제들의 핵심은 모양을 그리고 픽셀을 설정하는 데에 있습니다. 4개의 기본 도형을 살펴보며 시작해볼까요!"
           coordinate-system-simple-shapes-p2x1: "위의 모양들을 그리기 위해 필요한 위치와 크기(그 다음, 색상까지도) 정보가 무엇일지 고민해볼까요. 아래의 도식들을 보면, 우리는 먼저 너비 100 픽셀 그리고 높이 100 픽셀에 해당하는 창을 만듭니다."
        @@ -463,7 +463,7 @@ community:
           in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 초심자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
           in-practice4: "우리는 언제나 모든 형태의 기여와 참여를 적극적으로 인정하고 인증하고자 합니다."
           in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다."
        -  in-times-conflict-title: "갈등 발생시:"
        +  in-times-conflict-title: "갈등이 발생할 경우:"
           in-times-conflict1: "서로의 생각에 귀 기울입니다. "
           in-times-conflict2: "명확한 의사소통을 하되, 타인의 감정을 생각합니다."
           in-times-conflict3: "우리가 잘못한 경우에는 그 잘못을 인정하고, 용서를 구하며, 행동에 대한 책임을 집니다. "
        @@ -473,10 +473,12 @@ community:
           in-times-conflict7: "사려깊고 친절한 태도로 소통합니다. "
           in-the-future-title: "미래에 우리는: "
           in-the-future1: "지금이 바로 미래입니다."
        -  sharing-title: "공유하기"
        -  sharing1: "이 성명서는 "
        -  sharing2: "Creative Commons license"
        -  sharing3: "에 의해 라이선스를 부여받습니다. 출처와 함께 자유롭게 공유하고 응용하셔도 좋습니다."
        +  notes-title: "Notes"
        +  notes1: "Please also see our "
        +  notes2: "p5.js Code of Conduct"
        +  notes3: ". The p5.js Community Statement is licensed under a "
        +  notes4: "Creative Commons license"
        +  notes5: ". Please feel free to share and remix with attribution."
         
           contribute-title: "함께하기"
           contribute1: "우리 커뮤니티는 다양한 방법으로 도움을 줄 수 있는 열정가 분들을 항시 찾고 있습니다. "
        @@ -601,6 +603,46 @@ community:
         
         books:
           books-title: "출판물"
        +  book-1-title: "Getting Started with p5.js"
        +  book-1-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Illustrations by Taeyoon Choi."
        +  book-1-publisher: "Published October 2015, Maker Media. "
        +  book-1-pages: "246 pages. "
        +  book-1-type: "Paperback."
        +  book-1-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-1-order-a: "Order Print/Ebook from O'Reilly"
        +  book-1-order-b: "Order from Amazon"
        +  book-2-title: "Introduction to p5.js (Spanish Edition)"
        +  book-2-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Translated by Aarón Montoya-Moraga. Ilustraciones de Taeyoon Choi."
        +  book-2-publisher: "Published 2018, Processing Foundation, Inc. "
        +  book-2-pages: "246 pages. "
        +  book-2-type: "Soft cover."
        +  book-2-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-2-order-a: "Order the PDF from The Processing Foundation Press"
        +  book-2-order-b: "Order the physical version from Amazon"
        +  book-3-title: "Generative Design"
        +  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-3-publisher: "Published October 30, 2018, Princeton Architectural Press; Reprint edition. "
        +  book-3-pages: "255 pages. "
        +  book-3-type: "Paperback."
        +  book-3-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-3-order-a: "Order from Princeton Architectural Press"
        +  book-3-order-b: "Order from Amazon"
        +  book-4-title: "Generative Gestaltung (German Edition)"
        +  book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-4-publisher: "Published March 1, 2018, Schmidt Hermann Verlag. "
        +  book-4-pages: "256 pages. "
        +  book-4-type: "Hardcover."
        +  book-4-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-4-order-a: "Order from Verlag Hermann Schmidt"
        +  book-4-order-b: "Order from Amazon"
        +  book-5-title: "Learn JavaScript with p5.js"
        +  book-5-authors: "Engin Arslan."
        +  book-5-publisher: "Published 2018, Apress. "
        +  book-5-pages: "217 pages. "
        +  book-5-type: "Paperback."
        +  book-5-description: "Learn coding from scratch in a highly engaging and visual manner using the vastly popular JavaScript with the programming library p5.js. The skills you will acquire from this book are highly transferable to a myriad of industries and can be used towards building web applications, programmable robots, or generative art. "
        +  book-5-order-a: "Order from Apress"
        +  book-5-order-b: "Order from Amazon"
         
         examples:
           Examples: "예제"
        @@ -615,7 +657,7 @@ examples:
           Math: "수학"
           Simulate: "시뮬레이션"
           Interaction: "인터랙션"
        -  Objects: "오브젝트"
        +  Objects: "객체"
           Lights: "라이트"
           Motion: "모션"
           Instance_Mode: "인스턴스 모드"
        @@ -628,7 +670,7 @@ examples:
           Advanced_Data: "고급 데이터"
           Sound: "사운드"
           Mobile: "모바일"
        -  Hello_P5: "Hello p5"
        +  Hello_P5: "안녕 p5"
         
         reference:
           Reference: "레퍼런스"
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 9e24eb2b20..f6e9e1ca95 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -59,23 +59,23 @@
           "Environment": "환경",  
           "DOM": "DOM", 
           "Rendering": "렌더링",  
        -  "Transform": "변형(Transform)", 
        +  "Transform": "변형", 
           "Data": "데이터",  
           "Dictionary": "사전(Dictionary)",  
           "Array Functions": "배열 기능",  
           "Conversion": "변환(Conversion)", 
        -  "String Functions": "문자열(String) 기능",  
        +  "String Functions": "문자열 기능",  
           "Events": "이벤트",  
           "Acceleration": "가속",  
           "Keyboard": "키보드",  
           "Mouse": "마우스", 
           "Touch": "터치", 
           "Image": "이미지",  
        -  "Loading & Displaying": "로딩 & 디스플레이", 
        +  "Loading & Displaying": "불러오기 & 보이기", 
           "Pixels": "픽셀",  
           "IO": "IO", 
        -  "Input": "입력(Input)", 
        -  "Output": "아웃풋", 
        +  "Input": "입력", 
        +  "Output": "출력", 
           "Table": "테이블", 
           "Time & Date": "날짜 & 시간",  
           "XML": "XML", 
        diff --git a/src/data/zh-Hans.yml b/src/data/zh-Hans.yml
        index 6718a3880c..44f09ab59b 100644
        --- a/src/data/zh-Hans.yml
        +++ b/src/data/zh-Hans.yml
        @@ -107,7 +107,7 @@ get started:
           your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition"
           your-first-sketch-intro3: "Processing 过度教程(英文页面)"
           your-first-sketch-intro4: "在代码编程器内输入:"
        -  your-first-sketch2: "这一行代码表示〝在离左边 50 像素及里上边 50 像素的位置画个高度和阔度都为 80 像素的椭圆形〞。"
        +  your-first-sketch2: "这一行代码表示〝在离左边 50 像素及里上边 50 像素的位置画个高度和宽度都为 80 像素的椭圆形〞。"
           your-first-sketch3: "保存该绘图的档案并刷新您浏览器的页面,这时如果您成功输入以上范例,您会在浏览器内看到如下页面:"
           your-first-sketch4: "如果您使用荧幕阅读器,您需要在 p5 网上编辑器内开启无障碍输出(accessible outputs),或不使用该编辑器的话您则需要在您的 HTML 文件内添加无障碍程式库。以了解更多关于"
           your-first-sketch5: "使用 p5 及荧幕阅读器的相关资讯请点击这里"
        @@ -473,10 +473,12 @@ community:
           in-times-conflict7: "在我们的互动中,我们保持细心及友善。"
           in-the-future-title: "在未来:"
           in-the-future1: "未来就是现在。"
        -  sharing-title: "共享"
        -  sharing1: "此宣言可根据 "
        -  sharing2: "Creative Commons license"
        -  sharing3: " 条款下使用。请随意分享及更改并注明出处。"
        +  notes-title: "Notes"
        +  notes1: "Please also see our "
        +  notes2: "p5.js Code of Conduct"
        +  notes3: "。此宣言可根据 "
        +  notes4: "Creative Commons license"
        +  notes5: " 条款下使用。请随意分享及更改并注明出处。"
         
           contribute-title: "贡献"
           contribute1: "我们的社群都会一直需要各种不同的帮助。"
        @@ -601,6 +603,46 @@ community:
         
         books:
           books-title: "书籍"
        +  book-1-title: "Getting Started with p5.js"
        +  book-1-authors: "Lauren McCarthy, Casey Reas, and Ben Fry.  Illustrations by Taeyoon Choi."
        +  book-1-publisher: "Published October 2015, Maker Media. "
        +  book-1-pages: "246 pages. "
        +  book-1-type: "Paperback."
        +  book-1-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-1-order-a: "Order Print/Ebook from O'Reilly"
        +  book-1-order-b: "Order from Amazon"
        +  book-2-title: "Introduction to p5.js (Spanish Edition)"
        +  book-2-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Translated by Aarón Montoya-Moraga. Illustrations by Taeyoon Choi."
        +  book-2-publisher: "Published 2018, Processing Foundation, Inc. "
        +  book-2-pages: "246 pages. "
        +  book-2-type: "Soft cover."
        +  book-2-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        +  book-2-order-a: "Order the PDF from The Processing Foundation Press"
        +  book-2-order-b: "Order the physical version from Amazon"
        +  book-3-title: "Generative Design"
        +  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-3-publisher: "Published October 30, 2018, Princeton Architectural Press; Reprint edition. "
        +  book-3-pages: "255 pages. "
        +  book-3-type: "Paperback."
        +  book-3-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-3-order-a: "Order from Princeton Architectural Press"
        +  book-3-order-b: "Order from Amazon"
        +  book-4-title: "Generative Gestaltung (German Edition)"
        +  book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        +  book-4-publisher: "Published March 1, 2018, Schmidt Hermann Verlag. "
        +  book-4-pages: "256 pages. "
        +  book-4-type: "Hardcover."
        +  book-4-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        +  book-4-order-a: "Order from Verlag Hermann Schmidt"
        +  book-4-order-b: "Order from Amazon"
        +  book-5-title: "Learn JavaScript with p5.js"
        +  book-5-authors: "Engin Arslan."
        +  book-5-publisher: "Published 2018, Apress. "
        +  book-5-pages: "217 pages. "
        +  book-5-type: "Paperback."
        +  book-5-description: "Learn coding from scratch in a highly engaging and visual manner using the vastly popular JavaScript with the programming library p5.js. The skills you will acquire from this book are highly transferable to a myriad of industries and can be used towards building web applications, programmable robots, or generative art. "
        +  book-5-order-a: "Order from Apress"
        +  book-5-order-b: "Order from Amazon"
         
         examples:
           Examples: "范例"
        diff --git a/src/templates/layouts/default.hbs b/src/templates/layouts/default.hbs
        index 45c2ffbe0a..0441fa1a36 100644
        --- a/src/templates/layouts/default.hbs
        +++ b/src/templates/layouts/default.hbs
        @@ -6,7 +6,7 @@
             <meta name="viewport" content="width=device-width">
             <meta name="description" content="p5.js a JS client-side library for creating graphic and interactive experiences, based on the core principles of Processing.">
             <title tabindex="1">{{title}} | p5.js</title>
        -    <link rel="stylesheet" href="/{{assets}}/css/all.css?v=1.0.0">
        +    <link rel="stylesheet" href="/{{assets}}/css/all.css?v=1.0.1">
             <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
         
             <link rel="shortcut icon" href="/{{assets}}/img/favicon.ico">
        @@ -17,7 +17,7 @@
             <script src="/{{assets}}/js/vendor/ace-nc/ace.js"></script>
             <script src="/{{assets}}/js/vendor/ace-nc/mode-javascript.js"></script>
             <script src="/{{assets}}/js/vendor/prism.js"></script>
        -    <script src="/{{assets}}/js/init.js?v=1.0.0"></script>
        +    <script src="/{{assets}}/js/init.js?v=1.0.1"></script>
         
             {{#ifLowerCaseEquals language "zh-Hans"}}
             <script src="/{{assets}}/js/vendor/pangu.min.js"></script>
        diff --git a/src/templates/pages/books/index.hbs b/src/templates/pages/books/index.hbs
        index 35e4113cb5..39cbc9463d 100644
        --- a/src/templates/pages/books/index.hbs
        +++ b/src/templates/pages/books/index.hbs
        @@ -20,18 +20,45 @@ slug: books/
                 </div>
         
                 <div class="wide-right-column book">
        -          <h2>Getting Started with p5.js</h2>
        -          <p>Lauren McCarthy, Casey Reas, and Ben Fry<br>
        -          Published October 2015, Maker Media. 246 pages. Paperback.
        +          <h2>{{#i18n "book-1-title"}}{{/i18n}}</h2>
        +
        +          <p>{{#i18n "book-1-authors"}}{{/i18n}}</p>
        +          <p>
        +            {{#i18n "book-1-publisher"}}{{/i18n}}
        +            {{#i18n "book-1-pages"}}{{/i18n}}
        +            {{#i18n "book-1-type"}}{{/i18n}}
                   </p>
         
        -          <p>Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML.</p>
        +          <p>{{#i18n "book-1-description"}}{{/i18n}}</p>
        +
        +          <p><a href="http://shop.oreilly.com/product/0636920032076.do" target="_blank">{{#i18n "book-1-order-a"}}{{/i18n}}</a></p>
        +          <p><a href="http://www.amazon.com/Make-Interactive-Graphics-JavaScript-Processing/dp/1457186772" target="_blank">{{#i18n "book-1-order-b"}}{{/i18n}}</a></p>
        +
        +        </div>
        +      </div>
        +
        +      <div style='clear:both; height: 2em'></div>
        +
        +      <div>
        +        <div class="narrow-left-column">
        +          <img src="{{assets}}/img/books/gettingstarted-es.jpg" alt="book cover Introducción a p5.js">
        +        </div>
         
        +        <div class="wide-right-column book">
        +          <h2>{{#i18n "book-2-title"}}{{/i18n}}</h2>
        +
        +          <p>{{#i18n "book-2-authors"}}{{/i18n}}</p>
                   <p>
        -            <a href="http://shop.oreilly.com/product/0636920032076.do" target="_blank">Order Print/Ebook from O'Reilly</a><br>
        -            <a href="http://www.amazon.com/Make-Interactive-Graphics-JavaScript-Processing/dp/1457186772" target="_blank">Order from Amazon</a>
        +            {{#i18n "book-2-publisher"}}{{/i18n}}
        +            {{#i18n "book-2-pages"}}{{/i18n}}
        +            {{#i18n "book-2-type"}}{{/i18n}}
                   </p>
         
        +          <p>{{#i18n "book-2-description"}}{{/i18n}}</p>
        +
        +          <p><a href="https://processingfoundation.press/product/introduccion-a-p5-js/" target="_blank">{{#i18n "book-2-order-a"}}{{/i18n}}</a></p>
        +          <p><a href="https://www.amazon.com/Introducci%C3%B3n-p5-js-Spanish-Lauren-McCarthy/dp/0999881302/" target="_blank">{{#i18n "book-2-order-b"}}{{/i18n}}</a></p>
        +
                 </div>
               </div>
         
        @@ -39,24 +66,75 @@ slug: books/
         
               <div>
                 <div class="narrow-left-column">
        -          <img src="{{assets}}/img/books/gettingstarted-es.jpg" alt="book cover Introducción a p5.js">
        +          <img src="{{assets}}/img/books/generative_design.jpg" alt="book cover generative design">
                 </div>
         
                 <div class="wide-right-column book">
        -          <h2>Introducción a p5.js</h2>
        -          <p>Lauren McCarthy, Casey Reas, y Ben Fry. Traducido por Aarón Montoya-Moraga.
        -          Publicado 2018, Processing Foundation, Inc. 246 páginas. Tapa blanda.
        +          <h2>{{#i18n "book-3-title"}}{{/i18n}}</h2>
        +
        +          <p>{{#i18n "book-3-authors"}}{{/i18n}}</p>
        +          <p>
        +            {{#i18n "book-3-publisher"}}{{/i18n}}
        +            {{#i18n "book-3-pages"}}{{/i18n}}
        +            {{#i18n "book-3-type"}}{{/i18n}}
                   </p>
         
        -          <p>Escrito por la desarolladora principal de p5.js y los fundadores de Processing, este libro provee una introducción a las posibilidades creativas de la web actual, usando Javascript y HTML.</p>
        +          <p>{{#i18n "book-3-description"}}{{/i18n}}</p>
        +
        +          <p><a href="https://www.papress.com/html/product.details.dna?isbn=9781616897581" target="_blank">{{#i18n "book-3-order-a"}}{{/i18n}}</a></p>
        +          <p><a href="https://www.amazon.com/Generative-Design-Visualize-Program-JavaScript/dp/1616897589" target="_blank">{{#i18n "book-3-order-b"}}{{/i18n}}</a></p>
        +
        +        </div>
        +      </div>
         
        +      <div style='clear:both; height: 2em'></div>
        +
        +      <div>
        +        <div class="narrow-left-column">
        +          <img src="{{assets}}/img/books/generative_gestaltung.jpg" alt="book cover Generative Gestaltung">
        +        </div>
        +
        +        <div class="wide-right-column book">
        +          <h2>{{#i18n "book-4-title"}}{{/i18n}}</h2>
        +
        +          <p>{{#i18n "book-4-authors"}}{{/i18n}}</p>
                   <p>
        -            <a href="https://processingfoundation.press/product/introduccion-a-p5-js/" target='_blank'>Ordena el pdf desde The Processing Foundation Press</a><br>
        -            <a href="https://www.amazon.com/Introducci%C3%B3n-p5-js-Spanish-Lauren-McCarthy/dp/0999881302/" target="_blank">Ordena la versión física desde Amazon</a>
        +            {{#i18n "book-4-publisher"}}{{/i18n}}
        +            {{#i18n "book-4-pages"}}{{/i18n}}
        +            {{#i18n "book-4-type"}}{{/i18n}}
                   </p>
         
        +          <p>{{#i18n "book-4-description"}}{{/i18n}}</p>
        +
        +          <p><a href="https://typografie.de/produkt/generative-gestaltung-creative-coding-im-web/" target="_blank">{{#i18n "book-4-order-a"}}{{/i18n}}</a></p>
        +          <p><a href="https://www.amazon.com/Generative-Gestaltung/dp/3874399028" target="_blank">{{#i18n "book-4-order-b"}}{{/i18n}}</a></p>
        +
        +        </div>
        +      </div>
        +
        +      <div style='clear:both; height: 2em'></div>
        +
        +      <div>
        +        <div class="narrow-left-column">
        +          <img src="{{assets}}/img/books/learn_javascript.jpg" alt="book cover learn javascript">
                 </div>
         
        +        <div class="wide-right-column book">
        +          <h2>{{#i18n "book-5-title"}}{{/i18n}}</h2>
        +
        +          <p>{{#i18n "book-5-authors"}}{{/i18n}}</p>
        +          <p>
        +            {{#i18n "book-5-publisher"}}{{/i18n}}
        +            {{#i18n "book-5-pages"}}{{/i18n}}
        +            {{#i18n "book-5-type"}}{{/i18n}}
        +          </p>
        +
        +          <p>{{#i18n "book-5-description"}}{{/i18n}}</p>
        +
        +          <p><a href="https://www.apress.com/gp/book/9781484234259" target="_blank">{{#i18n "book-5-order-a"}}{{/i18n}}</a></p>
        +          <p><a href="https://www.amazon.com/Learn-JavaScript-p5-js-Coding-Learners/dp/1484234251" target="_blank">{{#i18n "book-5-order-b"}}{{/i18n}}</a></p>
        +
        +        </div>
               </div>
               <br>
               <div style='clear:both; height: 2em'></div>
        diff --git a/src/templates/pages/community/index.hbs b/src/templates/pages/community/index.hbs
        index 2b90438f7a..43f54dbd83 100644
        --- a/src/templates/pages/community/index.hbs
        +++ b/src/templates/pages/community/index.hbs
        @@ -45,9 +45,9 @@ slug: community/
                 <ul aria-labelledby="in-future" class="bullets list_view">
                   <li>{{#i18n "in-the-future1"}}{{/i18n}}</li>
                 </ul>
        -
        -        <h3 id="sharing">{{#i18n "sharing-title"}}{{/i18n}}</h3>
        -        <p>{{#i18n "sharing1"}}{{/i18n}}<a href="https://creativecommons.org/licenses/by-sa/4.0/">{{#i18n "sharing2"}}{{/i18n}}</a>{{#i18n "sharing3"}}{{/i18n}}</p>
        +        <br>
        +        <h3 id="notes" class='sr-only'>{{#i18n "notes-title"}}{{/i18n}}</h3>
        +        <p>{{#i18n "notes1"}}{{/i18n}} <a href="">{{#i18n "notes2"}}{{/i18n}}</a>{{#i18n "notes3"}}{{/i18n}}<a href="https://creativecommons.org/licenses/by-sa/4.0/">{{#i18n "notes4"}}{{/i18n}}</a>{{#i18n "notes5"}}{{/i18n}}</p>
               </div>
         
               <h2 id="contribute">{{#i18n "contribute-title"}}{{/i18n}}</h2>
        @@ -83,13 +83,13 @@ slug: community/
                   <p>{{#i18n "mailing-list-1"}}{{/i18n}}</p>
                   <div class="email-octopus-form-row">
                     <input type="email" name="emailAddress" placeholder="email" class="email-octopus-email-address">
        +            <button type="submit">subscribe</button>
                   </div>
                   <div class="email-octopus-form-row-hp" aria-hidden="true">
                     <input type="text" name="hp537b6ec8-d123-11e6-8561-06ead731d453" tabindex="-1">
                   </div>
                   <div class="email-octopus-form-row-subscribe">
                     <input type="hidden" name="successRedirectUrl" class="email-octopus-success-redirect-url" value="">
        -            <button type="submit">subscribe</button>
                   </div>
                 </form>
               </div>
        diff --git a/src/templates/pages/download/index.hbs b/src/templates/pages/download/index.hbs
        index 5b4aab2bfc..2c5438c9a6 100644
        --- a/src/templates/pages/download/index.hbs
        +++ b/src/templates/pages/download/index.hbs
        @@ -18,7 +18,7 @@ slug: download/
         
               <!-- EDITOR -->
               <div class="link_group">
        -        <a class="anchor"><h2>{{#i18n "editor-title"}}{{/i18n}}</h2></a>
        +        <h2>{{#i18n "editor-title"}}{{/i18n}}</h2>
                 <p>{{#i18n "p5.js-editor-intro"}}{{/i18n}}</p>
         
                 <a class='support_link' href="https://editor.p5js.org" target="_blank">
        @@ -79,7 +79,7 @@ slug: download/
                   </li>
         
                   <li>
        -            <a class='support_link p5_link' href="https://cdn.jsdelivr.net/npm/p5@[p5_version]/lib/p5.min.js" target="_blank">
        +            <a class='support_link p5_link' href="https://cdnjs.com/libraries/p5.js" target="_blank">
                       <div class="download_box half_box last_box">
                         <span class="download_name">CDN</span>
                         <p>{{#i18n "link"}}{{/i18n}}
        diff --git a/src/templates/pages/get-started/index.hbs b/src/templates/pages/get-started/index.hbs
        index e5478cb3f7..851cacb97e 100644
        --- a/src/templates/pages/get-started/index.hbs
        +++ b/src/templates/pages/get-started/index.hbs
        @@ -29,17 +29,17 @@ slug: get-started/
                 <pre><code class="language-markup">&lt;script src="../p5.min.js">&lt;/script></code></pre>
         
                 <p>{{#i18n "download5"}}{{/i18n}}
        -          <a target="_blank" href="https://cdn.jsdelivr.net/npm/p5/lib/">
        +          <a target="_blank" href="https://cdnjs.com/libraries/p5.js">
                     p5.js CDN</a>{{#i18n "download6"}}{{/i18n}}
                 </p>
         
        -        <pre class='p5-replace'><code class="language-markup">&lt;script src="https://cdn.jsdelivr.net/npm/p5@[p5_version]/lib/p5.js">&lt;/script></code></pre>
        +        <pre class='p5-replace'><code class="language-markup">&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/[p5_version]/lib/p5.js">&lt;/script></code></pre>
         
                 <p>{{#i18n "download7"}}{{/i18n}}</p>
         
                 <pre class='p5-replace'><code class="language-markup">&lt;html>
           &lt;head>
        -    &lt;script src="https://cdn.jsdelivr.net/npm/p5@[p5_version]/lib/p5.js">&lt;/script>
        +    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/[p5_version]/lib/p5.js">&lt;/script>
             &lt;script src="sketch.js">&lt;/script>
           &lt;/head>
           &lt;body>
        diff --git a/src/templates/pages/index.hbs b/src/templates/pages/index.hbs
        index 7f6777ace2..d4a819f1c7 100644
        --- a/src/templates/pages/index.hbs
        +++ b/src/templates/pages/index.hbs
        @@ -11,14 +11,14 @@ slug: /
               <form id="search" method="get" action="https://www.google.com/search">
                 <input type="hidden" name="as_sitesearch" value="p5js.org" >
                 <input id="search_button" type="submit" aria-label="Search" class='sr-only'>
        -        <input id='search_field' type="text" size="20" placeholder="Search p5js.org" name="q" >
        +        <input tabindex="1" id='search_field' type="text" size="20" placeholder="Search p5js.org" name="q" >
                 <label class="sr-only" for="search_field">Search p5js.org</label>
               </form>
         
               <h1>{{#i18n "p1xh1"}}{{/i18n}}</h1>
               <p style="margin-top:1em">{{#i18n "p1x1"}}{{/i18n}}</p>
               <p>{{#i18n "p1x2"}}{{/i18n}}</p>
        -      <span class='button_box'><a href="https://editor.p5js.org">{{#i18n "start-creating"}}{{/i18n}}</a></span>
        +      <a href="https://editor.p5js.org"><span class='button_box'>{{#i18n "start-creating"}}{{/i18n}}</span></a>
         
               <h2>{{#i18n "p2xh2"}}{{/i18n}}</h2>
               <p>{{#i18n "p2x1"}}{{/i18n}}</p>
        diff --git a/src/templates/pages/learn/coordinate-system-and-shapes.hbs b/src/templates/pages/learn/coordinate-system-and-shapes.hbs
        index a46f1b8b85..2b976156b8 100644
        --- a/src/templates/pages/learn/coordinate-system-and-shapes.hbs
        +++ b/src/templates/pages/learn/coordinate-system-and-shapes.hbs
        @@ -87,7 +87,7 @@ function setup(){
           rectMode(CORNERS);
         }
         function draw(){
        -  rect(10, 10, 50, 30); // rect(x, y, width, height)
        +  rect(10, 10, 50, 30); // rect(x1, y1, x2, y2)
         }
         </script>
         
        @@ -118,7 +118,7 @@ function setup(){
           ellipseMode(CORNERS);
         }
         function draw(){
        -  ellipse(10, 10, 40, 50); // ellipse(x, y, width, height)
        +  ellipse(10, 10, 40, 50); // ellipse(x1, y1, x2, y2)
         }
         </script>
         
        diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js
        index 29a5a885c5..ee120e52ea 100644
        --- a/src/templates/pages/reference/assets/js/reference.js
        +++ b/src/templates/pages/reference/assets/js/reference.js
        @@ -2348,6 +2348,9 @@ define('listView',[
                     }
                     var hash = App.router.getHash(item);
         
        +            // fixes broken links for #/p5/> and #/p5/>=
        +            item.hash = item.hash.replace('>', '&gt;');
        +
                     // Create a group list
                     if (!self.groups[group]) {
                       self.groups[group] = {
        @@ -2445,7 +2448,7 @@ define('listView',[
         define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\r\n\r\n<% if (item.example) { %>\r\n<div class="example">\r\n  <h3 id="reference-example">Examples</h3>\r\n\r\n  <div class="example-content" data-alt="<%= item.alt %>">\r\n    <% _.each(item.example, function(example, i){ %>\r\n      <%= example %>\r\n    <% }); %>\r\n  </div>\r\n</div>\r\n<% } %>\r\n\r\n<div class="description">\r\n    \r\n  <h3 id="reference-description">Description</h3>\r\n\r\n  <% if (item.deprecated) { %>\r\n    <p>\r\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\r\n    </p>\r\n  <% } %>\r\n      \r\n\r\n  <span class=\'description-text\'><%= item.description %></span>\r\n\r\n  <% if (item.extends) { %>\r\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\r\n  <% } %>\r\n\r\n  <% if (item.module === \'p5.sound\') { %>\r\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\r\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\r\n    </p>\r\n  <% } %>\r\n\r\n  <% if (item.constRefs) { %>\r\n    <p>Used by:\r\n  <%\r\n      var refs = item.constRefs;\r\n      for (var i = 0; i < refs.length; i ++) {\r\n        var ref = refs[i];\r\n        var name = ref;\r\n        if (name.substr(0, 3) === \'p5.\') {\r\n          name = name.substr(3);\r\n        }\r\n  if (i !== 0) {\r\n          if (i == refs.length - 1) {\r\n            %> and <%\r\n          } else {\r\n            %>, <%\r\n          }\r\n        }\r\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\r\n      }\r\n  %>\r\n    </p>\r\n  <% } %>\r\n</div>\r\n\r\n<% if (isConstructor || !isClass) { %>\r\n\r\n<div>\r\n  <h3 id="reference-syntax">Syntax</h3>\r\n  <p>\r\n    <% syntaxes.forEach(function(syntax) { %>\r\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\r\n    <% }) %>\r\n  </p>\r\n</div>\r\n\r\n\r\n<% if (item.params) { %>\r\n  <div class="params">\r\n    <h3 id="reference-parameters">Parameters</h3>\r\n    <ul aria-labelledby=\'reference-parameters\'>\r\n    <% for (var i=0; i<item.params.length; i++) { %>\r\n      <% var p = item.params[i] %>\r\n      <li>\r\n        <div class=\'paramname\'><%=p.name%></div>\r\n        <% if (p.type) { %>\r\n          <div class=\'paramtype\'>\r\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\r\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\r\n          <% if (p.optional) { %> (Optional)<% } %>\r\n          </div>\r\n        <% } %>\r\n      </li>\r\n    <% } %>\r\n    </ul>\r\n  </div>\r\n<% } %>\r\n\r\n<% if (item.return && item.return.type) { %>\r\n  <div>\r\n    <h3 id="reference-returns">Returns</h3>\r\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\r\n  </div>\r\n<% } %>\r\n\r\n<% } %>\r\n';});
         
         
        -define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <!--<h2>Constructor</h2>--> \r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% var fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h4>Fields</h4>\r\n  <p>\r\n    <% _.each(fields, function(item) { %>\r\n      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>\r\n      <br>\r\n    <% }); %>\r\n  </p>\r\n<% } %>\r\n\r\n<% var methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h4>Methods</h4>\r\n  <p>\r\n    <table>\r\n    <% _.each(methods, function(item) { %>\r\n      <tr>\r\n      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>\r\n      </tr>\r\n    <% }); %>\r\n    </table>\r\n  </p>\r\n<% } %>\r\n';});
        +define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% let fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h3 id=\'reference-fields\'>Fields</h3>\r\n  <ul aria-labelledby=\'reference-fields\'>\r\n  <% _.each(fields, function(item) { %>\r\n    <li>\r\n      <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>\r\n      <div class=\'paramtype\'><%= item.description %></div>\r\n    </li>\r\n  <% }); %>\r\n  </ul>\r\n<% } %>\r\n\r\n<% let methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h3 id=\'reference-methods\'>Methods</h3>\r\n  <ul aria-labelledby=\'reference-methods\'>\r\n    <% _.each(methods, function(item) { %>\r\n      <li>\r\n        <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></div>\r\n        <div class=\'paramtype\'><%= item.description %></div>\r\n      </li>\r\n    <% }); %>\r\n  </ul>\r\n<% } %>\r\n';});
         
         
         define('text!tpl/itemEnd.html',[],function () { return '\r\n<br><br>\r\n\r\n<div>\r\n<% if (item.file && item.line) { %>\r\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\r\n<% } %>\r\n</div>\r\n\r\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\r\n<br><br>\r\n';});
        @@ -4401,7 +4404,7 @@ define('menuView',[
         });
         
         
        -define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
        +define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a><br> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define(
           'libraryView',[
        @@ -4872,7 +4875,7 @@ require([
           './documented-method'], function(App, DocumentedMethod) {
         
           // Set collections
        -  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];
        +  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];
         
           // Get json API data
           $.getJSON('data.min.json', function(data) {
        diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map
        index dfd60136e2..92c49461da 100644
        --- a/src/templates/pages/reference/assets/js/reference.js.map
        +++ b/src/templates/pages/reference/assets/js/reference.js.map
        @@ -25,7 +25,7 @@
             "../../../config-wrap-end-default.js"
           ],
           "names": [],
        -  "mappings": "AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnYA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9rDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3HA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxIA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1nDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/NA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClEA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxFA",
        +  "mappings": "AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnYA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9rDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3HA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3IA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1nDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/NA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClEA;AACA;AACA;AACA,ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxFA",
           "file": "reference.js",
           "sourcesContent": [
             "(function () {\n",
        @@ -36,19 +36,19 @@
             "/*!\r\n * typeahead.js 0.10.2\r\n * https://github.com/twitter/typeahead.js\r\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\r\n */\r\ndefine('typeahead',[], function() {\r\n\r\n//(function($) {\r\n\r\n\r\n    var _ = {\r\n        isMsie: function() {\r\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\r\n        },\r\n        isBlankString: function(str) {\r\n            return !str || /^\\s*$/.test(str);\r\n        },\r\n        escapeRegExChars: function(str) {\r\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\r\n        },\r\n        isString: function(obj) {\r\n            return typeof obj === \"string\";\r\n        },\r\n        isNumber: function(obj) {\r\n            return typeof obj === \"number\";\r\n        },\r\n        isArray: $.isArray,\r\n        isFunction: $.isFunction,\r\n        isObject: $.isPlainObject,\r\n        isUndefined: function(obj) {\r\n            return typeof obj === \"undefined\";\r\n        },\r\n        bind: $.proxy,\r\n        each: function(collection, cb) {\r\n            $.each(collection, reverseArgs);\r\n            function reverseArgs(index, value) {\r\n                return cb(value, index);\r\n            }\r\n        },\r\n        map: $.map,\r\n        filter: $.grep,\r\n        every: function(obj, test) {\r\n            var result = true;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (!(result = test.call(null, val, key, obj))) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        some: function(obj, test) {\r\n            var result = false;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (result = test.call(null, val, key, obj)) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        mixin: $.extend,\r\n        getUniqueId: function() {\r\n            var counter = 0;\r\n            return function() {\r\n                return counter++;\r\n            };\r\n        }(),\r\n        templatify: function templatify(obj) {\r\n            return $.isFunction(obj) ? obj : template;\r\n            function template() {\r\n                return String(obj);\r\n            }\r\n        },\r\n        defer: function(fn) {\r\n            setTimeout(fn, 0);\r\n        },\r\n        debounce: function(func, wait, immediate) {\r\n            var timeout, result;\r\n            return function() {\r\n                var context = this, args = arguments, later, callNow;\r\n                later = function() {\r\n                    timeout = null;\r\n                    if (!immediate) {\r\n                        result = func.apply(context, args);\r\n                    }\r\n                };\r\n                callNow = immediate && !timeout;\r\n                clearTimeout(timeout);\r\n                timeout = setTimeout(later, wait);\r\n                if (callNow) {\r\n                    result = func.apply(context, args);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        throttle: function(func, wait) {\r\n            var context, args, timeout, result, previous, later;\r\n            previous = 0;\r\n            later = function() {\r\n                previous = new Date();\r\n                timeout = null;\r\n                result = func.apply(context, args);\r\n            };\r\n            return function() {\r\n                var now = new Date(), remaining = wait - (now - previous);\r\n                context = this;\r\n                args = arguments;\r\n                if (remaining <= 0) {\r\n                    clearTimeout(timeout);\r\n                    timeout = null;\r\n                    previous = now;\r\n                    result = func.apply(context, args);\r\n                } else if (!timeout) {\r\n                    timeout = setTimeout(later, remaining);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        noop: function() {}\r\n    };\r\n    var VERSION = \"0.10.2\";\r\n    var tokenizers = function(root) {\r\n        return {\r\n            nonword: nonword,\r\n            whitespace: whitespace,\r\n            obj: {\r\n                nonword: getObjTokenizer(nonword),\r\n                whitespace: getObjTokenizer(whitespace)\r\n            }\r\n        };\r\n        function whitespace(s) {\r\n            return s.split(/\\s+/);\r\n        }\r\n        function nonword(s) {\r\n            return s.split(/\\W+/);\r\n        }\r\n        function getObjTokenizer(tokenizer) {\r\n            return function setKey(key) {\r\n                return function tokenize(o) {\r\n                    return tokenizer(o[key]);\r\n                };\r\n            };\r\n        }\r\n    }();\r\n    var LruCache = function() {\r\n        function LruCache(maxSize) {\r\n            this.maxSize = maxSize || 100;\r\n            this.size = 0;\r\n            this.hash = {};\r\n            this.list = new List();\r\n        }\r\n        _.mixin(LruCache.prototype, {\r\n            set: function set(key, val) {\r\n                var tailItem = this.list.tail, node;\r\n                if (this.size >= this.maxSize) {\r\n                    this.list.remove(tailItem);\r\n                    delete this.hash[tailItem.key];\r\n                }\r\n                if (node = this.hash[key]) {\r\n                    node.val = val;\r\n                    this.list.moveToFront(node);\r\n                } else {\r\n                    node = new Node(key, val);\r\n                    this.list.add(node);\r\n                    this.hash[key] = node;\r\n                    this.size++;\r\n                }\r\n            },\r\n            get: function get(key) {\r\n                var node = this.hash[key];\r\n                if (node) {\r\n                    this.list.moveToFront(node);\r\n                    return node.val;\r\n                }\r\n            }\r\n        });\r\n        function List() {\r\n            this.head = this.tail = null;\r\n        }\r\n        _.mixin(List.prototype, {\r\n            add: function add(node) {\r\n                if (this.head) {\r\n                    node.next = this.head;\r\n                    this.head.prev = node;\r\n                }\r\n                this.head = node;\r\n                this.tail = this.tail || node;\r\n            },\r\n            remove: function remove(node) {\r\n                node.prev ? node.prev.next = node.next : this.head = node.next;\r\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\r\n            },\r\n            moveToFront: function(node) {\r\n                this.remove(node);\r\n                this.add(node);\r\n            }\r\n        });\r\n        function Node(key, val) {\r\n            this.key = key;\r\n            this.val = val;\r\n            this.prev = this.next = null;\r\n        }\r\n        return LruCache;\r\n    }();\r\n    var PersistentStorage = function() {\r\n        var ls, methods;\r\n        try {\r\n            ls = window.localStorage;\r\n            ls.setItem(\"~~~\", \"!\");\r\n            ls.removeItem(\"~~~\");\r\n        } catch (err) {\r\n            ls = null;\r\n        }\r\n        function PersistentStorage(namespace) {\r\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\r\n            this.ttlKey = \"__ttl__\";\r\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\r\n        }\r\n        if (ls && window.JSON) {\r\n            methods = {\r\n                _prefix: function(key) {\r\n                    return this.prefix + key;\r\n                },\r\n                _ttlKey: function(key) {\r\n                    return this._prefix(key) + this.ttlKey;\r\n                },\r\n                get: function(key) {\r\n                    if (this.isExpired(key)) {\r\n                        this.remove(key);\r\n                    }\r\n                    return decode(ls.getItem(this._prefix(key)));\r\n                },\r\n                set: function(key, val, ttl) {\r\n                    if (_.isNumber(ttl)) {\r\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\r\n                    } else {\r\n                        ls.removeItem(this._ttlKey(key));\r\n                    }\r\n                    return ls.setItem(this._prefix(key), encode(val));\r\n                },\r\n                remove: function(key) {\r\n                    ls.removeItem(this._ttlKey(key));\r\n                    ls.removeItem(this._prefix(key));\r\n                    return this;\r\n                },\r\n                clear: function() {\r\n                    var i, key, keys = [], len = ls.length;\r\n                    for (i = 0; i < len; i++) {\r\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\r\n                            keys.push(key.replace(this.keyMatcher, \"\"));\r\n                        }\r\n                    }\r\n                    for (i = keys.length; i--; ) {\r\n                        this.remove(keys[i]);\r\n                    }\r\n                    return this;\r\n                },\r\n                isExpired: function(key) {\r\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\r\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\r\n                }\r\n            };\r\n        } else {\r\n            methods = {\r\n                get: _.noop,\r\n                set: _.noop,\r\n                remove: _.noop,\r\n                clear: _.noop,\r\n                isExpired: _.noop\r\n            };\r\n        }\r\n        _.mixin(PersistentStorage.prototype, methods);\r\n        return PersistentStorage;\r\n        function now() {\r\n            return new Date().getTime();\r\n        }\r\n        function encode(val) {\r\n            return JSON.stringify(_.isUndefined(val) ? null : val);\r\n        }\r\n        function decode(val) {\r\n            return JSON.parse(val);\r\n        }\r\n    }();\r\n    var Transport = function() {\r\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\r\n        function Transport(o) {\r\n            o = o || {};\r\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\r\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\r\n        }\r\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\r\n            maxPendingRequests = num;\r\n        };\r\n        Transport.resetCache = function clearCache() {\r\n            requestCache = new LruCache(10);\r\n        };\r\n        _.mixin(Transport.prototype, {\r\n            _get: function(url, o, cb) {\r\n                var that = this, jqXhr;\r\n                if (jqXhr = pendingRequests[url]) {\r\n                    jqXhr.done(done).fail(fail);\r\n                } else if (pendingRequestsCount < maxPendingRequests) {\r\n                    pendingRequestsCount++;\r\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\r\n                } else {\r\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\r\n                }\r\n                function done(resp) {\r\n                    cb && cb(null, resp);\r\n                    requestCache.set(url, resp);\r\n                }\r\n                function fail() {\r\n                    cb && cb(true);\r\n                }\r\n                function always() {\r\n                    pendingRequestsCount--;\r\n                    delete pendingRequests[url];\r\n                    if (that.onDeckRequestArgs) {\r\n                        that._get.apply(that, that.onDeckRequestArgs);\r\n                        that.onDeckRequestArgs = null;\r\n                    }\r\n                }\r\n            },\r\n            get: function(url, o, cb) {\r\n                var resp;\r\n                if (_.isFunction(o)) {\r\n                    cb = o;\r\n                    o = {};\r\n                }\r\n                if (resp = requestCache.get(url)) {\r\n                    _.defer(function() {\r\n                        cb && cb(null, resp);\r\n                    });\r\n                } else {\r\n                    this._get(url, o, cb);\r\n                }\r\n                return !!resp;\r\n            }\r\n        });\r\n        return Transport;\r\n        function callbackToDeferred(fn) {\r\n            return function customSendWrapper(url, o) {\r\n                var deferred = $.Deferred();\r\n                fn(url, o, onSuccess, onError);\r\n                return deferred;\r\n                function onSuccess(resp) {\r\n                    _.defer(function() {\r\n                        deferred.resolve(resp);\r\n                    });\r\n                }\r\n                function onError(err) {\r\n                    _.defer(function() {\r\n                        deferred.reject(err);\r\n                    });\r\n                }\r\n            };\r\n        }\r\n    }();\r\n    var SearchIndex = function() {\r\n        function SearchIndex(o) {\r\n            o = o || {};\r\n            if (!o.datumTokenizer || !o.queryTokenizer) {\r\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\r\n            }\r\n            this.datumTokenizer = o.datumTokenizer;\r\n            this.queryTokenizer = o.queryTokenizer;\r\n            this.reset();\r\n        }\r\n        _.mixin(SearchIndex.prototype, {\r\n            bootstrap: function bootstrap(o) {\r\n                this.datums = o.datums;\r\n                this.trie = o.trie;\r\n            },\r\n            add: function(data) {\r\n                var that = this;\r\n                data = _.isArray(data) ? data : [ data ];\r\n                _.each(data, function(datum) {\r\n                    var id, tokens;\r\n                    id = that.datums.push(datum) - 1;\r\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\r\n                    _.each(tokens, function(token) {\r\n                        var node, chars, ch;\r\n                        node = that.trie;\r\n                        chars = token.split(\"\");\r\n                        while (ch = chars.shift()) {\r\n                            node = node.children[ch] || (node.children[ch] = newNode());\r\n                            node.ids.push(id);\r\n                        }\r\n                    });\r\n                });\r\n            },\r\n            get: function get(query) {\r\n                var that = this, tokens, matches;\r\n                tokens = normalizeTokens(this.queryTokenizer(query));\r\n                _.each(tokens, function(token) {\r\n                    var node, chars, ch, ids;\r\n                    if (matches && matches.length === 0) {\r\n                        return false;\r\n                    }\r\n                    node = that.trie;\r\n                    chars = token.split(\"\");\r\n                    while (node && (ch = chars.shift())) {\r\n                        node = node.children[ch];\r\n                    }\r\n                    if (node && chars.length === 0) {\r\n                        ids = node.ids.slice(0);\r\n                        matches = matches ? getIntersection(matches, ids) : ids;\r\n                    } else {\r\n                        matches = [];\r\n                        return false;\r\n                    }\r\n                });\r\n                return matches ? _.map(unique(matches), function(id) {\r\n                    return that.datums[id];\r\n                }) : [];\r\n            },\r\n            reset: function reset() {\r\n                this.datums = [];\r\n                this.trie = newNode();\r\n            },\r\n            serialize: function serialize() {\r\n                return {\r\n                    datums: this.datums,\r\n                    trie: this.trie\r\n                };\r\n            }\r\n        });\r\n        return SearchIndex;\r\n        function normalizeTokens(tokens) {\r\n            tokens = _.filter(tokens, function(token) {\r\n                return !!token;\r\n            });\r\n            tokens = _.map(tokens, function(token) {\r\n                return token.toLowerCase();\r\n            });\r\n            return tokens;\r\n        }\r\n        function newNode() {\r\n            return {\r\n                ids: [],\r\n                children: {}\r\n            };\r\n        }\r\n        function unique(array) {\r\n            var seen = {}, uniques = [];\r\n            for (var i = 0; i < array.length; i++) {\r\n                if (!seen[array[i]]) {\r\n                    seen[array[i]] = true;\r\n                    uniques.push(array[i]);\r\n                }\r\n            }\r\n            return uniques;\r\n        }\r\n        function getIntersection(arrayA, arrayB) {\r\n            var ai = 0, bi = 0, intersection = [];\r\n            arrayA = arrayA.sort(compare);\r\n            arrayB = arrayB.sort(compare);\r\n            while (ai < arrayA.length && bi < arrayB.length) {\r\n                if (arrayA[ai] < arrayB[bi]) {\r\n                    ai++;\r\n                } else if (arrayA[ai] > arrayB[bi]) {\r\n                    bi++;\r\n                } else {\r\n                    intersection.push(arrayA[ai]);\r\n                    ai++;\r\n                    bi++;\r\n                }\r\n            }\r\n            return intersection;\r\n            function compare(a, b) {\r\n                return a - b;\r\n            }\r\n        }\r\n    }();\r\n    var oParser = function() {\r\n        return {\r\n            local: getLocal,\r\n            prefetch: getPrefetch,\r\n            remote: getRemote\r\n        };\r\n        function getLocal(o) {\r\n            return o.local || null;\r\n        }\r\n        function getPrefetch(o) {\r\n            var prefetch, defaults;\r\n            defaults = {\r\n                url: null,\r\n                thumbprint: \"\",\r\n                ttl: 24 * 60 * 60 * 1e3,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (prefetch = o.prefetch || null) {\r\n                prefetch = _.isString(prefetch) ? {\r\n                    url: prefetch\r\n                } : prefetch;\r\n                prefetch = _.mixin(defaults, prefetch);\r\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\r\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\r\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\r\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\r\n            }\r\n            return prefetch;\r\n        }\r\n        function getRemote(o) {\r\n            var remote, defaults;\r\n            defaults = {\r\n                url: null,\r\n                wildcard: \"%QUERY\",\r\n                replace: null,\r\n                rateLimitBy: \"debounce\",\r\n                rateLimitWait: 300,\r\n                send: null,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (remote = o.remote || null) {\r\n                remote = _.isString(remote) ? {\r\n                    url: remote\r\n                } : remote;\r\n                remote = _.mixin(defaults, remote);\r\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\r\n                remote.ajax.type = remote.ajax.type || \"GET\";\r\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\r\n                delete remote.rateLimitBy;\r\n                delete remote.rateLimitWait;\r\n                !remote.url && $.error(\"remote requires url to be set\");\r\n            }\r\n            return remote;\r\n            function byDebounce(wait) {\r\n                return function(fn) {\r\n                    return _.debounce(fn, wait);\r\n                };\r\n            }\r\n            function byThrottle(wait) {\r\n                return function(fn) {\r\n                    return _.throttle(fn, wait);\r\n                };\r\n            }\r\n        }\r\n    }();\r\n    (function(root) {\r\n        var old, keys;\r\n        old = root.Bloodhound;\r\n        keys = {\r\n            data: \"data\",\r\n            protocol: \"protocol\",\r\n            thumbprint: \"thumbprint\"\r\n        };\r\n        root.Bloodhound = Bloodhound;\r\n        function Bloodhound(o) {\r\n            if (!o || !o.local && !o.prefetch && !o.remote) {\r\n                $.error(\"one of local, prefetch, or remote is required\");\r\n            }\r\n            this.limit = o.limit || 5;\r\n            this.sorter = getSorter(o.sorter);\r\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\r\n            this.local = oParser.local(o);\r\n            this.prefetch = oParser.prefetch(o);\r\n            this.remote = oParser.remote(o);\r\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\r\n            this.index = new SearchIndex({\r\n                datumTokenizer: o.datumTokenizer,\r\n                queryTokenizer: o.queryTokenizer\r\n            });\r\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\r\n        }\r\n        Bloodhound.noConflict = function noConflict() {\r\n            root.Bloodhound = old;\r\n            return Bloodhound;\r\n        };\r\n        Bloodhound.tokenizers = tokenizers;\r\n        _.mixin(Bloodhound.prototype, {\r\n            _loadPrefetch: function loadPrefetch(o) {\r\n                var that = this, serialized, deferred;\r\n                if (serialized = this._readFromStorage(o.thumbprint)) {\r\n                    this.index.bootstrap(serialized);\r\n                    deferred = $.Deferred().resolve();\r\n                } else {\r\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\r\n                }\r\n                return deferred;\r\n                function handlePrefetchResponse(resp) {\r\n                    that.clear();\r\n                    that.add(o.filter ? o.filter(resp) : resp);\r\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\r\n                }\r\n            },\r\n            _getFromRemote: function getFromRemote(query, cb) {\r\n                var that = this, url, uriEncodedQuery;\r\n                query = query || \"\";\r\n                uriEncodedQuery = encodeURIComponent(query);\r\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\r\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\r\n                function handleRemoteResponse(err, resp) {\r\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\r\n                }\r\n            },\r\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\r\n                if (this.storage) {\r\n                    this.storage.set(keys.data, data, ttl);\r\n                    this.storage.set(keys.protocol, location.protocol, ttl);\r\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\r\n                }\r\n            },\r\n            _readFromStorage: function readFromStorage(thumbprint) {\r\n                var stored = {}, isExpired;\r\n                if (this.storage) {\r\n                    stored.data = this.storage.get(keys.data);\r\n                    stored.protocol = this.storage.get(keys.protocol);\r\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\r\n                }\r\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\r\n                return stored.data && !isExpired ? stored.data : null;\r\n            },\r\n            _initialize: function initialize() {\r\n                var that = this, local = this.local, deferred;\r\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\r\n                local && deferred.done(addLocalToIndex);\r\n                this.transport = this.remote ? new Transport(this.remote) : null;\r\n                return this.initPromise = deferred.promise();\r\n                function addLocalToIndex() {\r\n                    that.add(_.isFunction(local) ? local() : local);\r\n                }\r\n            },\r\n            initialize: function initialize(force) {\r\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\r\n            },\r\n            add: function add(data) {\r\n                this.index.add(data);\r\n            },\r\n            get: function get(query, cb) {\r\n                var that = this, matches = [], cacheHit = false;\r\n                matches = this.index.get(query);\r\n                matches = this.sorter(matches).slice(0, this.limit);\r\n                if (matches.length < this.limit && this.transport) {\r\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\r\n                }\r\n                if (!cacheHit) {\r\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\r\n                }\r\n                function returnRemoteMatches(remoteMatches) {\r\n                    var matchesWithBackfill = matches.slice(0);\r\n                    _.each(remoteMatches, function(remoteMatch) {\r\n                        var isDuplicate;\r\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\r\n                            return that.dupDetector(remoteMatch, match);\r\n                        });\r\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\r\n                        return matchesWithBackfill.length < that.limit;\r\n                    });\r\n                    cb && cb(that.sorter(matchesWithBackfill));\r\n                }\r\n            },\r\n            clear: function clear() {\r\n                this.index.reset();\r\n            },\r\n            clearPrefetchCache: function clearPrefetchCache() {\r\n                this.storage && this.storage.clear();\r\n            },\r\n            clearRemoteCache: function clearRemoteCache() {\r\n                this.transport && Transport.resetCache();\r\n            },\r\n            ttAdapter: function ttAdapter() {\r\n                return _.bind(this.get, this);\r\n            }\r\n        });\r\n        return Bloodhound;\r\n        function getSorter(sortFn) {\r\n            return _.isFunction(sortFn) ? sort : noSort;\r\n            function sort(array) {\r\n                return array.sort(sortFn);\r\n            }\r\n            function noSort(array) {\r\n                return array;\r\n            }\r\n        }\r\n        function ignoreDuplicates() {\r\n            return false;\r\n        }\r\n    })(this);\r\n    var html = {\r\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\r\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\r\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\r\n        suggestions: '<span class=\"tt-suggestions\"></span>',\r\n        suggestion: '<div class=\"tt-suggestion\"></div>'\r\n    };\r\n    var css = {\r\n        wrapper: {\r\n            position: \"relative\",\r\n            display: \"inline-block\"\r\n        },\r\n        hint: {\r\n            position: \"absolute\",\r\n            top: \"0\",\r\n            left: \"0\",\r\n            borderColor: \"transparent\",\r\n            boxShadow: \"none\"\r\n        },\r\n        input: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\",\r\n            backgroundColor: \"transparent\"\r\n        },\r\n        inputWithNoHint: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\"\r\n        },\r\n        dropdown: {\r\n            position: \"absolute\",\r\n            top: \"100%\",\r\n            left: \"0\",\r\n            zIndex: \"100\",\r\n            display: \"none\"\r\n        },\r\n        suggestions: {\r\n            display: \"block\"\r\n        },\r\n        suggestion: {\r\n            whiteSpace: \"nowrap\",\r\n            cursor: \"pointer\"\r\n        },\r\n        suggestionChild: {\r\n            whiteSpace: \"normal\"\r\n        },\r\n        ltr: {\r\n            left: \"0\",\r\n            right: \"auto\"\r\n        },\r\n        rtl: {\r\n            left: \"auto\",\r\n            right: \" 0\"\r\n        }\r\n    };\r\n    if (_.isMsie()) {\r\n        _.mixin(css.input, {\r\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\r\n        });\r\n    }\r\n    if (_.isMsie() && _.isMsie() <= 7) {\r\n        _.mixin(css.input, {\r\n            marginTop: \"-1px\"\r\n        });\r\n    }\r\n    var EventBus = function() {\r\n        var namespace = \"typeahead:\";\r\n        function EventBus(o) {\r\n            if (!o || !o.el) {\r\n                $.error(\"EventBus initialized without el\");\r\n            }\r\n            this.$el = $(o.el);\r\n        }\r\n        _.mixin(EventBus.prototype, {\r\n            trigger: function(type) {\r\n                var args = [].slice.call(arguments, 1);\r\n                this.$el.trigger(namespace + type, args);\r\n            }\r\n        });\r\n        return EventBus;\r\n    }();\r\n    var EventEmitter = function() {\r\n        var splitter = /\\s+/, nextTick = getNextTick();\r\n        return {\r\n            onSync: onSync,\r\n            onAsync: onAsync,\r\n            off: off,\r\n            trigger: trigger\r\n        };\r\n        function on(method, types, cb, context) {\r\n            var type;\r\n            if (!cb) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            cb = context ? bindContext(cb, context) : cb;\r\n            this._callbacks = this._callbacks || {};\r\n            while (type = types.shift()) {\r\n                this._callbacks[type] = this._callbacks[type] || {\r\n                    sync: [],\r\n                    async: []\r\n                };\r\n                this._callbacks[type][method].push(cb);\r\n            }\r\n            return this;\r\n        }\r\n        function onAsync(types, cb, context) {\r\n            return on.call(this, \"async\", types, cb, context);\r\n        }\r\n        function onSync(types, cb, context) {\r\n            return on.call(this, \"sync\", types, cb, context);\r\n        }\r\n        function off(types) {\r\n            var type;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            while (type = types.shift()) {\r\n                delete this._callbacks[type];\r\n            }\r\n            return this;\r\n        }\r\n        function trigger(types) {\r\n            var type, callbacks, args, syncFlush, asyncFlush;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            args = [].slice.call(arguments, 1);\r\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\r\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\r\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\r\n                syncFlush() && nextTick(asyncFlush);\r\n            }\r\n            return this;\r\n        }\r\n        function getFlush(callbacks, context, args) {\r\n            return flush;\r\n            function flush() {\r\n                var cancelled;\r\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\r\n                    cancelled = callbacks[i].apply(context, args) === false;\r\n                }\r\n                return !cancelled;\r\n            }\r\n        }\r\n        function getNextTick() {\r\n            var nextTickFn;\r\n            if (window.setImmediate) {\r\n                nextTickFn = function nextTickSetImmediate(fn) {\r\n                    setImmediate(function() {\r\n                        fn();\r\n                    });\r\n                };\r\n            } else {\r\n                nextTickFn = function nextTickSetTimeout(fn) {\r\n                    setTimeout(function() {\r\n                        fn();\r\n                    }, 0);\r\n                };\r\n            }\r\n            return nextTickFn;\r\n        }\r\n        function bindContext(fn, context) {\r\n            return fn.bind ? fn.bind(context) : function() {\r\n                fn.apply(context, [].slice.call(arguments, 0));\r\n            };\r\n        }\r\n    }();\r\n    var highlight = function(doc) {\r\n        var defaults = {\r\n            node: null,\r\n            pattern: null,\r\n            tagName: \"strong\",\r\n            className: null,\r\n            wordsOnly: false,\r\n            caseSensitive: false\r\n        };\r\n        return function hightlight(o) {\r\n            var regex;\r\n            o = _.mixin({}, defaults, o);\r\n            if (!o.node || !o.pattern) {\r\n                return;\r\n            }\r\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\r\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\r\n            traverse(o.node, hightlightTextNode);\r\n            function hightlightTextNode(textNode) {\r\n                var match, patternNode;\r\n                if (match = regex.exec(textNode.data)) {\r\n                    wrapperNode = doc.createElement(o.tagName);\r\n                    o.className && (wrapperNode.className = o.className);\r\n                    patternNode = textNode.splitText(match.index);\r\n                    patternNode.splitText(match[0].length);\r\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\r\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\r\n                }\r\n                return !!match;\r\n            }\r\n            function traverse(el, hightlightTextNode) {\r\n                var childNode, TEXT_NODE_TYPE = 3;\r\n                for (var i = 0; i < el.childNodes.length; i++) {\r\n                    childNode = el.childNodes[i];\r\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\r\n                        i += hightlightTextNode(childNode) ? 1 : 0;\r\n                    } else {\r\n                        traverse(childNode, hightlightTextNode);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        function getRegex(patterns, caseSensitive, wordsOnly) {\r\n            var escapedPatterns = [], regexStr;\r\n            for (var i = 0; i < patterns.length; i++) {\r\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\r\n            }\r\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\r\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\r\n        }\r\n    }(window.document);\r\n    var Input = function() {\r\n        var specialKeyCodeMap;\r\n        specialKeyCodeMap = {\r\n            9: \"tab\",\r\n            27: \"esc\",\r\n            37: \"left\",\r\n            39: \"right\",\r\n            13: \"enter\",\r\n            38: \"up\",\r\n            40: \"down\"\r\n        };\r\n        function Input(o) {\r\n            var that = this, onBlur, onFocus, onKeydown, onInput;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"input is missing\");\r\n            }\r\n            onBlur = _.bind(this._onBlur, this);\r\n            onFocus = _.bind(this._onFocus, this);\r\n            onKeydown = _.bind(this._onKeydown, this);\r\n            onInput = _.bind(this._onInput, this);\r\n            this.$hint = $(o.hint);\r\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\r\n            if (this.$hint.length === 0) {\r\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\r\n            }\r\n            if (!_.isMsie()) {\r\n                this.$input.on(\"input.tt\", onInput);\r\n            } else {\r\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\r\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\r\n                        return;\r\n                    }\r\n                    _.defer(_.bind(that._onInput, that, $e));\r\n                });\r\n            }\r\n            this.query = this.$input.val();\r\n            this.$overflowHelper = buildOverflowHelper(this.$input);\r\n        }\r\n        Input.normalizeQuery = function(str) {\r\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\r\n        };\r\n        _.mixin(Input.prototype, EventEmitter, {\r\n            _onBlur: function onBlur() {\r\n                this.resetInputValue();\r\n                this.trigger(\"blurred\");\r\n            },\r\n            _onFocus: function onFocus() {\r\n                this.trigger(\"focused\");\r\n            },\r\n            _onKeydown: function onKeydown($e) {\r\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\r\n                this._managePreventDefault(keyName, $e);\r\n                if (keyName && this._shouldTrigger(keyName, $e)) {\r\n                    this.trigger(keyName + \"Keyed\", $e);\r\n                }\r\n            },\r\n            _onInput: function onInput() {\r\n                this._checkInputValue();\r\n            },\r\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\r\n                var preventDefault, hintValue, inputValue;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    hintValue = this.getHint();\r\n                    inputValue = this.getInputValue();\r\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\r\n                    break;\r\n\r\n                  case \"up\":\r\n                  case \"down\":\r\n                    preventDefault = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    preventDefault = false;\r\n                }\r\n                preventDefault && $e.preventDefault();\r\n            },\r\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\r\n                var trigger;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    trigger = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    trigger = true;\r\n                }\r\n                return trigger;\r\n            },\r\n            _checkInputValue: function checkInputValue() {\r\n                var inputValue, areEquivalent, hasDifferentWhitespace;\r\n                inputValue = this.getInputValue();\r\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\r\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\r\n                if (!areEquivalent) {\r\n                    this.trigger(\"queryChanged\", this.query = inputValue);\r\n                } else if (hasDifferentWhitespace) {\r\n                    this.trigger(\"whitespaceChanged\", this.query);\r\n                }\r\n            },\r\n            focus: function focus() {\r\n                this.$input.focus();\r\n            },\r\n            blur: function blur() {\r\n                this.$input.blur();\r\n            },\r\n            getQuery: function getQuery() {\r\n                return this.query;\r\n            },\r\n            setQuery: function setQuery(query) {\r\n                this.query = query;\r\n            },\r\n            getInputValue: function getInputValue() {\r\n                return this.$input.val();\r\n            },\r\n            setInputValue: function setInputValue(value, silent) {\r\n                this.$input.val(value);\r\n                silent ? this.clearHint() : this._checkInputValue();\r\n            },\r\n            resetInputValue: function resetInputValue() {\r\n                this.setInputValue(this.query, true);\r\n            },\r\n            getHint: function getHint() {\r\n                return this.$hint.val();\r\n            },\r\n            setHint: function setHint(value) {\r\n                this.$hint.val(value);\r\n            },\r\n            clearHint: function clearHint() {\r\n                this.setHint(\"\");\r\n            },\r\n            clearHintIfInvalid: function clearHintIfInvalid() {\r\n                var val, hint, valIsPrefixOfHint, isValid;\r\n                val = this.getInputValue();\r\n                hint = this.getHint();\r\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\r\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\r\n                !isValid && this.clearHint();\r\n            },\r\n            getLanguageDirection: function getLanguageDirection() {\r\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\r\n            },\r\n            hasOverflow: function hasOverflow() {\r\n                var constraint = this.$input.width() - 2;\r\n                this.$overflowHelper.text(this.getInputValue());\r\n                return this.$overflowHelper.width() >= constraint;\r\n            },\r\n            isCursorAtEnd: function() {\r\n                var valueLength, selectionStart, range;\r\n                valueLength = this.$input.val().length;\r\n                selectionStart = this.$input[0].selectionStart;\r\n                if (_.isNumber(selectionStart)) {\r\n                    return selectionStart === valueLength;\r\n                } else if (document.selection) {\r\n                    range = document.selection.createRange();\r\n                    range.moveStart(\"character\", -valueLength);\r\n                    return valueLength === range.text.length;\r\n                }\r\n                return true;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$hint.off(\".tt\");\r\n                this.$input.off(\".tt\");\r\n                this.$hint = this.$input = this.$overflowHelper = null;\r\n            }\r\n        });\r\n        return Input;\r\n        function buildOverflowHelper($input) {\r\n            return $('<pre aria-hidden=\"true\"></pre>').css({\r\n                position: \"absolute\",\r\n                visibility: \"hidden\",\r\n                whiteSpace: \"pre\",\r\n                fontFamily: $input.css(\"font-family\"),\r\n                fontSize: $input.css(\"font-size\"),\r\n                fontStyle: $input.css(\"font-style\"),\r\n                fontVariant: $input.css(\"font-variant\"),\r\n                fontWeight: $input.css(\"font-weight\"),\r\n                wordSpacing: $input.css(\"word-spacing\"),\r\n                letterSpacing: $input.css(\"letter-spacing\"),\r\n                textIndent: $input.css(\"text-indent\"),\r\n                textRendering: $input.css(\"text-rendering\"),\r\n                textTransform: $input.css(\"text-transform\")\r\n            }).insertAfter($input);\r\n        }\r\n        function areQueriesEquivalent(a, b) {\r\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\r\n        }\r\n        function withModifier($e) {\r\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\r\n        }\r\n    }();\r\n    var Dataset = function() {\r\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\r\n        function Dataset(o) {\r\n            o = o || {};\r\n            o.templates = o.templates || {};\r\n            if (!o.source) {\r\n                $.error(\"missing source\");\r\n            }\r\n            if (o.name && !isValidName(o.name)) {\r\n                $.error(\"invalid dataset name: \" + o.name);\r\n            }\r\n            this.query = null;\r\n            this.highlight = !!o.highlight;\r\n            this.name = o.name || _.getUniqueId();\r\n            this.source = o.source;\r\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\r\n            this.templates = getTemplates(o.templates, this.displayFn);\r\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\r\n        }\r\n        Dataset.extractDatasetName = function extractDatasetName(el) {\r\n            return $(el).data(datasetKey);\r\n        };\r\n        Dataset.extractValue = function extractDatum(el) {\r\n            return $(el).data(valueKey);\r\n        };\r\n        Dataset.extractDatum = function extractDatum(el) {\r\n            return $(el).data(datumKey);\r\n        };\r\n        _.mixin(Dataset.prototype, EventEmitter, {\r\n            _render: function render(query, suggestions) {\r\n                if (!this.$el) {\r\n                    return;\r\n                }\r\n                var that = this, hasSuggestions;\r\n                this.$el.empty();\r\n                hasSuggestions = suggestions && suggestions.length;\r\n                if (!hasSuggestions && this.templates.empty) {\r\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                } else if (hasSuggestions) {\r\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                }\r\n                this.trigger(\"rendered\");\r\n                function getEmptyHtml() {\r\n                    return that.templates.empty({\r\n                        query: query,\r\n                        isEmpty: true\r\n                    });\r\n                }\r\n                function getSuggestionsHtml() {\r\n                    var $suggestions, nodes;\r\n                    $suggestions = $(html.suggestions).css(css.suggestions);\r\n                    nodes = _.map(suggestions, getSuggestionNode);\r\n                    $suggestions.append.apply($suggestions, nodes);\r\n                    that.highlight && highlight({\r\n                        node: $suggestions[0],\r\n                        pattern: query\r\n                    });\r\n                    return $suggestions;\r\n                    function getSuggestionNode(suggestion) {\r\n                        var $el;\r\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\r\n                        $el.children().each(function() {\r\n                            $(this).css(css.suggestionChild);\r\n                        });\r\n                        return $el;\r\n                    }\r\n                }\r\n                function getHeaderHtml() {\r\n                    return that.templates.header({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n                function getFooterHtml() {\r\n                    return that.templates.footer({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n            },\r\n            getRoot: function getRoot() {\r\n                return this.$el;\r\n            },\r\n            update: function update(query) {\r\n                var that = this;\r\n                this.query = query;\r\n                this.canceled = false;\r\n                this.source(query, render);\r\n                function render(suggestions) {\r\n                    if (!that.canceled && query === that.query) {\r\n                        that._render(query, suggestions);\r\n                    }\r\n                }\r\n            },\r\n            cancel: function cancel() {\r\n                this.canceled = true;\r\n            },\r\n            clear: function clear() {\r\n                this.cancel();\r\n                this.$el.empty();\r\n                this.trigger(\"rendered\");\r\n            },\r\n            isEmpty: function isEmpty() {\r\n                return this.$el.is(\":empty\");\r\n            },\r\n            destroy: function destroy() {\r\n                this.$el = null;\r\n            }\r\n        });\r\n        return Dataset;\r\n        function getDisplayFn(display) {\r\n            display = display || \"value\";\r\n            return _.isFunction(display) ? display : displayFn;\r\n            function displayFn(obj) {\r\n                return obj[display];\r\n            }\r\n        }\r\n        function getTemplates(templates, displayFn) {\r\n            return {\r\n                empty: templates.empty && _.templatify(templates.empty),\r\n                header: templates.header && _.templatify(templates.header),\r\n                footer: templates.footer && _.templatify(templates.footer),\r\n                suggestion: templates.suggestion || suggestionTemplate\r\n            };\r\n            function suggestionTemplate(context) {\r\n                return \"<p>\" + displayFn(context) + \"</p>\";\r\n            }\r\n        }\r\n        function isValidName(str) {\r\n            return /^[_a-zA-Z0-9-]+$/.test(str);\r\n        }\r\n    }();\r\n    var Dropdown = function() {\r\n        function Dropdown(o) {\r\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\r\n            o = o || {};\r\n            if (!o.menu) {\r\n                $.error(\"menu is required\");\r\n            }\r\n            this.isOpen = false;\r\n            this.isEmpty = true;\r\n            this.datasets = _.map(o.datasets, initializeDataset);\r\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\r\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\r\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\r\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\r\n            _.each(this.datasets, function(dataset) {\r\n                that.$menu.append(dataset.getRoot());\r\n                dataset.onSync(\"rendered\", that._onRendered, that);\r\n            });\r\n        }\r\n        _.mixin(Dropdown.prototype, EventEmitter, {\r\n            _onSuggestionClick: function onSuggestionClick($e) {\r\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\r\n            },\r\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\r\n                this._removeCursor();\r\n                this._setCursor($($e.currentTarget), true);\r\n            },\r\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\r\n                this._removeCursor();\r\n            },\r\n            _onRendered: function onRendered() {\r\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\r\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\r\n                this.trigger(\"datasetRendered\");\r\n                function isDatasetEmpty(dataset) {\r\n                    return dataset.isEmpty();\r\n                }\r\n            },\r\n            _hide: function() {\r\n                this.$menu.hide();\r\n            },\r\n            _show: function() {\r\n                this.$menu.css(\"display\", \"block\");\r\n            },\r\n            _getSuggestions: function getSuggestions() {\r\n                return this.$menu.find(\".tt-suggestion\");\r\n            },\r\n            _getCursor: function getCursor() {\r\n                return this.$menu.find(\".tt-cursor\").first();\r\n            },\r\n            _setCursor: function setCursor($el, silent) {\r\n                $el.first().addClass(\"tt-cursor\");\r\n                !silent && this.trigger(\"cursorMoved\");\r\n            },\r\n            _removeCursor: function removeCursor() {\r\n                this._getCursor().removeClass(\"tt-cursor\");\r\n            },\r\n            _moveCursor: function moveCursor(increment) {\r\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\r\n                if (!this.isOpen) {\r\n                    return;\r\n                }\r\n                $oldCursor = this._getCursor();\r\n                $suggestions = this._getSuggestions();\r\n                this._removeCursor();\r\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\r\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\r\n                if (newCursorIndex === -1) {\r\n                    this.trigger(\"cursorRemoved\");\r\n                    return;\r\n                } else if (newCursorIndex < -1) {\r\n                    newCursorIndex = $suggestions.length - 1;\r\n                }\r\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\r\n                this._ensureVisible($newCursor);\r\n            },\r\n            _ensureVisible: function ensureVisible($el) {\r\n                var elTop, elBottom, menuScrollTop, menuHeight;\r\n                elTop = $el.position().top;\r\n                elBottom = elTop + $el.outerHeight(true);\r\n                menuScrollTop = this.$menu.scrollTop();\r\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\r\n                if (elTop < 0) {\r\n                    this.$menu.scrollTop(menuScrollTop + elTop);\r\n                } else if (menuHeight < elBottom) {\r\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\r\n                }\r\n            },\r\n            close: function close() {\r\n                if (this.isOpen) {\r\n                    this.isOpen = false;\r\n                    this._removeCursor();\r\n                    this._hide();\r\n                    this.trigger(\"closed\");\r\n                }\r\n            },\r\n            open: function open() {\r\n                if (!this.isOpen) {\r\n                    this.isOpen = true;\r\n                    !this.isEmpty && this._show();\r\n                    this.trigger(\"opened\");\r\n                }\r\n            },\r\n            setLanguageDirection: function setLanguageDirection(dir) {\r\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\r\n            },\r\n            moveCursorUp: function moveCursorUp() {\r\n                this._moveCursor(-1);\r\n            },\r\n            moveCursorDown: function moveCursorDown() {\r\n                this._moveCursor(+1);\r\n            },\r\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\r\n                var datum = null;\r\n                if ($el.length) {\r\n                    datum = {\r\n                        raw: Dataset.extractDatum($el),\r\n                        value: Dataset.extractValue($el),\r\n                        datasetName: Dataset.extractDatasetName($el)\r\n                    };\r\n                }\r\n                return datum;\r\n            },\r\n            getDatumForCursor: function getDatumForCursor() {\r\n                return this.getDatumForSuggestion(this._getCursor().first());\r\n            },\r\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\r\n                return this.getDatumForSuggestion(this._getSuggestions().first());\r\n            },\r\n            update: function update(query) {\r\n                _.each(this.datasets, updateDataset);\r\n                function updateDataset(dataset) {\r\n                    dataset.update(query);\r\n                }\r\n            },\r\n            empty: function empty() {\r\n                _.each(this.datasets, clearDataset);\r\n                this.isEmpty = true;\r\n                function clearDataset(dataset) {\r\n                    dataset.clear();\r\n                }\r\n            },\r\n            isVisible: function isVisible() {\r\n                return this.isOpen && !this.isEmpty;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$menu.off(\".tt\");\r\n                this.$menu = null;\r\n                _.each(this.datasets, destroyDataset);\r\n                function destroyDataset(dataset) {\r\n                    dataset.destroy();\r\n                }\r\n            }\r\n        });\r\n        return Dropdown;\r\n        function initializeDataset(oDataset) {\r\n            return new Dataset(oDataset);\r\n        }\r\n    }();\r\n    var Typeahead = function() {\r\n        var attrsKey = \"ttAttrs\";\r\n        function Typeahead(o) {\r\n            var $menu, $input, $hint;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"missing input\");\r\n            }\r\n            this.isActivated = false;\r\n            this.autoselect = !!o.autoselect;\r\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\r\n            this.$node = buildDomStructure(o.input, o.withHint);\r\n            $menu = this.$node.find(\".tt-dropdown-menu\");\r\n            $input = this.$node.find(\".tt-input\");\r\n            $hint = this.$node.find(\".tt-hint\");\r\n            $input.on(\"blur.tt\", function($e) {\r\n                var active, isActive, hasActive;\r\n                active = document.activeElement;\r\n                isActive = $menu.is(active);\r\n                hasActive = $menu.has(active).length > 0;\r\n                if (_.isMsie() && (isActive || hasActive)) {\r\n                    $e.preventDefault();\r\n                    $e.stopImmediatePropagation();\r\n                    _.defer(function() {\r\n                        $input.focus();\r\n                    });\r\n                }\r\n            });\r\n            $menu.on(\"mousedown.tt\", function($e) {\r\n                $e.preventDefault();\r\n            });\r\n            this.eventBus = o.eventBus || new EventBus({\r\n                el: $input\r\n            });\r\n            this.dropdown = new Dropdown({\r\n                menu: $menu,\r\n                datasets: o.datasets\r\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\r\n            this.input = new Input({\r\n                input: $input,\r\n                hint: $hint\r\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\r\n            this._setLanguageDirection();\r\n        }\r\n        _.mixin(Typeahead.prototype, {\r\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\r\n                    this._select(datum);\r\n                }\r\n            },\r\n            _onCursorMoved: function onCursorMoved() {\r\n                var datum = this.dropdown.getDatumForCursor();\r\n                this.input.setInputValue(datum.value, true);\r\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\r\n            },\r\n            _onCursorRemoved: function onCursorRemoved() {\r\n                this.input.resetInputValue();\r\n                this._updateHint();\r\n            },\r\n            _onDatasetRendered: function onDatasetRendered() {\r\n                this._updateHint();\r\n            },\r\n            _onOpened: function onOpened() {\r\n                this._updateHint();\r\n                this.eventBus.trigger(\"opened\");\r\n            },\r\n            _onClosed: function onClosed() {\r\n                this.input.clearHint();\r\n                this.eventBus.trigger(\"closed\");\r\n            },\r\n            _onFocused: function onFocused() {\r\n                this.isActivated = true;\r\n                this.dropdown.open();\r\n            },\r\n            _onBlurred: function onBlurred() {\r\n                this.isActivated = false;\r\n                this.dropdown.empty();\r\n                this.dropdown.close();\r\n                this.setVal(\"\", true); //LM\r\n            },\r\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\r\n                var cursorDatum, topSuggestionDatum;\r\n                cursorDatum = this.dropdown.getDatumForCursor();\r\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\r\n                if (cursorDatum) {\r\n                    this._select(cursorDatum);\r\n                    $e.preventDefault();\r\n                } else if (this.autoselect && topSuggestionDatum) {\r\n                    this._select(topSuggestionDatum);\r\n                    $e.preventDefault();\r\n                }\r\n            },\r\n            _onTabKeyed: function onTabKeyed(type, $e) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForCursor()) {\r\n                    this._select(datum);\r\n                    $e.preventDefault();\r\n                } else {\r\n                    this._autocomplete(true);\r\n                }\r\n            },\r\n            _onEscKeyed: function onEscKeyed() {\r\n                this.dropdown.close();\r\n                this.input.resetInputValue();\r\n            },\r\n            _onUpKeyed: function onUpKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\r\n                this.dropdown.open();\r\n            },\r\n            _onDownKeyed: function onDownKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\r\n                this.dropdown.open();\r\n            },\r\n            _onLeftKeyed: function onLeftKeyed() {\r\n                this.dir === \"rtl\" && this._autocomplete();\r\n            },\r\n            _onRightKeyed: function onRightKeyed() {\r\n                this.dir === \"ltr\" && this._autocomplete();\r\n            },\r\n            _onQueryChanged: function onQueryChanged(e, query) {\r\n                this.input.clearHintIfInvalid();\r\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\r\n                this.dropdown.open();\r\n                this._setLanguageDirection();\r\n            },\r\n            _onWhitespaceChanged: function onWhitespaceChanged() {\r\n                this._updateHint();\r\n                this.dropdown.open();\r\n            },\r\n            _setLanguageDirection: function setLanguageDirection() {\r\n                var dir;\r\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\r\n                    this.dir = dir;\r\n                    this.$node.css(\"direction\", dir);\r\n                    this.dropdown.setLanguageDirection(dir);\r\n                }\r\n            },\r\n            _updateHint: function updateHint() {\r\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\r\n                datum = this.dropdown.getDatumForTopSuggestion();\r\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\r\n                    val = this.input.getInputValue();\r\n                    query = Input.normalizeQuery(val);\r\n                    escapedQuery = _.escapeRegExChars(query);\r\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\r\n                    match = frontMatchRegEx.exec(datum.value);\r\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\r\n                } else {\r\n                    this.input.clearHint();\r\n                }\r\n            },\r\n            _autocomplete: function autocomplete(laxCursor) {\r\n                var hint, query, isCursorAtEnd, datum;\r\n                hint = this.input.getHint();\r\n                query = this.input.getQuery();\r\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\r\n                if (hint && query !== hint && isCursorAtEnd) {\r\n                    datum = this.dropdown.getDatumForTopSuggestion();\r\n                    datum && this.input.setInputValue(datum.value);\r\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\r\n                }\r\n            },\r\n            _select: function select(datum) {\r\n                this.input.setQuery(datum.value);\r\n                this.input.setInputValue(datum.value, true);\r\n                this._setLanguageDirection();\r\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\r\n                this.dropdown.close();\r\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\r\n            },\r\n            open: function open() {\r\n                this.dropdown.open();\r\n            },\r\n            close: function close() {\r\n                this.dropdown.close();\r\n            },\r\n            setVal: function setVal(val) {\r\n                if (this.isActivated) {\r\n                    this.input.setInputValue(val);\r\n                } else {\r\n                    this.input.setQuery(val);\r\n                    this.input.setInputValue(val, true);\r\n                }\r\n                this._setLanguageDirection();\r\n            },\r\n            getVal: function getVal() {\r\n                return this.input.getQuery();\r\n            },\r\n            destroy: function destroy() {\r\n                this.input.destroy();\r\n                this.dropdown.destroy();\r\n                destroyDomStructure(this.$node);\r\n                this.$node = null;\r\n            }\r\n        });\r\n        return Typeahead;\r\n        function buildDomStructure(input, withHint) {\r\n            var $input, $wrapper, $dropdown, $hint;\r\n            $input = $(input);\r\n            $wrapper = $(html.wrapper).css(css.wrapper);\r\n            $dropdown = $(html.dropdown).css(css.dropdown);\r\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\r\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: \"false\"\r\n            });\r\n            $input.data(attrsKey, {\r\n                dir: $input.attr(\"dir\"),\r\n                autocomplete: $input.attr(\"autocomplete\"),\r\n                spellcheck: $input.attr(\"spellcheck\"),\r\n                style: $input.attr(\"style\")\r\n            });\r\n            $input.addClass(\"tt-input\").attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: false\r\n            }).css(withHint ? css.input : css.inputWithNoHint);\r\n            try {\r\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\r\n            } catch (e) {}\r\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\r\n        }\r\n        function getBackgroundStyles($el) {\r\n            return {\r\n                backgroundAttachment: $el.css(\"background-attachment\"),\r\n                backgroundClip: $el.css(\"background-clip\"),\r\n                backgroundColor: $el.css(\"background-color\"),\r\n                backgroundImage: $el.css(\"background-image\"),\r\n                backgroundOrigin: $el.css(\"background-origin\"),\r\n                backgroundPosition: $el.css(\"background-position\"),\r\n                backgroundRepeat: $el.css(\"background-repeat\"),\r\n                backgroundSize: $el.css(\"background-size\")\r\n            };\r\n        }\r\n        function destroyDomStructure($node) {\r\n            var $input = $node.find(\".tt-input\");\r\n            _.each($input.data(attrsKey), function(val, key) {\r\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\r\n            });\r\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\r\n            $node.remove();\r\n        }\r\n    }();\r\n    (function() {\r\n        var old, typeaheadKey, methods;\r\n        old = $.fn.typeahead;\r\n        typeaheadKey = \"ttTypeahead\";\r\n        methods = {\r\n            initialize: function initialize(o, datasets) {\r\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\r\n                o = o || {};\r\n                return this.each(attach);\r\n                function attach() {\r\n                    var $input = $(this), eventBus, typeahead;\r\n                    _.each(datasets, function(d) {\r\n                        d.highlight = !!o.highlight;\r\n                    });\r\n                    typeahead = new Typeahead({\r\n                        input: $input,\r\n                        eventBus: eventBus = new EventBus({\r\n                            el: $input\r\n                        }),\r\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\r\n                        minLength: o.minLength,\r\n                        autoselect: o.autoselect,\r\n                        datasets: datasets\r\n                    });\r\n                    $input.data(typeaheadKey, typeahead);\r\n                }\r\n            },\r\n            open: function open() {\r\n                return this.each(openTypeahead);\r\n                function openTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.open();\r\n                    }\r\n                }\r\n            },\r\n            close: function close() {\r\n                return this.each(closeTypeahead);\r\n                function closeTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.close();\r\n                    }\r\n                }\r\n            },\r\n            val: function val(newVal) {\r\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\r\n                function setVal() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.setVal(newVal);\r\n                    }\r\n                }\r\n                function getVal($input) {\r\n                    var typeahead, query;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        query = typeahead.getVal();\r\n                    }\r\n                    return query;\r\n                }\r\n            },\r\n            destroy: function destroy() {\r\n                return this.each(unattach);\r\n                function unattach() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.destroy();\r\n                        $input.removeData(typeaheadKey);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        $.fn.typeahead = function(method) {\r\n            if (methods[method]) {\r\n                return methods[method].apply(this, [].slice.call(arguments, 1));\r\n            } else {\r\n                return methods.initialize.apply(this, arguments);\r\n            }\r\n        };\r\n        $.fn.typeahead.noConflict = function noConflict() {\r\n            $.fn.typeahead = old;\r\n            return this;\r\n        };\r\n    })();\r\n    \r\n    \r\n    \r\n//})(window.jQuery);\r\n\r\n\r\n});\n",
             "define('searchView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/search.html',\r\n  'text!tpl/search_suggestion.html',\r\n  // Tools\r\n  'typeahead'\r\n], function(App, searchTpl, suggestionTpl) {\r\n\r\n  var searchView = Backbone.View.extend({\r\n    el: '#search',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      var tpl = _.template(searchTpl);\r\n      var className = 'form-control input-lg';\r\n      var placeholder = 'Search reference';\r\n      this.searchHtml = tpl({\r\n        'placeholder': placeholder,\r\n        'className': className\r\n      });\r\n      this.items = App.classes.concat(App.allItems);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render input field with Typehead activated.\r\n     */\r\n    render: function() {\r\n      // Append the view to the dom\r\n      this.$el.append(this.searchHtml);\r\n\r\n      // Render Typeahead\r\n      var $searchInput = this.$el.find('input[type=text]');\r\n      this.typeaheadRender($searchInput);\r\n      this.typeaheadEvents($searchInput);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Apply Twitter Typeahead to the search input field.\r\n     * @param {jquery} $input\r\n     */\r\n    typeaheadRender: function($input) {\r\n      var self = this;\r\n      $input.typeahead(null, {\r\n        'displayKey': 'name',\r\n        'minLength': 2,\r\n        //'highlight': true,\r\n        'source': self.substringMatcher(this.items),\r\n        'templates': {\r\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\r\n          'suggestion': _.template(suggestionTpl)\r\n        }\r\n      });\r\n    },\r\n    /**\r\n     * Setup typeahead custom events (item selected).\r\n     */\r\n    typeaheadEvents: function($input) {\r\n      var self = this;\r\n      $input.on('typeahead:selected', function(e, item, datasetName) {\r\n        var selectedItem = self.items[item.idx];\r\n        select(selectedItem);\r\n      });\r\n      $input.on('keydown', function(e) {\r\n        if (e.which === 13) { // enter\r\n          var txt = $input.val();\r\n          var f = _.find(self.items, function(it) { return it.name == txt; });\r\n          if (f) {\r\n            select(f);\r\n          }\r\n        } else if (e.which === 27) {\r\n          $input.blur();\r\n        }\r\n      });\r\n\r\n      function select(selectedItem) {\r\n        var hash = App.router.getHash(selectedItem);//\r\n        App.router.navigate(hash, {'trigger': true});\r\n        $('#item').focus();\r\n      }\r\n    },\r\n    /**\r\n     * substringMatcher function for Typehead (search for strings in an array).\r\n     * @param {array} array\r\n     * @returns {Function}\r\n     */\r\n    substringMatcher: function(array) {\r\n      return function findMatches(query, callback) {\r\n        var matches = [], substrRegex, arrayLength = array.length;\r\n\r\n        // regex used to determine if a string contains the substring `query`\r\n        substrRegex = new RegExp(query, 'i');\r\n\r\n        // iterate through the pool of strings and for any string that\r\n        // contains the substring `query`, add it to the `matches` array\r\n        for (var i=0; i < arrayLength; i++) {\r\n          var item = array[i];\r\n          if (substrRegex.test(item.name)) {\r\n            // typeahead expects suggestions to be a js object\r\n            matches.push({\r\n              'itemtype': item.itemtype,\r\n              'name': item.name,\r\n              'className': item.class,\r\n              'is_constructor': !!item.is_constructor,\r\n              'final': item.final,\r\n              'idx': i\r\n            });\r\n          }\r\n        }\r\n\r\n        callback(matches);\r\n      };\r\n    }\r\n\r\n  });\r\n\r\n  return searchView;\r\n\r\n});\r\n\n",
             "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\r\\n  <div class=\"reference-group clearfix main-ref-page\">  \\r\\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\r\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\r\\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\r\\n      <div class=\"reference-subgroup\">\\r\\n        <% if (subgroup.name !== \\'0\\') { %>\\r\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\r\\n        <% } %>\\r\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\r\\n        <% _.each(subgroup.items, function(item) { %>\\r\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\r\\n        <% }); %>\\r\\n        </ul>\\r\\n      </div>\\r\\n    <% }); %>\\r\\n    </div>\\r\\n  </div>\\r\\n<% }); %>\\r\\n';});\n\n",
        -    "define('listView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/list.html'\r\n], function (App, listTpl) {\r\n  var striptags = function(html) {\r\n    var div = document.createElement('div');\r\n    div.innerHTML = html;\r\n    return div.textContent;\r\n  };\r\n\r\n  var listView = Backbone.View.extend({\r\n    el: '#list',\r\n    events: {},\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function () {\r\n      this.listTpl = _.template(listTpl);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render the list.\r\n     */\r\n    render: function (items, listCollection) {\r\n      if (items && listCollection) {\r\n        var self = this;\r\n\r\n        // Render items and group them by module\r\n        // module === group\r\n        this.groups = {};\r\n        _.each(items, function (item, i) {\r\n\r\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n\r\n            var group = item.module || '_';\r\n            var subgroup = item.submodule || '_';\r\n            if (group === subgroup) {\r\n              subgroup = '0';\r\n            }\r\n            var hash = App.router.getHash(item);\r\n\r\n            // Create a group list\r\n            if (!self.groups[group]) {\r\n              self.groups[group] = {\r\n                name: group.replace('_', '&nbsp;'),\r\n                subgroups: {}\r\n              };\r\n            }\r\n\r\n            // Create a subgroup list\r\n            if (!self.groups[group].subgroups[subgroup]) {\r\n              self.groups[group].subgroups[subgroup] = {\r\n                name: subgroup.replace('_', '&nbsp;'),\r\n                items: []\r\n              };\r\n            }\r\n\r\n            // hide the un-interesting constants\r\n            if (group === 'Constants' && !item.example)\r\n              return;\r\n\r\n            if (item.class === 'p5') {\r\n\r\n              self.groups[group].subgroups[subgroup].items.push(item);\r\n\r\n            } else {\r\n\r\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\r\n                function(i){ return i.name == item.class; });\r\n\r\n              if (!found) {\r\n\r\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\r\n                var ind = hash.lastIndexOf('/');\r\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\r\n                self.groups[group].subgroups[subgroup].items.push({\r\n                  name: item.class,\r\n                  hash: hash\r\n                });\r\n              }\r\n\r\n            }\r\n          }\r\n        });\r\n\r\n        // Put the <li> items html into the list <ul>\r\n        var listHtml = self.listTpl({\r\n          'striptags': striptags,\r\n          'title': self.capitalizeFirst(listCollection),\r\n          'groups': self.groups,\r\n          'listCollection': listCollection\r\n        });\r\n\r\n        // Render the view\r\n        this.$el.html(listHtml);\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a list of items.\r\n     * @param {array} items Array of item objects.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function (listGroup) {\r\n      if (App[listGroup]) {\r\n        this.render(App[listGroup], listGroup);\r\n      }\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function (str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n\r\n\r\n\r\n  });\r\n\r\n  return listView;\r\n\r\n});\r\n\n",
        +    "define('listView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/list.html'\r\n], function (App, listTpl) {\r\n  var striptags = function(html) {\r\n    var div = document.createElement('div');\r\n    div.innerHTML = html;\r\n    return div.textContent;\r\n  };\r\n\r\n  var listView = Backbone.View.extend({\r\n    el: '#list',\r\n    events: {},\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function () {\r\n      this.listTpl = _.template(listTpl);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render the list.\r\n     */\r\n    render: function (items, listCollection) {\r\n      if (items && listCollection) {\r\n        var self = this;\r\n\r\n        // Render items and group them by module\r\n        // module === group\r\n        this.groups = {};\r\n        _.each(items, function (item, i) {\r\n\r\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n\r\n            var group = item.module || '_';\r\n            var subgroup = item.submodule || '_';\r\n            if (group === subgroup) {\r\n              subgroup = '0';\r\n            }\r\n            var hash = App.router.getHash(item);\r\n\r\n            // fixes broken links for #/p5/> and #/p5/>=\r\n            item.hash = item.hash.replace('>', '&gt;');\r\n\r\n            // Create a group list\r\n            if (!self.groups[group]) {\r\n              self.groups[group] = {\r\n                name: group.replace('_', '&nbsp;'),\r\n                subgroups: {}\r\n              };\r\n            }\r\n\r\n            // Create a subgroup list\r\n            if (!self.groups[group].subgroups[subgroup]) {\r\n              self.groups[group].subgroups[subgroup] = {\r\n                name: subgroup.replace('_', '&nbsp;'),\r\n                items: []\r\n              };\r\n            }\r\n\r\n            // hide the un-interesting constants\r\n            if (group === 'Constants' && !item.example)\r\n              return;\r\n\r\n            if (item.class === 'p5') {\r\n\r\n              self.groups[group].subgroups[subgroup].items.push(item);\r\n\r\n            } else {\r\n\r\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\r\n                function(i){ return i.name == item.class; });\r\n\r\n              if (!found) {\r\n\r\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\r\n                var ind = hash.lastIndexOf('/');\r\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\r\n                self.groups[group].subgroups[subgroup].items.push({\r\n                  name: item.class,\r\n                  hash: hash\r\n                });\r\n              }\r\n\r\n            }\r\n          }\r\n        });\r\n\r\n        // Put the <li> items html into the list <ul>\r\n        var listHtml = self.listTpl({\r\n          'striptags': striptags,\r\n          'title': self.capitalizeFirst(listCollection),\r\n          'groups': self.groups,\r\n          'listCollection': listCollection\r\n        });\r\n\r\n        // Render the view\r\n        this.$el.html(listHtml);\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a list of items.\r\n     * @param {array} items Array of item objects.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function (listGroup) {\r\n      if (App[listGroup]) {\r\n        this.render(App[listGroup], listGroup);\r\n      }\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function (str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n\r\n\r\n\r\n  });\r\n\r\n  return listView;\r\n\r\n});\r\n\n",
             "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\r\\n\\r\\n<% if (item.example) { %>\\r\\n<div class=\"example\">\\r\\n  <h3 id=\"reference-example\">Examples</h3>\\r\\n\\r\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\r\\n    <% _.each(item.example, function(example, i){ %>\\r\\n      <%= example %>\\r\\n    <% }); %>\\r\\n  </div>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<div class=\"description\">\\r\\n    \\r\\n  <h3 id=\"reference-description\">Description</h3>\\r\\n\\r\\n  <% if (item.deprecated) { %>\\r\\n    <p>\\r\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n      \\r\\n\\r\\n  <span class=\\'description-text\\'><%= item.description %></span>\\r\\n\\r\\n  <% if (item.extends) { %>\\r\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.module === \\'p5.sound\\') { %>\\r\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\r\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\r\\n    </p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.constRefs) { %>\\r\\n    <p>Used by:\\r\\n  <%\\r\\n      var refs = item.constRefs;\\r\\n      for (var i = 0; i < refs.length; i ++) {\\r\\n        var ref = refs[i];\\r\\n        var name = ref;\\r\\n        if (name.substr(0, 3) === \\'p5.\\') {\\r\\n          name = name.substr(3);\\r\\n        }\\r\\n  if (i !== 0) {\\r\\n          if (i == refs.length - 1) {\\r\\n            %> and <%\\r\\n          } else {\\r\\n            %>, <%\\r\\n          }\\r\\n        }\\r\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\r\\n      }\\r\\n  %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n</div>\\r\\n\\r\\n<% if (isConstructor || !isClass) { %>\\r\\n\\r\\n<div>\\r\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\r\\n  <p>\\r\\n    <% syntaxes.forEach(function(syntax) { %>\\r\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\r\\n    <% }) %>\\r\\n  </p>\\r\\n</div>\\r\\n\\r\\n\\r\\n<% if (item.params) { %>\\r\\n  <div class=\"params\">\\r\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\r\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\r\\n    <% for (var i=0; i<item.params.length; i++) { %>\\r\\n      <% var p = item.params[i] %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><%=p.name%></div>\\r\\n        <% if (p.type) { %>\\r\\n          <div class=\\'paramtype\\'>\\r\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\r\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\r\\n          <% if (p.optional) { %> (Optional)<% } %>\\r\\n          </div>\\r\\n        <% } %>\\r\\n      </li>\\r\\n    <% } %>\\r\\n    </ul>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% if (item.return && item.return.type) { %>\\r\\n  <div>\\r\\n    <h3 id=\"reference-returns\">Returns</h3>\\r\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% } %>\\r\\n';});\n\n",
        -    "\ndefine('text!tpl/class.html',[],function () { return '\\r\\n<% if (typeof constructor !== \\'undefined\\') { %>\\r\\n<div class=\"constructor\">\\r\\n  <!--<h2>Constructor</h2>--> \\r\\n  <%=constructor%>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<% var fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (fields.length > 0) { %>\\r\\n  <h4>Fields</h4>\\r\\n  <p>\\r\\n    <% _.each(fields, function(item) { %>\\r\\n      <a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %> ><%=item.name%></a>: <%= item.description %>\\r\\n      <br>\\r\\n    <% }); %>\\r\\n  </p>\\r\\n<% } %>\\r\\n\\r\\n<% var methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (methods.length > 0) { %>\\r\\n  <h4>Methods</h4>\\r\\n  <p>\\r\\n    <table>\\r\\n    <% _.each(methods, function(item) { %>\\r\\n      <tr>\\r\\n      <td><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></td><td><div class=\"method_description\"><%= item.description %></div></td>\\r\\n      </tr>\\r\\n    <% }); %>\\r\\n    </table>\\r\\n  </p>\\r\\n<% } %>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/class.html',[],function () { return '\\r\\n<% if (typeof constructor !== \\'undefined\\') { %>\\r\\n<div class=\"constructor\">\\r\\n  <%=constructor%>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<% let fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (fields.length > 0) { %>\\r\\n  <h3 id=\\'reference-fields\\'>Fields</h3>\\r\\n  <ul aria-labelledby=\\'reference-fields\\'>\\r\\n  <% _.each(fields, function(item) { %>\\r\\n    <li>\\r\\n      <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%></a></div>\\r\\n      <div class=\\'paramtype\\'><%= item.description %></div>\\r\\n    </li>\\r\\n  <% }); %>\\r\\n  </ul>\\r\\n<% } %>\\r\\n\\r\\n<% let methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (methods.length > 0) { %>\\r\\n  <h3 id=\\'reference-methods\\'>Methods</h3>\\r\\n  <ul aria-labelledby=\\'reference-methods\\'>\\r\\n    <% _.each(methods, function(item) { %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></div>\\r\\n        <div class=\\'paramtype\\'><%= item.description %></div>\\r\\n      </li>\\r\\n    <% }); %>\\r\\n  </ul>\\r\\n<% } %>\\r\\n';});\n\n",
             "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\r\\n<br><br>\\r\\n\\r\\n<div>\\r\\n<% if (item.file && item.line) { %>\\r\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\r\\n<% } %>\\r\\n</div>\\r\\n\\r\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\r\\n<br><br>\\r\\n';});\n\n",
             "// Copyright (C) 2006 Google Inc.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n//      http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview\r\n * some functions for browser-side pretty printing of code contained in html.\r\n *\r\n * <p>\r\n * For a fairly comprehensive set of languages see the\r\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\r\n * file that came with this source.  At a minimum, the lexer should work on a\r\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\r\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\r\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\r\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\r\n * <p>\r\n * Usage: <ol>\r\n * <li> include this source file in an html page via\r\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\r\n * <li> define style rules.  See the example page for examples.\r\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\r\n *    {@code class=prettyprint.}\r\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\r\n *    printer needs to do more substantial DOM manipulations to support that, so\r\n *    some css styles may not be preserved.\r\n * </ol>\r\n * That's it.  I wanted to keep the API as simple as possible, so there's no\r\n * need to specify which language the code is in, but if you wish, you can add\r\n * another class to the {@code <pre>} or {@code <code>} element to specify the\r\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\r\n * starts with \"lang-\" followed by a file extension, specifies the file type.\r\n * See the \"lang-*.js\" files in this directory for code that implements\r\n * per-language file handlers.\r\n * <p>\r\n * Change log:<br>\r\n * cbeust, 2006/08/22\r\n * <blockquote>\r\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\r\n * </blockquote>\r\n * @requires console\r\n */\r\n\r\n// JSLint declarations\r\n/*global console, document, navigator, setTimeout, window, define */\r\n\r\n/** @define {boolean} */\r\nvar IN_GLOBAL_SCOPE = true;\r\n\r\n/**\r\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\r\n * UI events.\r\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\r\n */\r\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\r\n\r\n/**\r\n * Pretty print a chunk of code.\r\n * @param {string} sourceCodeHtml The HTML to pretty print.\r\n * @param {string} opt_langExtension The language name to use.\r\n *     Typically, a filename extension like 'cpp' or 'java'.\r\n * @param {number|boolean} opt_numberLines True to number lines,\r\n *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n * @return {string} code as html, but prettier\r\n */\r\nvar prettyPrintOne;\r\n/**\r\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n * {@code class=prettyprint} and prettify them.\r\n *\r\n * @param {Function} opt_whenDone called when prettifying is done.\r\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n *   containing all the elements to pretty print.\r\n *   Defaults to {@code document.body}.\r\n */\r\nvar prettyPrint;\r\n\r\n\r\n(function () {\r\n  var win = window;\r\n  // Keyword lists for various languages.\r\n  // We use things that coerce to strings to make them compact when minified\r\n  // and to defeat aggressive optimizers that fold large string constants.\r\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\r\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \r\n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\r\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\r\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\r\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\r\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\r\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\r\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\r\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\r\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\r\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\r\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\r\n      \"throws,transient\"];\r\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\r\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\r\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\r\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\r\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\r\n      \"var,virtual,where\"];\r\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\r\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\r\n      \"throw,true,try,unless,until,when,while,yes\";\r\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\r\n      \"Infinity,NaN\"];\r\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\r\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\r\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\r\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\r\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\r\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\r\n      \"False,True,None\"];\r\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\r\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\r\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\r\n      \"BEGIN,END\"];\r\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\r\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\r\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\r\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\r\n      \"function,in,local,set,then,until\"];\r\n  var ALL_KEYWORDS = [\r\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\r\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\r\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\r\n\r\n  // token style names.  correspond to css classes\r\n  /**\r\n   * token style for a string literal\r\n   * @const\r\n   */\r\n  var PR_STRING = 'str';\r\n  /**\r\n   * token style for a keyword\r\n   * @const\r\n   */\r\n  var PR_KEYWORD = 'kwd';\r\n  /**\r\n   * token style for a comment\r\n   * @const\r\n   */\r\n  var PR_COMMENT = 'com';\r\n  /**\r\n   * token style for a type\r\n   * @const\r\n   */\r\n  var PR_TYPE = 'typ';\r\n  /**\r\n   * token style for a literal value.  e.g. 1, null, true.\r\n   * @const\r\n   */\r\n  var PR_LITERAL = 'lit';\r\n  /**\r\n   * token style for a punctuation string.\r\n   * @const\r\n   */\r\n  var PR_PUNCTUATION = 'pun';\r\n  /**\r\n   * token style for plain text.\r\n   * @const\r\n   */\r\n  var PR_PLAIN = 'pln';\r\n\r\n  /**\r\n   * token style for an sgml tag.\r\n   * @const\r\n   */\r\n  var PR_TAG = 'tag';\r\n  /**\r\n   * token style for a markup declaration such as a DOCTYPE.\r\n   * @const\r\n   */\r\n  var PR_DECLARATION = 'dec';\r\n  /**\r\n   * token style for embedded source.\r\n   * @const\r\n   */\r\n  var PR_SOURCE = 'src';\r\n  /**\r\n   * token style for an sgml attribute name.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_NAME = 'atn';\r\n  /**\r\n   * token style for an sgml attribute value.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_VALUE = 'atv';\r\n\r\n  /**\r\n   * A class that indicates a section of markup that is not code, e.g. to allow\r\n   * embedding of line numbers within code listings.\r\n   * @const\r\n   */\r\n  var PR_NOCODE = 'nocode';\r\n\r\n  \r\n  \r\n  /**\r\n   * A set of tokens that can precede a regular expression literal in\r\n   * javascript\r\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\r\n   * has the full list, but I've removed ones that might be problematic when\r\n   * seen in languages that don't support regular expression literals.\r\n   *\r\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\r\n   * literal in a syntactically legal javascript program, and I've removed the\r\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\r\n   * as a count of inches.\r\n   *\r\n   * <p>The link above does not accurately describe EcmaScript rules since\r\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\r\n   * very well in practice.\r\n   *\r\n   * @private\r\n   * @const\r\n   */\r\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\r\n  \r\n  // CAVEAT: this does not properly handle the case where a regular\r\n  // expression immediately follows another since a regular expression may\r\n  // have flags for case-sensitivity and the like.  Having regexp tokens\r\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\r\n  // TODO: maybe style special characters inside a regexp as punctuation.\r\n\r\n  /**\r\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\r\n   * matches the union of the sets of strings matched by the input RegExp.\r\n   * Since it matches globally, if the input strings have a start-of-input\r\n   * anchor (/^.../), it is ignored for the purposes of unioning.\r\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\r\n   * @return {RegExp} a global regex.\r\n   */\r\n  function combinePrefixPatterns(regexs) {\r\n    var capturedGroupIndex = 0;\r\n  \r\n    var needToFoldCase = false;\r\n    var ignoreCase = false;\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.ignoreCase) {\r\n        ignoreCase = true;\r\n      } else if (/[a-z]/i.test(regex.source.replace(\r\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\r\n        needToFoldCase = true;\r\n        ignoreCase = false;\r\n        break;\r\n      }\r\n    }\r\n  \r\n    var escapeCharToCodeUnit = {\r\n      'b': 8,\r\n      't': 9,\r\n      'n': 0xa,\r\n      'v': 0xb,\r\n      'f': 0xc,\r\n      'r': 0xd\r\n    };\r\n  \r\n    function decodeEscape(charsetPart) {\r\n      var cc0 = charsetPart.charCodeAt(0);\r\n      if (cc0 !== 92 /* \\\\ */) {\r\n        return cc0;\r\n      }\r\n      var c1 = charsetPart.charAt(1);\r\n      cc0 = escapeCharToCodeUnit[c1];\r\n      if (cc0) {\r\n        return cc0;\r\n      } else if ('0' <= c1 && c1 <= '7') {\r\n        return parseInt(charsetPart.substring(1), 8);\r\n      } else if (c1 === 'u' || c1 === 'x') {\r\n        return parseInt(charsetPart.substring(2), 16);\r\n      } else {\r\n        return charsetPart.charCodeAt(1);\r\n      }\r\n    }\r\n  \r\n    function encodeEscape(charCode) {\r\n      if (charCode < 0x20) {\r\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\r\n      }\r\n      var ch = String.fromCharCode(charCode);\r\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\r\n          ? \"\\\\\" + ch : ch;\r\n    }\r\n  \r\n    function caseFoldCharset(charSet) {\r\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\r\n          new RegExp(\r\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\r\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\r\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\r\n              + '|\\\\\\\\[0-7]{1,2}'\r\n              + '|\\\\\\\\[\\\\s\\\\S]'\r\n              + '|-'\r\n              + '|[^-\\\\\\\\]',\r\n              'g'));\r\n      var ranges = [];\r\n      var inverse = charsetParts[0] === '^';\r\n  \r\n      var out = ['['];\r\n      if (inverse) { out.push('^'); }\r\n  \r\n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\r\n        var p = charsetParts[i];\r\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\r\n          out.push(p);\r\n        } else {\r\n          var start = decodeEscape(p);\r\n          var end;\r\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\r\n            end = decodeEscape(charsetParts[i + 2]);\r\n            i += 2;\r\n          } else {\r\n            end = start;\r\n          }\r\n          ranges.push([start, end]);\r\n          // If the range might intersect letters, then expand it.\r\n          // This case handling is too simplistic.\r\n          // It does not deal with non-latin case folding.\r\n          // It works for latin source code identifiers though.\r\n          if (!(end < 65 || start > 122)) {\r\n            if (!(end < 65 || start > 90)) {\r\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\r\n            }\r\n            if (!(end < 97 || start > 122)) {\r\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\r\n      // -> [[1, 12], [14, 14], [16, 17]]\r\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\r\n      var consolidatedRanges = [];\r\n      var lastRange = [];\r\n      for (var i = 0; i < ranges.length; ++i) {\r\n        var range = ranges[i];\r\n        if (range[0] <= lastRange[1] + 1) {\r\n          lastRange[1] = Math.max(lastRange[1], range[1]);\r\n        } else {\r\n          consolidatedRanges.push(lastRange = range);\r\n        }\r\n      }\r\n  \r\n      for (var i = 0; i < consolidatedRanges.length; ++i) {\r\n        var range = consolidatedRanges[i];\r\n        out.push(encodeEscape(range[0]));\r\n        if (range[1] > range[0]) {\r\n          if (range[1] + 1 > range[0]) { out.push('-'); }\r\n          out.push(encodeEscape(range[1]));\r\n        }\r\n      }\r\n      out.push(']');\r\n      return out.join('');\r\n    }\r\n  \r\n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\r\n      // Split into character sets, escape sequences, punctuation strings\r\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\r\n      // include any of the above.\r\n      var parts = regex.source.match(\r\n          new RegExp(\r\n              '(?:'\r\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\r\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\r\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\r\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\r\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\r\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\r\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\r\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\r\n              + ')',\r\n              'g'));\r\n      var n = parts.length;\r\n  \r\n      // Maps captured group numbers to the number they will occupy in\r\n      // the output or to -1 if that has not been determined, or to\r\n      // undefined if they need not be capturing in the output.\r\n      var capturedGroups = [];\r\n  \r\n      // Walk over and identify back references to build the capturedGroups\r\n      // mapping.\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          // groups are 1-indexed, so max group index is count of '('\r\n          ++groupIndex;\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue) {\r\n            if (decimalValue <= groupIndex) {\r\n              capturedGroups[decimalValue] = -1;\r\n            } else {\r\n              // Replace with an unambiguous escape sequence so that\r\n              // an octal escape sequence does not turn into a backreference\r\n              // to a capturing group from an earlier regex.\r\n              parts[i] = encodeEscape(decimalValue);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Renumber groups and reduce capturing groups to non-capturing groups\r\n      // where possible.\r\n      for (var i = 1; i < capturedGroups.length; ++i) {\r\n        if (-1 === capturedGroups[i]) {\r\n          capturedGroups[i] = ++capturedGroupIndex;\r\n        }\r\n      }\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          ++groupIndex;\r\n          if (!capturedGroups[groupIndex]) {\r\n            parts[i] = '(?:';\r\n          }\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue && decimalValue <= groupIndex) {\r\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Remove any prefix anchors so that the output will match anywhere.\r\n      // ^^ really does mean an anchored match though.\r\n      for (var i = 0; i < n; ++i) {\r\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\r\n      }\r\n  \r\n      // Expand letters to groups to handle mixing of case-sensitive and\r\n      // case-insensitive patterns if necessary.\r\n      if (regex.ignoreCase && needToFoldCase) {\r\n        for (var i = 0; i < n; ++i) {\r\n          var p = parts[i];\r\n          var ch0 = p.charAt(0);\r\n          if (p.length >= 2 && ch0 === '[') {\r\n            parts[i] = caseFoldCharset(p);\r\n          } else if (ch0 !== '\\\\') {\r\n            // TODO: handle letters in numeric escapes.\r\n            parts[i] = p.replace(\r\n                /[a-zA-Z]/g,\r\n                function (ch) {\r\n                  var cc = ch.charCodeAt(0);\r\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\r\n                });\r\n          }\r\n        }\r\n      }\r\n  \r\n      return parts.join('');\r\n    }\r\n  \r\n    var rewritten = [];\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\r\n      rewritten.push(\r\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\r\n    }\r\n  \r\n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\r\n  }\r\n\r\n  /**\r\n   * Split markup into a string of source code and an array mapping ranges in\r\n   * that string to the text nodes in which they appear.\r\n   *\r\n   * <p>\r\n   * The HTML DOM structure:</p>\r\n   * <pre>\r\n   * (Element   \"p\"\r\n   *   (Element \"b\"\r\n   *     (Text  \"print \"))       ; #1\r\n   *   (Text    \"'Hello '\")      ; #2\r\n   *   (Element \"br\")            ; #3\r\n   *   (Text    \"  + 'World';\")) ; #4\r\n   * </pre>\r\n   * <p>\r\n   * corresponds to the HTML\r\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\r\n   *\r\n   * <p>\r\n   * It will produce the output:</p>\r\n   * <pre>\r\n   * {\r\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\r\n   *   //                     1          2\r\n   *   //           012345678901234 5678901234567\r\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\r\n   * }\r\n   * </pre>\r\n   * <p>\r\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\r\n   * on for the other text nodes.\r\n   * </p>\r\n   *\r\n   * <p>\r\n   * The {@code} spans array is an array of pairs.  Even elements are the start\r\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\r\n   * that contain the text for those substrings.\r\n   * Substrings continue until the next index or the end of the source.\r\n   * </p>\r\n   *\r\n   * @param {Node} node an HTML DOM subtree containing source-code.\r\n   * @param {boolean} isPreformatted true if white-space in text nodes should\r\n   *    be considered significant.\r\n   * @return {Object} source code and the text nodes in which they occur.\r\n   */\r\n  function extractSourceSpans(node, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n  \r\n    var chunks = [];\r\n    var length = 0;\r\n    var spans = [];\r\n    var k = 0;\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1) {  // Element\r\n        if (nocode.test(node.className)) { return; }\r\n        for (var child = node.firstChild; child; child = child.nextSibling) {\r\n          walk(child);\r\n        }\r\n        var nodeName = node.nodeName.toLowerCase();\r\n        if ('br' === nodeName || 'li' === nodeName) {\r\n          chunks[k] = '\\n';\r\n          spans[k << 1] = length++;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      } else if (type == 3 || type == 4) {  // Text\r\n        var text = node.nodeValue;\r\n        if (text.length) {\r\n          if (!isPreformatted) {\r\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\r\n          } else {\r\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\r\n          }\r\n          // TODO: handle tabs here?\r\n          chunks[k] = text;\r\n          spans[k << 1] = length;\r\n          length += text.length;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      }\r\n    }\r\n  \r\n    walk(node);\r\n  \r\n    return {\r\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\r\n      spans: spans\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Apply the given language handler to sourceCode and add the resulting\r\n   * decorations to out.\r\n   * @param {number} basePos the index of sourceCode within the chunk of source\r\n   *    whose decorations are already present on out.\r\n   */\r\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\r\n    if (!sourceCode) { return; }\r\n    var job = {\r\n      sourceCode: sourceCode,\r\n      basePos: basePos\r\n    };\r\n    langHandler(job);\r\n    out.push.apply(out, job.decorations);\r\n  }\r\n\r\n  var notWs = /\\S/;\r\n\r\n  /**\r\n   * Given an element, if it contains only one child element and any text nodes\r\n   * it contains contain only space characters, return the sole child element.\r\n   * Otherwise returns undefined.\r\n   * <p>\r\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\r\n   * there is a single child element that contains all the non-space textual\r\n   * content, but not to return anything where there are multiple child elements\r\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\r\n   * is textual content.\r\n   */\r\n  function childContentWrapper(element) {\r\n    var wrapper = undefined;\r\n    for (var c = element.firstChild; c; c = c.nextSibling) {\r\n      var type = c.nodeType;\r\n      wrapper = (type === 1)  // Element Node\r\n          ? (wrapper ? element : c)\r\n          : (type === 3)  // Text Node\r\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\r\n          : wrapper;\r\n    }\r\n    return wrapper === element ? undefined : wrapper;\r\n  }\r\n\r\n  /** Given triples of [style, pattern, context] returns a lexing function,\r\n    * The lexing function interprets the patterns to find token boundaries and\r\n    * returns a decoration list of the form\r\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\r\n    * where index_n is an index into the sourceCode, and style_n is a style\r\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\r\n    * all characters in sourceCode[index_n-1:index_n].\r\n    *\r\n    * The stylePatterns is a list whose elements have the form\r\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\r\n    *\r\n    * Style is a style constant like PR_PLAIN, or can be a string of the\r\n    * form 'lang-FOO', where FOO is a language extension describing the\r\n    * language of the portion of the token in $1 after pattern executes.\r\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\r\n    * '(hello (world))', then that portion of the token will be passed to the\r\n    * registered lisp handler for formatting.\r\n    * The text before and after group 1 will be restyled using this decorator\r\n    * so decorators should take care that this doesn't result in infinite\r\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\r\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\r\n    * '<script>foo()<\\/script>', which would cause the current decorator to\r\n    * be called with '<script>' which would not match the same rule since\r\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\r\n    * the generic tag rule.  The handler registered for the 'js' extension would\r\n    * then be called with 'foo()', and finally, the current decorator would\r\n    * be called with '<\\/script>' which would not match the original rule and\r\n    * so the generic tag rule would identify it as a tag.\r\n    *\r\n    * Pattern must only match prefixes, and if it matches a prefix, then that\r\n    * match is considered a token with the same style.\r\n    *\r\n    * Context is applied to the last non-whitespace, non-comment token\r\n    * recognized.\r\n    *\r\n    * Shortcut is an optional string of characters, any of which, if the first\r\n    * character, gurantee that this pattern and only this pattern matches.\r\n    *\r\n    * @param {Array} shortcutStylePatterns patterns that always start with\r\n    *   a known character.  Must have a shortcut string.\r\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\r\n    *   order if the shortcut ones fail.  May have shortcuts.\r\n    *\r\n    * @return {function (Object)} a\r\n    *   function that takes source code and returns a list of decorations.\r\n    */\r\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\r\n    var shortcuts = {};\r\n    var tokenizer;\r\n    (function () {\r\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\r\n      var allRegexs = [];\r\n      var regexKeys = {};\r\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\r\n        var patternParts = allPatterns[i];\r\n        var shortcutChars = patternParts[3];\r\n        if (shortcutChars) {\r\n          for (var c = shortcutChars.length; --c >= 0;) {\r\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\r\n          }\r\n        }\r\n        var regex = patternParts[1];\r\n        var k = '' + regex;\r\n        if (!regexKeys.hasOwnProperty(k)) {\r\n          allRegexs.push(regex);\r\n          regexKeys[k] = null;\r\n        }\r\n      }\r\n      allRegexs.push(/[\\0-\\uffff]/);\r\n      tokenizer = combinePrefixPatterns(allRegexs);\r\n    })();\r\n\r\n    var nPatterns = fallthroughStylePatterns.length;\r\n\r\n    /**\r\n     * Lexes job.sourceCode and produces an output array job.decorations of\r\n     * style classes preceded by the position at which they start in\r\n     * job.sourceCode in order.\r\n     *\r\n     * @param {Object} job an object like <pre>{\r\n     *    sourceCode: {string} sourceText plain text,\r\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\r\n     *        sourceCode.\r\n     * }</pre>\r\n     */\r\n    var decorate = function (job) {\r\n      var sourceCode = job.sourceCode, basePos = job.basePos;\r\n      /** Even entries are positions in source in ascending order.  Odd enties\r\n        * are style markers (e.g., PR_COMMENT) that run from that position until\r\n        * the end.\r\n        * @type {Array.<number|string>}\r\n        */\r\n      var decorations = [basePos, PR_PLAIN];\r\n      var pos = 0;  // index into sourceCode\r\n      var tokens = sourceCode.match(tokenizer) || [];\r\n      var styleCache = {};\r\n\r\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\r\n        var token = tokens[ti];\r\n        var style = styleCache[token];\r\n        var match = void 0;\r\n\r\n        var isEmbedded;\r\n        if (typeof style === 'string') {\r\n          isEmbedded = false;\r\n        } else {\r\n          var patternParts = shortcuts[token.charAt(0)];\r\n          if (patternParts) {\r\n            match = token.match(patternParts[1]);\r\n            style = patternParts[0];\r\n          } else {\r\n            for (var i = 0; i < nPatterns; ++i) {\r\n              patternParts = fallthroughStylePatterns[i];\r\n              match = token.match(patternParts[1]);\r\n              if (match) {\r\n                style = patternParts[0];\r\n                break;\r\n              }\r\n            }\r\n\r\n            if (!match) {  // make sure that we make progress\r\n              style = PR_PLAIN;\r\n            }\r\n          }\r\n\r\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\r\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\r\n            isEmbedded = false;\r\n            style = PR_SOURCE;\r\n          }\r\n\r\n          if (!isEmbedded) { styleCache[token] = style; }\r\n        }\r\n\r\n        var tokenStart = pos;\r\n        pos += token.length;\r\n\r\n        if (!isEmbedded) {\r\n          decorations.push(basePos + tokenStart, style);\r\n        } else {  // Treat group 1 as an embedded block of source code.\r\n          var embeddedSource = match[1];\r\n          var embeddedSourceStart = token.indexOf(embeddedSource);\r\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\r\n          if (match[2]) {\r\n            // If embeddedSource can be blank, then it would match at the\r\n            // beginning which would cause us to infinitely recurse on the\r\n            // entire token, so we catch the right context in match[2].\r\n            embeddedSourceEnd = token.length - match[2].length;\r\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\r\n          }\r\n          var lang = style.substring(5);\r\n          // Decorate the left of the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart,\r\n              token.substring(0, embeddedSourceStart),\r\n              decorate, decorations);\r\n          // Decorate the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceStart,\r\n              embeddedSource,\r\n              langHandlerForExtension(lang, embeddedSource),\r\n              decorations);\r\n          // Decorate the right of the embedded section\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceEnd,\r\n              token.substring(embeddedSourceEnd),\r\n              decorate, decorations);\r\n        }\r\n      }\r\n      job.decorations = decorations;\r\n    };\r\n    return decorate;\r\n  }\r\n\r\n  /** returns a function that produces a list of decorations from source text.\r\n    *\r\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\r\n    * escape.  It does not recognize perl's qq() style strings.\r\n    * It has no special handling for double delimiter escapes as in basic, or\r\n    * the tripled delimiters used in python, but should work on those regardless\r\n    * although in those cases a single string literal may be broken up into\r\n    * multiple adjacent string literals.\r\n    *\r\n    * It recognizes C, C++, and shell style comments.\r\n    *\r\n    * @param {Object} options a set of optional parameters.\r\n    * @return {function (Object)} a function that examines the source code\r\n    *     in the input job and builds the decoration list.\r\n    */\r\n  function sourceDecorator(options) {\r\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\r\n    if (options['tripleQuotedStrings']) {\r\n      // '''multi-line-string''', 'single-line-string', and double-quoted\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\r\n           null, '\\'\"']);\r\n    } else if (options['multiLineStrings']) {\r\n      // 'multi-line-string', \"multi-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\r\n           null, '\\'\"`']);\r\n    } else {\r\n      // 'single-line-string', \"single-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,\r\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\r\n           null, '\"\\'']);\r\n    }\r\n    if (options['verbatimStrings']) {\r\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\r\n      fallthroughStylePatterns.push(\r\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\r\n    }\r\n    var hc = options['hashComments'];\r\n    if (hc) {\r\n      if (options['cStyleComments']) {\r\n        if (hc > 1) {  // multiline hash comments\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\r\n        } else {\r\n          // Stop C preprocessor declarations at an unclosed open comment\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\r\n               null, '#']);\r\n        }\r\n        // #include <stdio.h>\r\n        fallthroughStylePatterns.push(\r\n            [PR_STRING,\r\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\r\n             null]);\r\n      } else {\r\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\r\n      }\r\n    }\r\n    if (options['cStyleComments']) {\r\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\r\n      fallthroughStylePatterns.push(\r\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\r\n    }\r\n    var regexLiterals = options['regexLiterals'];\r\n    if (regexLiterals) {\r\n      /**\r\n       * @const\r\n       */\r\n      var regexExcls = regexLiterals > 1\r\n        ? ''  // Multiline regex literals\r\n        : '\\n\\r';\r\n      /**\r\n       * @const\r\n       */\r\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\r\n      /**\r\n       * @const\r\n       */\r\n      var REGEX_LITERAL = (\r\n          // A regular expression literal starts with a slash that is\r\n          // not followed by * or / so that it is not confused with\r\n          // comments.\r\n          '/(?=[^/*' + regexExcls + '])'\r\n          // and then contains any number of raw characters,\r\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\r\n          // escape sequences (\\x5C),\r\n          +    '|\\\\x5C' + regexAny\r\n          // or non-nesting character sets (\\x5B\\x5D);\r\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\r\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\r\n          // finally closed by a /.\r\n          + '/');\r\n      fallthroughStylePatterns.push(\r\n          ['lang-regex',\r\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\r\n           ]);\r\n    }\r\n\r\n    var types = options['types'];\r\n    if (types) {\r\n      fallthroughStylePatterns.push([PR_TYPE, types]);\r\n    }\r\n\r\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\r\n    if (keywords.length) {\r\n      fallthroughStylePatterns.push(\r\n          [PR_KEYWORD,\r\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\r\n           null]);\r\n    }\r\n\r\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\r\n\r\n    var punctuation =\r\n      // The Bash man page says\r\n\r\n      // A word is a sequence of characters considered as a single\r\n      // unit by GRUB. Words are separated by metacharacters,\r\n      // which are the following plus space, tab, and newline: { }\r\n      // | & $ ; < >\r\n      // ...\r\n      \r\n      // A word beginning with # causes that word and all remaining\r\n      // characters on that line to be ignored.\r\n\r\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\r\n      // comment but empirically\r\n      // $ echo {#}\r\n      // {#}\r\n      // $ echo \\$#\r\n      // $#\r\n      // $ echo }#\r\n      // }#\r\n\r\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\r\n\r\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\r\n      // suggests that this definition is compatible with a\r\n      // default mode that tries to use a single token definition\r\n      // to recognize both bash/python style comments and C\r\n      // preprocessor directives.\r\n\r\n      // This definition of punctuation does not include # in the list of\r\n      // follow-on exclusions, so # will not be broken before if preceeded\r\n      // by a punctuation character.  We could try to exclude # after\r\n      // [|&;<>] but that doesn't seem to cause many major problems.\r\n      // If that does turn out to be a problem, we should change the below\r\n      // when hc is truthy to include # in the run of punctuation characters\r\n      // only when not followint [|&;<>].\r\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\r\n    if (options['regexLiterals']) {\r\n      punctuation += '(?!\\s*\\/)';\r\n    }\r\n\r\n    fallthroughStylePatterns.push(\r\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\r\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\r\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_LITERAL,\r\n         new RegExp(\r\n             '^(?:'\r\n             // A hex number\r\n             + '0x[a-f0-9]+'\r\n             // or an octal or decimal number,\r\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\r\n             // possibly in scientific notation\r\n             + '(?:e[+\\\\-]?\\\\d+)?'\r\n             + ')'\r\n             // with an optional modifier like UL for unsigned long\r\n             + '[a-z]*', 'i'),\r\n         null, '0123456789'],\r\n        // Don't treat escaped quotes in bash as starting strings.\r\n        // See issue 144.\r\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\r\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\r\n\r\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\r\n  }\r\n\r\n  var decorateSource = sourceDecorator({\r\n        'keywords': ALL_KEYWORDS,\r\n        'hashComments': true,\r\n        'cStyleComments': true,\r\n        'multiLineStrings': true,\r\n        'regexLiterals': true\r\n      });\r\n\r\n  /**\r\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\r\n   * list item.\r\n   *\r\n   * @param {Node} node modified in place.  Its content is pulled into an\r\n   *     HTMLOListElement, and each line is moved into a separate list item.\r\n   *     This requires cloning elements, so the input might not have unique\r\n   *     IDs after numbering.\r\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\r\n   *     be treated as significant.\r\n   */\r\n  function numberLines(node, opt_startLineNum, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n    var lineBreak = /\\r\\n?|\\n/;\r\n  \r\n    var document = node.ownerDocument;\r\n  \r\n    var li = document.createElement('li');\r\n    while (node.firstChild) {\r\n      li.appendChild(node.firstChild);\r\n    }\r\n    // An array of lines.  We split below, so this is initialized to one\r\n    // un-split line.\r\n    var listItems = [li];\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1 && !nocode.test(node.className)) {  // Element\r\n        if ('br' === node.nodeName) {\r\n          breakAfter(node);\r\n          // Discard the <BR> since it is now flush against a </LI>.\r\n          if (node.parentNode) {\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        } else {\r\n          for (var child = node.firstChild; child; child = child.nextSibling) {\r\n            walk(child);\r\n          }\r\n        }\r\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\r\n        var text = node.nodeValue;\r\n        var match = text.match(lineBreak);\r\n        if (match) {\r\n          var firstLine = text.substring(0, match.index);\r\n          node.nodeValue = firstLine;\r\n          var tail = text.substring(match.index + match[0].length);\r\n          if (tail) {\r\n            var parent = node.parentNode;\r\n            parent.insertBefore(\r\n              document.createTextNode(tail), node.nextSibling);\r\n          }\r\n          breakAfter(node);\r\n          if (!firstLine) {\r\n            // Don't leave blank text nodes in the DOM.\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  \r\n    // Split a line after the given node.\r\n    function breakAfter(lineEndNode) {\r\n      // If there's nothing to the right, then we can skip ending the line\r\n      // here, and move root-wards since splitting just before an end-tag\r\n      // would require us to create a bunch of empty copies.\r\n      while (!lineEndNode.nextSibling) {\r\n        lineEndNode = lineEndNode.parentNode;\r\n        if (!lineEndNode) { return; }\r\n      }\r\n  \r\n      function breakLeftOf(limit, copy) {\r\n        // Clone shallowly if this node needs to be on both sides of the break.\r\n        var rightSide = copy ? limit.cloneNode(false) : limit;\r\n        var parent = limit.parentNode;\r\n        if (parent) {\r\n          // We clone the parent chain.\r\n          // This helps us resurrect important styling elements that cross lines.\r\n          // E.g. in <i>Foo<br>Bar</i>\r\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\r\n          var parentClone = breakLeftOf(parent, 1);\r\n          // Move the clone and everything to the right of the original\r\n          // onto the cloned parent.\r\n          var next = limit.nextSibling;\r\n          parentClone.appendChild(rightSide);\r\n          for (var sibling = next; sibling; sibling = next) {\r\n            next = sibling.nextSibling;\r\n            parentClone.appendChild(sibling);\r\n          }\r\n        }\r\n        return rightSide;\r\n      }\r\n  \r\n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\r\n  \r\n      // Walk the parent chain until we reach an unattached LI.\r\n      for (var parent;\r\n           // Check nodeType since IE invents document fragments.\r\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\r\n        copiedListItem = parent;\r\n      }\r\n      // Put it on the list of lines for later processing.\r\n      listItems.push(copiedListItem);\r\n    }\r\n  \r\n    // Split lines while there are lines left to split.\r\n    for (var i = 0;  // Number of lines that have been split so far.\r\n         i < listItems.length;  // length updated by breakAfter calls.\r\n         ++i) {\r\n      walk(listItems[i]);\r\n    }\r\n  \r\n    // Make sure numeric indices show correctly.\r\n    if (opt_startLineNum === (opt_startLineNum|0)) {\r\n      listItems[0].setAttribute('value', opt_startLineNum);\r\n    }\r\n  \r\n    var ol = document.createElement('ol');\r\n    ol.className = 'linenums';\r\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\r\n    for (var i = 0, n = listItems.length; i < n; ++i) {\r\n      li = listItems[i];\r\n      // Stick a class on the LIs so that stylesheets can\r\n      // color odd/even rows, or any other row pattern that\r\n      // is co-prime with 10.\r\n      li.className = 'L' + ((i + offset) % 10);\r\n      if (!li.firstChild) {\r\n        li.appendChild(document.createTextNode('\\xA0'));\r\n      }\r\n      ol.appendChild(li);\r\n    }\r\n  \r\n    node.appendChild(ol);\r\n  }\r\n  /**\r\n   * Breaks {@code job.sourceCode} around style boundaries in\r\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\r\n   * @param {Object} job like <pre>{\r\n   *    sourceCode: {string} source as plain text,\r\n   *    sourceNode: {HTMLElement} the element containing the source,\r\n   *    spans: {Array.<number|Node>} alternating span start indices into source\r\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\r\n   *       span.\r\n   *    decorations: {Array.<number|string} an array of style classes preceded\r\n   *       by the position at which they start in job.sourceCode in order\r\n   * }</pre>\r\n   * @private\r\n   */\r\n  function recombineTagsAndDecorations(job) {\r\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\r\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\r\n    var newlineRe = /\\n/g;\r\n  \r\n    var source = job.sourceCode;\r\n    var sourceLength = source.length;\r\n    // Index into source after the last code-unit recombined.\r\n    var sourceIndex = 0;\r\n  \r\n    var spans = job.spans;\r\n    var nSpans = spans.length;\r\n    // Index into spans after the last span which ends at or before sourceIndex.\r\n    var spanIndex = 0;\r\n  \r\n    var decorations = job.decorations;\r\n    var nDecorations = decorations.length;\r\n    // Index into decorations after the last decoration which ends at or before\r\n    // sourceIndex.\r\n    var decorationIndex = 0;\r\n  \r\n    // Remove all zero-length decorations.\r\n    decorations[nDecorations] = sourceLength;\r\n    var decPos, i;\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      if (decorations[i] !== decorations[i + 2]) {\r\n        decorations[decPos++] = decorations[i++];\r\n        decorations[decPos++] = decorations[i++];\r\n      } else {\r\n        i += 2;\r\n      }\r\n    }\r\n    nDecorations = decPos;\r\n  \r\n    // Simplify decorations.\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      var startPos = decorations[i];\r\n      // Conflate all adjacent decorations that use the same style.\r\n      var startDec = decorations[i + 1];\r\n      var end = i + 2;\r\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\r\n        end += 2;\r\n      }\r\n      decorations[decPos++] = startPos;\r\n      decorations[decPos++] = startDec;\r\n      i = end;\r\n    }\r\n  \r\n    nDecorations = decorations.length = decPos;\r\n  \r\n    var sourceNode = job.sourceNode;\r\n    var oldDisplay;\r\n    if (sourceNode) {\r\n      oldDisplay = sourceNode.style.display;\r\n      sourceNode.style.display = 'none';\r\n    }\r\n    try {\r\n      var decoration = null;\r\n      while (spanIndex < nSpans) {\r\n        var spanStart = spans[spanIndex];\r\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\r\n  \r\n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\r\n  \r\n        var end = Math.min(spanEnd, decEnd);\r\n  \r\n        var textNode = spans[spanIndex + 1];\r\n        var styledText;\r\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\r\n            // Don't introduce spans around empty text nodes.\r\n            && (styledText = source.substring(sourceIndex, end))) {\r\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\r\n          // code to display with spaces instead of line breaks.\r\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\r\n          // space to appear at the beginning of every line but the first.\r\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\r\n          if (isIE8OrEarlier) {\r\n            styledText = styledText.replace(newlineRe, '\\r');\r\n          }\r\n          textNode.nodeValue = styledText;\r\n          var document = textNode.ownerDocument;\r\n          var span = document.createElement('span');\r\n          span.className = decorations[decorationIndex + 1];\r\n          var parentNode = textNode.parentNode;\r\n          parentNode.replaceChild(span, textNode);\r\n          span.appendChild(textNode);\r\n          if (sourceIndex < spanEnd) {  // Split off a text node.\r\n            spans[spanIndex + 1] = textNode\r\n                // TODO: Possibly optimize by using '' if there's no flicker.\r\n                = document.createTextNode(source.substring(end, spanEnd));\r\n            parentNode.insertBefore(textNode, span.nextSibling);\r\n          }\r\n        }\r\n  \r\n        sourceIndex = end;\r\n  \r\n        if (sourceIndex >= spanEnd) {\r\n          spanIndex += 2;\r\n        }\r\n        if (sourceIndex >= decEnd) {\r\n          decorationIndex += 2;\r\n        }\r\n      }\r\n    } finally {\r\n      if (sourceNode) {\r\n        sourceNode.style.display = oldDisplay;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Maps language-specific file extensions to handlers. */\r\n  var langHandlerRegistry = {};\r\n  /** Register a language handler for the given file extensions.\r\n    * @param {function (Object)} handler a function from source code to a list\r\n    *      of decorations.  Takes a single argument job which describes the\r\n    *      state of the computation.   The single parameter has the form\r\n    *      {@code {\r\n    *        sourceCode: {string} as plain text.\r\n    *        decorations: {Array.<number|string>} an array of style classes\r\n    *                     preceded by the position at which they start in\r\n    *                     job.sourceCode in order.\r\n    *                     The language handler should assigned this field.\r\n    *        basePos: {int} the position of source in the larger source chunk.\r\n    *                 All positions in the output decorations array are relative\r\n    *                 to the larger source chunk.\r\n    *      } }\r\n    * @param {Array.<string>} fileExtensions\r\n    */\r\n  function registerLangHandler(handler, fileExtensions) {\r\n    for (var i = fileExtensions.length; --i >= 0;) {\r\n      var ext = fileExtensions[i];\r\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\r\n        langHandlerRegistry[ext] = handler;\r\n      } else if (win['console']) {\r\n        console['warn']('cannot override language handler %s', ext);\r\n      }\r\n    }\r\n  }\r\n  function langHandlerForExtension(extension, source) {\r\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\r\n      // Treat it as markup if the first non whitespace character is a < and\r\n      // the last non-whitespace character is a >.\r\n      extension = /^\\s*</.test(source)\r\n          ? 'default-markup'\r\n          : 'default-code';\r\n    }\r\n    return langHandlerRegistry[extension];\r\n  }\r\n  registerLangHandler(decorateSource, ['default-code']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [],\r\n          [\r\n           [PR_PLAIN,       /^[^<?]+/],\r\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\r\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\r\n           // Unescaped content in an unknown language\r\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\r\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\r\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\r\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\r\n           // Unescaped content in javascript.  (Or possibly vbscript).\r\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\r\n           // Contains unescaped stylesheet content\r\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\r\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\r\n          ]),\r\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [\r\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\r\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\r\n           ],\r\n          [\r\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\r\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\r\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\r\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\r\n           ]),\r\n      ['in.tag']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CPP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'types': C_TYPES\r\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': 'null,true,false'\r\n        }), ['json']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CSHARP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'verbatimStrings': true,\r\n          'types': C_TYPES\r\n        }), ['cs']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JAVA_KEYWORDS,\r\n          'cStyleComments': true\r\n        }), ['java']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': SH_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true\r\n        }), ['bash', 'bsh', 'csh', 'sh']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PYTHON_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'tripleQuotedStrings': true\r\n        }), ['cv', 'py', 'python']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PERL_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': 2  // multiline regex literals\r\n        }), ['perl', 'pl', 'pm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUBY_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': true\r\n        }), ['rb', 'ruby']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JSCRIPT_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'regexLiterals': true\r\n        }), ['javascript', 'js']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': COFFEE_KEYWORDS,\r\n          'hashComments': 3,  // ### style block comments\r\n          'cStyleComments': true,\r\n          'multilineStrings': true,\r\n          'tripleQuotedStrings': true,\r\n          'regexLiterals': true\r\n        }), ['coffee']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUST_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'multilineStrings': true\r\n        }), ['rc', 'rs', 'rust']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\r\n\r\n  function applyDecorator(job) {\r\n    var opt_langExtension = job.langExtension;\r\n\r\n    try {\r\n      // Extract tags, and convert the source code to plain text.\r\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\r\n      /** Plain text. @type {string} */\r\n      var source = sourceAndSpans.sourceCode;\r\n      job.sourceCode = source;\r\n      job.spans = sourceAndSpans.spans;\r\n      job.basePos = 0;\r\n\r\n      // Apply the appropriate language handler\r\n      langHandlerForExtension(opt_langExtension, source)(job);\r\n\r\n      // Integrate the decorations and tags back into the source code,\r\n      // modifying the sourceNode in place.\r\n      recombineTagsAndDecorations(job);\r\n    } catch (e) {\r\n      if (win['console']) {\r\n        console['log'](e && e['stack'] || e);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Pretty print a chunk of code.\r\n   * @param sourceCodeHtml {string} The HTML to pretty print.\r\n   * @param opt_langExtension {string} The language name to use.\r\n   *     Typically, a filename extension like 'cpp' or 'java'.\r\n   * @param opt_numberLines {number|boolean} True to number lines,\r\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n   */\r\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\r\n    var container = document.createElement('div');\r\n    // This could cause images to load and onload listeners to fire.\r\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\r\n    // We assume that the inner HTML is from a trusted source.\r\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\r\n    // when it is injected into a <pre> tag.\r\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\r\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\r\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\r\n    container = container.firstChild;\r\n    if (opt_numberLines) {\r\n      numberLines(container, opt_numberLines, true);\r\n    }\r\n\r\n    var job = {\r\n      langExtension: opt_langExtension,\r\n      numberLines: opt_numberLines,\r\n      sourceNode: container,\r\n      pre: 1\r\n    };\r\n    applyDecorator(job);\r\n    return container.innerHTML;\r\n  }\r\n\r\n   /**\r\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n    * {@code class=prettyprint} and prettify them.\r\n    *\r\n    * @param {Function} opt_whenDone called when prettifying is done.\r\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n    *   containing all the elements to pretty print.\r\n    *   Defaults to {@code document.body}.\r\n    */\r\n  function $prettyPrint(opt_whenDone, opt_root) {\r\n    var root = opt_root || document.body;\r\n    var doc = root.ownerDocument || document;\r\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\r\n    // fetch a list of nodes to rewrite\r\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\r\n    var elements = [];\r\n    for (var i = 0; i < codeSegments.length; ++i) {\r\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\r\n        elements.push(codeSegments[i][j]);\r\n      }\r\n    }\r\n    codeSegments = null;\r\n\r\n    var clock = Date;\r\n    if (!clock['now']) {\r\n      clock = { 'now': function () { return +(new Date); } };\r\n    }\r\n\r\n    // The loop is broken into a series of continuations to make sure that we\r\n    // don't make the browser unresponsive when rewriting a large page.\r\n    var k = 0;\r\n    var prettyPrintingJob;\r\n\r\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\r\n    var prettyPrintRe = /\\bprettyprint\\b/;\r\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\r\n    var preformattedTagNameRe = /pre|xmp/i;\r\n    var codeRe = /^code$/i;\r\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\r\n    var EMPTY = {};\r\n\r\n    function doWork() {\r\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\r\n                     clock['now']() + 250 /* ms */ :\r\n                     Infinity);\r\n      for (; k < elements.length && clock['now']() < endTime; k++) {\r\n        var cs = elements[k];\r\n\r\n        // Look for a preceding comment like\r\n        // <?prettify lang=\"...\" linenums=\"...\"?>\r\n        var attrs = EMPTY;\r\n        {\r\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\r\n            var nt = preceder.nodeType;\r\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\r\n            // like <!--?foo?-->, but in XML is a processing instruction\r\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\r\n            if (value\r\n                ? !/^\\??prettify\\b/.test(value)\r\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\r\n              // Skip over white-space text nodes but not others.\r\n              break;\r\n            }\r\n            if (value) {\r\n              attrs = {};\r\n              value.replace(\r\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\r\n                function (_, name, value) { attrs[name] = value; });\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        var className = cs.className;\r\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\r\n            // Don't redo this if we've already done it.\r\n            // This allows recalling pretty print to just prettyprint elements\r\n            // that have been added to the page since last call.\r\n            && !prettyPrintedRe.test(className)) {\r\n\r\n          // make sure this is not nested in an already prettified element\r\n          var nested = false;\r\n          for (var p = cs.parentNode; p; p = p.parentNode) {\r\n            var tn = p.tagName;\r\n            if (preCodeXmpRe.test(tn)\r\n                && p.className && prettyPrintRe.test(p.className)) {\r\n              nested = true;\r\n              break;\r\n            }\r\n          }\r\n          if (!nested) {\r\n            // Mark done.  If we fail to prettyprint for whatever reason,\r\n            // we shouldn't try again.\r\n            cs.className += ' prettyprinted';\r\n\r\n            // If the classes includes a language extensions, use it.\r\n            // Language extensions can be specified like\r\n            //     <pre class=\"prettyprint lang-cpp\">\r\n            // the language extension \"cpp\" is used to find a language handler\r\n            // as passed to PR.registerLangHandler.\r\n            // HTML5 recommends that a language be specified using \"language-\"\r\n            // as the prefix instead.  Google Code Prettify supports both.\r\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\r\n            var langExtension = attrs['lang'];\r\n            if (!langExtension) {\r\n              langExtension = className.match(langExtensionRe);\r\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\r\n              var wrapper;\r\n              if (!langExtension && (wrapper = childContentWrapper(cs))\r\n                  && codeRe.test(wrapper.tagName)) {\r\n                langExtension = wrapper.className.match(langExtensionRe);\r\n              }\r\n\r\n              if (langExtension) { langExtension = langExtension[1]; }\r\n            }\r\n\r\n            var preformatted;\r\n            if (preformattedTagNameRe.test(cs.tagName)) {\r\n              preformatted = 1;\r\n            } else {\r\n              var currentStyle = cs['currentStyle'];\r\n              var defaultView = doc.defaultView;\r\n              var whitespace = (\r\n                  currentStyle\r\n                  ? currentStyle['whiteSpace']\r\n                  : (defaultView\r\n                     && defaultView.getComputedStyle)\r\n                  ? defaultView.getComputedStyle(cs, null)\r\n                  .getPropertyValue('white-space')\r\n                  : 0);\r\n              preformatted = whitespace\r\n                  && 'pre' === whitespace.substring(0, 3);\r\n            }\r\n\r\n            // Look for a class like linenums or linenums:<n> where <n> is the\r\n            // 1-indexed number of the first line.\r\n            var lineNums = attrs['linenums'];\r\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\r\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\r\n              lineNums =\r\n                lineNums\r\n                ? lineNums[1] && lineNums[1].length\r\n                  ? +lineNums[1] : true\r\n                : false;\r\n            }\r\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\r\n\r\n            // do the pretty printing\r\n            prettyPrintingJob = {\r\n              langExtension: langExtension,\r\n              sourceNode: cs,\r\n              numberLines: lineNums,\r\n              pre: preformatted\r\n            };\r\n            applyDecorator(prettyPrintingJob);\r\n          }\r\n        }\r\n      }\r\n      if (k < elements.length) {\r\n        // finish up in a continuation\r\n        setTimeout(doWork, 250);\r\n      } else if ('function' === typeof opt_whenDone) {\r\n        opt_whenDone();\r\n      }\r\n    }\r\n\r\n    doWork();\r\n  }\r\n\r\n  /**\r\n   * Contains functions for creating and registering new language handlers.\r\n   * @type {Object}\r\n   */\r\n  var PR = win['PR'] = {\r\n        'createSimpleLexer': createSimpleLexer,\r\n        'registerLangHandler': registerLangHandler,\r\n        'sourceDecorator': sourceDecorator,\r\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\r\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\r\n        'PR_COMMENT': PR_COMMENT,\r\n        'PR_DECLARATION': PR_DECLARATION,\r\n        'PR_KEYWORD': PR_KEYWORD,\r\n        'PR_LITERAL': PR_LITERAL,\r\n        'PR_NOCODE': PR_NOCODE,\r\n        'PR_PLAIN': PR_PLAIN,\r\n        'PR_PUNCTUATION': PR_PUNCTUATION,\r\n        'PR_SOURCE': PR_SOURCE,\r\n        'PR_STRING': PR_STRING,\r\n        'PR_TAG': PR_TAG,\r\n        'PR_TYPE': PR_TYPE,\r\n        'prettyPrintOne':\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\r\n             : (prettyPrintOne = $prettyPrintOne),\r\n        'prettyPrint': prettyPrint =\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrint'] = $prettyPrint)\r\n             : (prettyPrint = $prettyPrint)\r\n      };\r\n\r\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\r\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\r\n  // The Asynchronous Module Definition (AMD) API specifies a\r\n  // mechanism for defining modules such that the module and its\r\n  // dependencies can be asynchronously loaded.\r\n  // ...\r\n  // To allow a clear indicator that a global define function (as\r\n  // needed for script src browser loading) conforms to the AMD API,\r\n  // any global define function SHOULD have a property called \"amd\"\r\n  // whose value is an object. This helps avoid conflict with any\r\n  // other existing JavaScript code that could have defined a define()\r\n  // function that does not conform to the AMD API.\r\n  if (typeof define === \"function\" && define['amd']) {\r\n    define(\"google-code-prettify\", [], function () {\r\n      return PR; \r\n    });\r\n  }\r\n})();\r\n\ndefine(\"prettify\", function(){});\n\n",
             "define('itemView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/item.html',\r\n  'text!tpl/class.html',\r\n  'text!tpl/itemEnd.html',\r\n  // Tools\r\n  'prettify'\r\n], function(App, itemTpl, classTpl, endTpl) {\r\n  'use strict';\r\n\r\n  var appVersion = App.project.version || 'master';\r\n\r\n  var itemView = Backbone.View.extend({\r\n    el: '#item',\r\n    init: function() {\r\n      this.$html = $('html');\r\n      this.$body = $('body');\r\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\r\n\r\n      this.tpl = _.template(itemTpl);\r\n      this.classTpl = _.template(classTpl);\r\n      this.endTpl = _.template(endTpl);\r\n\r\n      return this;\r\n    },\r\n    getSyntax: function(isMethod, cleanItem) {\r\n      var isConstructor = cleanItem.is_constructor;\r\n      var syntax = '';\r\n      if (isConstructor) {\r\n        syntax += 'new ';\r\n      } else if (cleanItem.static && cleanItem.class) {\r\n        syntax += cleanItem.class + '.';\r\n      }\r\n      syntax += cleanItem.name;\r\n\r\n      if (isMethod || isConstructor) {\r\n        syntax += '(';\r\n        if (cleanItem.params) {\r\n          for (var i = 0; i < cleanItem.params.length; i++) {\r\n            var p = cleanItem.params[i];\r\n            if (p.optional) {\r\n              syntax += '[';\r\n            }\r\n            syntax += p.name;\r\n            if (p.optdefault) {\r\n              syntax += '=' + p.optdefault;\r\n            }\r\n            if (p.optional) {\r\n              syntax += ']';\r\n            }\r\n            if (i !== cleanItem.params.length - 1) {\r\n              syntax += ', ';\r\n            }\r\n          }\r\n        }\r\n        syntax += ')';\r\n      }\r\n\r\n      return syntax;\r\n    },\r\n    // Return a list of valid syntaxes across all overloaded versions of\r\n    // this item.\r\n    //\r\n    // For reference, we ultimately want to replicate something like this:\r\n    //\r\n    // https://processing.org/reference/color_.html\r\n    getSyntaxes: function(isMethod, cleanItem) {\r\n      var overloads = cleanItem.overloads || [cleanItem];\r\n      return overloads.map(this.getSyntax.bind(this, isMethod));\r\n    },\r\n    render: function(item) {\r\n      if (item) {\r\n        var itemHtml = '';\r\n        var cleanItem = this.clean(item);\r\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\r\n        var collectionName = isClass\r\n            ? 'Constructor'\r\n            : this.capitalizeFirst(cleanItem.itemtype),\r\n          isConstructor = cleanItem.is_constructor;\r\n        cleanItem.isMethod = collectionName === 'Method';\r\n\r\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\r\n\r\n        // Set the item header (title)\r\n\r\n        // Set item contents\r\n        if (isClass) {\r\n          var constructor = this.tpl({\r\n            item: cleanItem,\r\n            isClass: true,\r\n            isConstructor: isConstructor,\r\n            syntaxes: syntaxes\r\n          });\r\n          cleanItem.constructor = constructor;\r\n\r\n          var contents = _.find(App.classes, function(c) {\r\n            return c.name === cleanItem.name;\r\n          });\r\n          cleanItem.things = contents.items;\r\n\r\n          itemHtml = this.classTpl(cleanItem);\r\n        } else {\r\n          cleanItem.constRefs =\r\n            item.module === 'Constants' && App.data.consts[item.name];\r\n\r\n          itemHtml = this.tpl({\r\n            item: cleanItem,\r\n            isClass: false,\r\n            isConstructor: false,\r\n            syntaxes: syntaxes\r\n          });\r\n        }\r\n\r\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\r\n\r\n        // Insert the view in the dom\r\n        this.$el.html(itemHtml);\r\n\r\n        renderCode(cleanItem.name);\r\n\r\n        // Set the document title based on the item name.\r\n        // If it is a method, add parentheses to the name\r\n        if (item.itemtype === 'method') {\r\n          App.pageView.appendToDocumentTitle(item.name + '()');\r\n        } else {\r\n          App.pageView.appendToDocumentTitle(item.name);\r\n        }\r\n\r\n        // Hook up alt-text for examples\r\n        setTimeout(function() {\r\n          var alts = $('.example-content')[0];\r\n          if (alts) {\r\n            alts = $(alts)\r\n              .data('alt')\r\n              .split('\\n');\r\n\r\n            var canvases = $('.cnv_div');\r\n            for (var j = 0; j < alts.length; j++) {\r\n              if (j < canvases.length) {\r\n                $(canvases[j]).append(\r\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\r\n                );\r\n              }\r\n            }\r\n          }\r\n        }, 1000);\r\n        Prism.highlightAll();\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Clean item properties: url encode properties containing paths.\r\n     * @param {object} item The item object.\r\n     * @returns {object} Returns the same item object with urlencoded paths.\r\n     */\r\n    clean: function(item) {\r\n      var cleanItem = item;\r\n\r\n      if (cleanItem.hasOwnProperty('file')) {\r\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\r\n      }\r\n      return cleanItem;\r\n    },\r\n    /**\r\n     * Show a single item.\r\n     * @param {object} item Item object.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function(item) {\r\n      if (item) {\r\n        this.render(item);\r\n      }\r\n\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      this.scrollTop();\r\n      $('#item').focus();\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a message if no item is found.\r\n     * @returns {object} This view.\r\n     */\r\n    nothingFound: function() {\r\n      this.$el.html(\r\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\r\n      );\r\n      App.pageView.hideContentViews();\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Scroll to the top of the window with an animation.\r\n     */\r\n    scrollTop: function() {\r\n      // Hack for Chrome/Firefox scroll animation\r\n      // Chrome scrolls 'body', Firefox scrolls 'html'\r\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\r\n      if (scroll) {\r\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\r\n      }\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function(str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n  });\r\n\r\n  return itemView;\r\n});\r\n\n",
             "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\r\\n  <br>\\r\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\r\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\r\\n</div>\\r\\n\\r\\n<div id=\\'collection-list-categories\\'>\\r\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\r\\n<% var i=0; %>\\r\\n<% var max=Math.floor(groups.length/4); %>\\r\\n<% var rem=groups.length%4; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% var m = rem > 0 ? 1 : 0 %>\\r\\n  <% if (i === 0) { %>\\r\\n    <ul aria-labelledby=\"categories\">\\r\\n    <% } %>\\r\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\r\\n    <% if (i === (max+m-1)) { %>\\r\\n    </ul>\\r\\n  \\t<% rem-- %>\\r\\n  \\t<% i=0 %>\\r\\n  <% } else { %>\\r\\n  \\t<% i++ %>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
             "define('menuView',[\r\n  'App',\r\n  'text!tpl/menu.html'\r\n], function(App, menuTpl) {\r\n\r\n  var menuView = Backbone.View.extend({\r\n    el: '#collection-list-nav',\r\n    /**\r\n     * Init.\r\n     * @returns {object} This view.\r\n     */\r\n    init: function() {\r\n      this.menuTpl = _.template(menuTpl);\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     * @returns {object} This view.\r\n     */\r\n    render: function() {\r\n\r\n      var groups = [];\r\n      _.each(App.modules, function (item, i) {\r\n        if (!item.is_submodule) {\r\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n            groups.push(item.name);\r\n          }\r\n        }\r\n        //}\r\n      });\r\n\r\n      // Sort groups by name A-Z\r\n      groups.sort();\r\n\r\n      var menuHtml = this.menuTpl({\r\n        'groups': groups\r\n      });\r\n\r\n      // Render the view\r\n      this.$el.html(menuHtml);\r\n    },\r\n\r\n    hide: function() {\r\n      this.$el.hide();\r\n    },\r\n\r\n    show: function() {\r\n      this.$el.show();\r\n    },\r\n\r\n    /**\r\n     * Update the menu.\r\n     * @param {string} el The name of the current route.\r\n     */\r\n    update: function(menuItem) {\r\n      //console.log(menuItem);\r\n      // this.$menuItems.removeClass('active');\r\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\r\n\r\n    }\r\n  });\r\n\r\n  return menuView;\r\n\r\n});\r\n\n",
        -    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\r\\n\\r\\n<p><%= module.description %></p>\\r\\n\\r\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\r\\n\\r\\n<% var t = 0; col = 0; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% if (t == 0) { %> \\r\\n    <div class=\"column_<%=col%>\">\\r\\n  <% } %>\\r\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\r\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\r\\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\r\\n    <% if (group.hash) { %> </a> <% } %>\\r\\n  <% } %>\\r\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\r\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\r\\n    <% t++; %>\\r\\n  <% }); %>\\r\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\r\\n    </div>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        +    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\r\\n\\r\\n<p><%= module.description %></p>\\r\\n\\r\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\r\\n\\r\\n<% var t = 0; col = 0; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% if (t == 0) { %> \\r\\n    <div class=\"column_<%=col%>\">\\r\\n  <% } %>\\r\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\r\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\r\\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\r\\n    <% if (group.hash) { %> </a><br> <% } %>\\r\\n  <% } %>\\r\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\r\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\r\\n    <% t++; %>\\r\\n  <% }); %>\\r\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\r\\n    </div>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
             "define(\r\n  'libraryView',[\r\n    'App',\r\n    // Templates\r\n    'text!tpl/library.html'\r\n  ],\r\n  function(App, libraryTpl) {\r\n    var libraryView = Backbone.View.extend({\r\n      el: '#list',\r\n      events: {},\r\n      /**\r\n       * Init.\r\n       */\r\n      init: function() {\r\n        this.libraryTpl = _.template(libraryTpl);\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Render the list.\r\n       */\r\n      render: function(m, listCollection) {\r\n        if (m && listCollection) {\r\n          var self = this;\r\n\r\n          // Render items and group them by module\r\n          // module === group\r\n          this.groups = {};\r\n          _.each(m.items, function(item, i) {\r\n            var module = item.module || '_';\r\n            var group;\r\n            // Override default group with a selected category\r\n            // TODO: Overwriting with the first category might not be the best choice\r\n            // We might also want to have links for categories\r\n            if (item.category && item.category[0]) {\r\n              group = item.category[0];\r\n              // Populate item.hash\r\n              App.router.getHash(item);\r\n\r\n              // Create a group list without link hash\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: undefined,\r\n                  items: []\r\n                };\r\n              }\r\n            } else {\r\n              group = item.class || '_';\r\n              var hash = App.router.getHash(item);\r\n\r\n              var ind = hash.lastIndexOf('/');\r\n              hash = hash.substring(0, ind);\r\n\r\n              // Create a group list\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: hash,\r\n                  items: []\r\n                };\r\n              }\r\n            }\r\n\r\n            self.groups[group].items.push(item);\r\n          });\r\n\r\n          // Sort groups by name A-Z\r\n          self.groups = _.sortBy(self.groups, this.sortByName);\r\n\r\n          // Put the <li> items html into the list <ul>\r\n          var libraryHtml = self.libraryTpl({\r\n            title: self.capitalizeFirst(listCollection),\r\n            module: m.module,\r\n            totalItems: m.items.length,\r\n            groups: self.groups\r\n          });\r\n\r\n          // Render the view\r\n          this.$el.html(libraryHtml);\r\n        }\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Show a list of items.\r\n       * @param {array} items Array of item objects.\r\n       * @returns {object} This view.\r\n       */\r\n      show: function(listGroup) {\r\n        if (App[listGroup]) {\r\n          this.render(App[listGroup], listGroup);\r\n        }\r\n        App.pageView.hideContentViews();\r\n\r\n        this.$el.show();\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Helper method to capitalize the first letter of a string\r\n       * @param {string} str\r\n       * @returns {string} Returns the string.\r\n       */\r\n      capitalizeFirst: function(str) {\r\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n      },\r\n      /**\r\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\r\n       * @param {string} a\r\n       * @param {string} b\r\n       * @returns {Array} Returns an array with elements sorted from A to Z.\r\n       */\r\n      sortAZ: function(a, b) {\r\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\r\n      },\r\n\r\n      sortByName: function(a, b) {\r\n        if (a.name === 'p5') return -1;\r\n        else return 0;\r\n      }\r\n    });\r\n\r\n    return libraryView;\r\n  }\r\n);\r\n\n",
             "define('pageView',[\r\n  'App',\r\n\r\n  // Views\r\n  'searchView',\r\n  'listView',\r\n  'itemView',\r\n  'menuView',\r\n  'libraryView'\r\n], function(App, searchView, listView, itemView, menuView, libraryView) {\r\n\r\n  // Store the original title parts so we can substitue different endings.\r\n  var _originalDocumentTitle = window.document.title;\r\n\r\n  var pageView = Backbone.View.extend({\r\n    el: 'body',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      App.$container = $('#container');\r\n      App.contentViews = [];\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     */\r\n    render: function() {\r\n\r\n      // Menu view\r\n      if (!App.menuView) {\r\n        App.menuView = new menuView();\r\n        App.menuView.init().render();\r\n      }\r\n\r\n      // Item view\r\n      if (!App.itemView) {\r\n        App.itemView = new itemView();\r\n        App.itemView.init().render();\r\n        // Add the item view to the views array\r\n        App.contentViews.push(App.itemView);\r\n      }\r\n\r\n      // List view\r\n      if (!App.listView) {\r\n        App.listView = new listView();\r\n        App.listView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.listView);\r\n      }\r\n\r\n      // Library view\r\n      if (!App.libraryView) {\r\n        App.libraryView = new libraryView();\r\n        App.libraryView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.libraryView);\r\n      }\r\n\r\n      // Search\r\n      if (!App.searchView) {\r\n        App.searchView = new searchView();\r\n        App.searchView.init().render();\r\n      }\r\n      return this;\r\n    },\r\n    /**\r\n     * Hide item and list views.\r\n     * @returns {object} This view.\r\n     */\r\n    hideContentViews: function() {\r\n      _.each(App.contentViews, function(view, i) {\r\n        view.$el.hide();\r\n      });\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Append the supplied name to the first part of original document title.\r\n     * If no name is supplied, the title will reset to the original one.\r\n     */\r\n    appendToDocumentTitle: function(name){\r\n      if(name){\r\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\r\n        window.document.title = [firstTitlePart, name].join(\" | \");\r\n      } else {\r\n        window.document.title = _originalDocumentTitle;\r\n      }\r\n    }    \r\n  });\r\n\r\n  return pageView;\r\n\r\n});\r\n\n",
             "define('router',[\r\n  'App'\r\n], function(App) {\r\n\r\n  'use strict'; //\r\n\r\n  var Router = Backbone.Router.extend({\r\n\r\n    routes: {\r\n      '': 'list',\r\n      'p5': 'list',\r\n      'p5/': 'list',\r\n      'classes': 'list',\r\n      'search': 'search',\r\n      'libraries/:lib': 'library',\r\n      ':searchClass(/:searchItem)': 'get'\r\n    },\r\n    /**\r\n     * Whether the json API data was loaded.\r\n     */\r\n    _initialized: false,\r\n    /**\r\n     * Initialize the app: load json API data and create searchable arrays.\r\n     */\r\n    init: function(callback) {\r\n      var self = this;\r\n      require(['pageView'], function(pageView) {\r\n\r\n        // If already initialized, move away from here!\r\n        if (self._initialized) {\r\n          if (callback)\r\n            callback();\r\n          return;\r\n        }\r\n\r\n        // Update initialization state: must be done now to avoid recursive mess\r\n        self._initialized = true;\r\n\r\n        // Render views\r\n        if (!App.pageView) {\r\n          App.pageView = new pageView();\r\n          App.pageView.init().render();\r\n        }\r\n\r\n        // If a callback is set (a route has already been called), run it\r\n        // otherwise, show the default list\r\n        if (callback)\r\n          callback();\r\n        else\r\n          self.list();\r\n      });\r\n    },\r\n    /**\r\n     * Start route. Simply check if initialized.\r\n     */\r\n    start: function() {\r\n      this.init();\r\n    },\r\n    /**\r\n     * Show item details by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     */\r\n    get: function(searchClass, searchItem) {\r\n\r\n      // if looking for a library page, redirect\r\n      if (searchClass === 'p5.sound' && !searchItem) {\r\n        window.location.hash = '/libraries/'+searchClass;\r\n        return;\r\n      }\r\n\r\n      var self = this;\r\n      this.init(function() {\r\n        var item = self.getItem(searchClass, searchItem);\r\n\r\n        App.menuView.hide();\r\n\r\n        if (item) {\r\n          App.itemView.show(item);\r\n        } else {\r\n          //App.itemView.nothingFound();\r\n\r\n          self.list();\r\n        }\r\n\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Returns one item object by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     * @returns {object} The item found or undefined if nothing was found.\r\n     */\r\n    getItem: function(searchClass, searchItem) {\r\n      var classes = App.classes,\r\n              items = App.allItems,\r\n              classesCount = classes.length,\r\n              itemsCount = items.length,\r\n              className = searchClass ? searchClass.toLowerCase() : undefined,\r\n              itemName = searchItem ? searchItem : undefined,\r\n              found;\r\n\r\n      // Only search for a class, if itemName is undefined\r\n      if (className && !itemName) {\r\n        for (var i = 0; i < classesCount; i++) {\r\n          if (classes[i].name.toLowerCase() === className) {\r\n            found = classes[i];\r\n            _.each(found.items, function(i, idx) {\r\n              i.hash = App.router.getHash(i);\r\n            });\r\n            break;\r\n          }\r\n        }\r\n        // Search for a class item\r\n      } else if (className && itemName) {\r\n        // Search case sensitively\r\n        for (var i = 0; i < itemsCount; i++) {\r\n          if (items[i].class.toLowerCase() === className &&\r\n            items[i].name === itemName) {\r\n            found = items[i];\r\n            break;\r\n          }\r\n        }\r\n\r\n        // If no match was found, fallback to search case insensitively\r\n        if(!found){\r\n          for (var i = 0; i < itemsCount; i++) {\r\n            if(items[i].class.toLowerCase() === className &&\r\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\r\n              found = items[i];\r\n              break;\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      return found;\r\n    },\r\n    /**\r\n     * List items.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    list: function(collection) {\r\n\r\n      collection = 'allItems';\r\n\r\n      // Make sure collection is valid\r\n      if (App.collections.indexOf(collection) < 0) {\r\n        return;\r\n      }\r\n\r\n      this.init(function() {\r\n        App.menuView.show(collection);\r\n        App.menuView.update(collection);\r\n        App.listView.show(collection);\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Display information for a library.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    library: function(collection) {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.libraryView.show(collection.substring(3)); //remove p5.\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Close all content views.\r\n     */\r\n    search: function() {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.pageView.hideContentViews();\r\n      });\r\n    },\r\n\r\n    /**\r\n     * Create an hash/url for the item.\r\n     * @param {Object} item A class, method, property or event object.\r\n     * @returns {String} The hash string, including the '#'.\r\n     */\r\n     getHash: function(item) {\r\n\r\n       if (!item.hash) {\r\n\r\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\r\n\r\n         if (item.class) {\r\n           var clsFunc = '#/' + item.class + '.' + item.name;\r\n           var idx = clsFunc.lastIndexOf('.');\r\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\r\n         } else {\r\n          item.hash = '#/' + item.name;\r\n         }\r\n       }\r\n\r\n       return item.hash;\r\n    }\r\n  });\r\n\r\n  \r\n  function styleCodeLinks() {\r\n    var links = document.getElementsByTagName(\"a\");\r\n    for (var iLink = 0; iLink < links.length; iLink++) {\r\n      var link = links[iLink];\r\n      if (link.hash.startsWith('#/p5')) {\r\n        link.classList.add('code');\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n  // Get the router\r\n  App.router = new Router();\r\n\r\n  // Start history\r\n  Backbone.history.start();\r\n\r\n  return App.router;\r\n\r\n});\r\n\n",
        -    "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
        +    "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
             "}());"
           ]
         }
        \ No newline at end of file
        diff --git a/src/templates/pages/reference/index.hbs b/src/templates/pages/reference/index.hbs
        index c084af60c4..c5538b1508 100644
        --- a/src/templates/pages/reference/index.hbs
        +++ b/src/templates/pages/reference/index.hbs
        @@ -109,12 +109,12 @@ slug: reference/
                 if (translations[obj] && translations[obj][name]) {
                   var entry = translations[obj][name];
                   $('.description-text').html('<p>'+entry.description+'</p>');
        -          $('.returns').html($('.returns').contents()[0].innerHTML + ": " + entry.returns);
        +          $('.returns').html(entry.returns);
                   $('.params').find('ul').each(function(i) {
                     if (i < entry.params.length) {
        -              $(this).children().each(function(j){
        -                $(this).children().eq(1).children().eq(1).html(entry.params[i]);
        -              })
        +              $(this).children('li').each(function(j){
        +                $(this).children('.paramtype').html(entry.params[j]);
        +              });
                     }
                   });
                 }
        diff --git a/src/templates/partials/asterisk.hbs b/src/templates/partials/asterisk.hbs
        index dc972c5d99..66182f53fd 100644
        --- a/src/templates/partials/asterisk.hbs
        +++ b/src/templates/partials/asterisk.hbs
        @@ -4,5 +4,4 @@
         <p class="clearfix"> &nbsp; </p>
         
         <object type="image/svg+xml" data="{{assets}}/img/thick-asterisk-alone.svg" id="asterisk-design-element" aria-hidden="true">
        -     *<!-- to do: add fallback image in CSS -->
         </object>
        diff --git a/src/yuidoc-p5-theme-src/scripts/main.js b/src/yuidoc-p5-theme-src/scripts/main.js
        index 65add4ddc3..3941415f7c 100644
        --- a/src/yuidoc-p5-theme-src/scripts/main.js
        +++ b/src/yuidoc-p5-theme-src/scripts/main.js
        @@ -16,7 +16,7 @@ require([
           './documented-method'], function(App, DocumentedMethod) {
         
           // Set collections
        -  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound', 'p5.dom'];
        +  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];
         
           // Get json API data
           $.getJSON('data.min.json', function(data) {
        diff --git a/src/yuidoc-p5-theme-src/scripts/tpl/class.html b/src/yuidoc-p5-theme-src/scripts/tpl/class.html
        index 6a0058168b..dcc23a3fd8 100644
        --- a/src/yuidoc-p5-theme-src/scripts/tpl/class.html
        +++ b/src/yuidoc-p5-theme-src/scripts/tpl/class.html
        @@ -1,32 +1,32 @@
         
         <% if (typeof constructor !== 'undefined') { %>
         <div class="constructor">
        -  <!--<h2>Constructor</h2>--> 
           <%=constructor%>
         </div>
         <% } %>
         
        -<% var fields = _.filter(things, function(item) { return item.itemtype === 'property' && item.access !== 'private' }); %>
        +<% let fields = _.filter(things, function(item) { return item.itemtype === 'property' && item.access !== 'private' }); %>
         <% if (fields.length > 0) { %>
        -  <h4>Fields</h4>
        -  <p>
        -    <% _.each(fields, function(item) { %>
        -      <a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %> ><%=item.name%></a>: <%= item.description %>
        -      <br>
        -    <% }); %>
        -  </p>
        +  <h3 id='reference-fields'>Fields</h3>
        +  <ul aria-labelledby='reference-fields'>
        +  <% _.each(fields, function(item) { %>
        +    <li>
        +      <div class='paramname'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>
        +      <div class='paramtype'><%= item.description %></div>
        +    </li>
        +  <% }); %>
        +  </ul>
         <% } %>
         
        -<% var methods = _.filter(things, function(item) { return item.itemtype === 'method' && item.access !== 'private' }); %>
        +<% let methods = _.filter(things, function(item) { return item.itemtype === 'method' && item.access !== 'private' }); %>
         <% if (methods.length > 0) { %>
        -  <h4>Methods</h4>
        -  <p>
        -    <table>
        +  <h3 id='reference-methods'>Methods</h3>
        +  <ul aria-labelledby='reference-methods'>
             <% _.each(methods, function(item) { %>
        -      <tr>
        -      <td><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === 'method') { %>()<%}%></a></td><td><div class="method_description"><%= item.description %></div></td>
        -      </tr>
        +      <li>
        +        <div class='paramname'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === 'method') { %>()<%}%></a></div>
        +        <div class='paramtype'><%= item.description %></div>
        +      </li>
             <% }); %>
        -    </table>
        -  </p>
        +  </ul>
         <% } %>
        diff --git a/src/yuidoc-p5-theme-src/scripts/tpl/library.html b/src/yuidoc-p5-theme-src/scripts/tpl/library.html
        index 92f340674f..ab183f813e 100644
        --- a/src/yuidoc-p5-theme-src/scripts/tpl/library.html
        +++ b/src/yuidoc-p5-theme-src/scripts/tpl/library.html
        @@ -13,7 +13,7 @@ <h3><%= module.name %> library</h3>
           <% if (group.name !== module.name && group.name !== 'p5') { %>
             <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  
             <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>
        -    <% if (group.hash) { %> </a> <% } %>
        +    <% if (group.hash) { %> </a><br> <% } %>
           <% } %>
           <% _.each(group.items.filter(function(item) {return item.access !== 'private'}), function(item) { %>
             <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === 'method') { %>()<%}%></a><br>
        diff --git a/src/yuidoc-p5-theme-src/scripts/views/listView.js b/src/yuidoc-p5-theme-src/scripts/views/listView.js
        index d3e185d936..125a3f440b 100644
        --- a/src/yuidoc-p5-theme-src/scripts/views/listView.js
        +++ b/src/yuidoc-p5-theme-src/scripts/views/listView.js
        @@ -41,6 +41,9 @@ define([
                     }
                     var hash = App.router.getHash(item);
         
        +            // fixes broken links for #/p5/> and #/p5/>=
        +            item.hash = item.hash.replace('>', '&gt;');
        +
                     // Create a group list
                     if (!self.groups[group]) {
                       self.groups[group] = {
        
        From 8a15ef42637da0f47447b860865123b67d76bd62 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Thu, 30 Apr 2020 17:53:42 +0900
        Subject: [PATCH 13/36] push for Korean translation on Publication and
         Community CC license
        
        ---
         src/data/ko.yml | 93 +++++++++++++++++++++++++------------------------
         1 file changed, 48 insertions(+), 45 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index ba7bf89476..5b42c691b6 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -473,12 +473,14 @@ community:
           in-times-conflict7: "사려깊고 친절한 태도로 소통합니다. "
           in-the-future-title: "미래에 우리는: "
           in-the-future1: "지금이 바로 미래입니다."
        -  notes-title: "Notes"
        -  notes1: "Please also see our "
        -  notes2: "p5.js Code of Conduct"
        -  notes3: ". The p5.js Community Statement is licensed under a "
        -  notes4: "Creative Commons license"
        -  notes5: ". Please feel free to share and remix with attribution."
        +
        +  notes-title: "유의사항"
        +  notes1: ""
        +  notes2: "p5.js 행동 강령"
        +  notes3: "을 참고하세요. p5.js 커뮤니티 성명서는 "
        +  notes4: "크리에이티브 커먼즈 라이선스(CC)"
        +  notes5: "에 따라 라이선스가 부여됩니다. 크레딧과 함께 자유로이 공유하고 응용할 수 있습니다."
        +
         
           contribute-title: "함께하기"
           contribute1: "우리 커뮤니티는 다양한 방법으로 도움을 줄 수 있는 열정가 분들을 항시 찾고 있습니다. "
        @@ -603,46 +605,47 @@ community:
         
         books:
           books-title: "출판물"
        -  book-1-title: "Getting Started with p5.js"
        -  book-1-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Illustrations by Taeyoon Choi."
        -  book-1-publisher: "Published October 2015, Maker Media. "
        -  book-1-pages: "246 pages. "
        -  book-1-type: "Paperback."
        -  book-1-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        -  book-1-order-a: "Order Print/Ebook from O'Reilly"
        -  book-1-order-b: "Order from Amazon"
        -  book-2-title: "Introduction to p5.js (Spanish Edition)"
        -  book-2-authors: "Lauren McCarthy, Casey Reas, and Ben Fry. Translated by Aarón Montoya-Moraga. Ilustraciones de Taeyoon Choi."
        -  book-2-publisher: "Published 2018, Processing Foundation, Inc. "
        -  book-2-pages: "246 pages. "
        -  book-2-type: "Soft cover."
        -  book-2-description: "Written by the lead p5.js developer and the founders of Processing, this book provides an introduction to the creative possibilities of today's Web, using JavaScript and HTML."
        -  book-2-order-a: "Order the PDF from The Processing Foundation Press"
        -  book-2-order-b: "Order the physical version from Amazon"
        -  book-3-title: "Generative Design"
        -  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        -  book-3-publisher: "Published October 30, 2018, Princeton Architectural Press; Reprint edition. "
        -  book-3-pages: "255 pages. "
        -  book-3-type: "Paperback."
        -  book-3-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        -  book-3-order-a: "Order from Princeton Architectural Press"
        -  book-3-order-b: "Order from Amazon"
        -  book-4-title: "Generative Gestaltung (German Edition)"
        +  book-1-title: "Getting Started with p5.js (p5.js 시작하기)"
        +  book-1-authors: "Lauren McCarthy, Casey Reas, Ben Fry 저. 삽화: 최태윤."
        +  book-1-publisher: "2015년 10월 Maker Media 출판. "
        +  book-1-pages: "246 페이지. "
        +  book-1-type: "페이퍼백."
        +  book-1-description: "p5.js의 리드 개발자와 프로세싱(Processing)의 창립자들이 저술한 이 책은, 자바스크립트(JavaScript)와 HTML을 통해 오늘날 웹아 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
        +  book-1-order-a: "O'Reilly에서 인쇄물/e북 주문하기"
        +  book-1-order-b: "아마존에서 주문하기"
        +  book-2-title: "Introduction to p5.js (스페인어 에디션)"
        +  book-2-authors: "Lauren McCarthy, Casey Reas, Ben Fry 저. <br> 번역: Aarón Montoya-Moraga. 삽화: 최태윤."
        +  book-2-publisher: "2018년 Processing Foundation, Inc. 출판. "
        +  book-2-pages: "246 페이지. "
        +  book-2-type: "소프트커버."
        +  book-2-description: "p5.js의 리드 개발자와 프로세싱(Processing)의 창립자들이 저술한 이 책은, 자바스크립트(JavaScript)와 HTML을 통해 오늘날 웹이 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
        +  book-2-order-a: "Processing Foundation Press에서 PDF 주문하기"
        +  book-2-order-b: "아마존에서 인쇄물 주문하기"
        +  book-3-title: "Generative Design(제너레이티브 디자인)"
        +  book-3-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni 저."
        +  book-3-publisher: "2018년 10월 30일 Princeton Architectural Press 출판; 별쇄본. "
        +  book-3-pages: "255 페이지. "
        +  book-3-type: "페이퍼백."
        +  book-3-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
        +  book-3-order-a: "Princeton Architectural Press에서 주문하기"
        +  book-3-order-b: "Amazon에서 주문하기"
        +  book-4-title: "Generative Gestaltung (제너레이티브 디자인 독일어 에디션)"
           book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
        -  book-4-publisher: "Published March 1, 2018, Schmidt Hermann Verlag. "
        -  book-4-pages: "256 pages. "
        -  book-4-type: "Hardcover."
        -  book-4-description: "By using simple languages such as JavaScript in p5.js, artists and makers can create everything from interactive typography and textiles to 3D-printed furniture to complex and elegant infographics."
        -  book-4-order-a: "Order from Verlag Hermann Schmidt"
        -  book-4-order-b: "Order from Amazon"
        -  book-5-title: "Learn JavaScript with p5.js"
        -  book-5-authors: "Engin Arslan."
        -  book-5-publisher: "Published 2018, Apress. "
        -  book-5-pages: "217 pages. "
        -  book-5-type: "Paperback."
        -  book-5-description: "Learn coding from scratch in a highly engaging and visual manner using the vastly popular JavaScript with the programming library p5.js. The skills you will acquire from this book are highly transferable to a myriad of industries and can be used towards building web applications, programmable robots, or generative art. "
        -  book-5-order-a: "Order from Apress"
        -  book-5-order-b: "Order from Amazon"
        +  book-4-publisher: "2018년 1월 Schmidt Hermann Verlag 출판. "
        +  book-4-pages: "256 페이지."
        +  book-4-type: "하드커버."
        +  book-4-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
        +  book-4-order-a: "Verlag Hermann Schmidt에서 주문하기"
        +  book-4-order-b: "Amazon에서 주문하기"
        +  book-5-title: "Learn JavaScript with p5.js <br> (p5.js로 자바스크립트 배우기)"
        +  book-5-authors: "Engin Arslan 저."
        +  book-5-publisher: "2018년 Apress 출판. "
        +  book-5-pages: "217 페이지."
        +  book-5-type: "페이퍼백."
        +  book-5-description: "널리 사용되는 자바스크립트(JavaScript)와 그 프로그래밍 라이브러리인 p5.js을 통해 아주 매력적이고 시각적인 방식으로 코딩에 입문하세요. 이 책에서 습득할 수 있는 기술은 수많은 산업계에서도 호환되는 것이며, 웹 어플리케이션, 로봇 프로그래밍, 제너레이티브 아트를 제작하는 데에도 쓰입니다."
        +  book-5-order-a: "Apress에서 주문하기"
        +  book-5-order-b: "Amazon에서 주문하기"
        +
         
         examples:
           Examples: "예제"
        
        From 48f46d65e93b3a71c70f23316fc80fac96f8ae9a Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Thu, 30 Apr 2020 17:58:58 +0900
        Subject: [PATCH 14/36] push for Korean translation on Publication and
         Community CC license
        
        ---
         src/data/ko.yml | 6 +++---
         1 file changed, 3 insertions(+), 3 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 5b42c691b6..762cb0b6ca 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -628,7 +628,7 @@ books:
           book-3-type: "페이퍼백."
           book-3-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
           book-3-order-a: "Princeton Architectural Press에서 주문하기"
        -  book-3-order-b: "Amazon에서 주문하기"
        +  book-3-order-b: "아마존에서 주문하기"
           book-4-title: "Generative Gestaltung (제너레이티브 디자인 독일어 에디션)"
           book-4-authors: "Benedikt Gross, Hartmut Bohnacker, Julia Laub and Claudius Lazzeroni."
           book-4-publisher: "2018년 1월 Schmidt Hermann Verlag 출판. "
        @@ -636,7 +636,7 @@ books:
           book-4-type: "하드커버."
           book-4-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
           book-4-order-a: "Verlag Hermann Schmidt에서 주문하기"
        -  book-4-order-b: "Amazon에서 주문하기"
        +  book-4-order-b: "아마존에서 주문하기"
           book-5-title: "Learn JavaScript with p5.js <br> (p5.js로 자바스크립트 배우기)"
           book-5-authors: "Engin Arslan 저."
           book-5-publisher: "2018년 Apress 출판. "
        @@ -644,7 +644,7 @@ books:
           book-5-type: "페이퍼백."
           book-5-description: "널리 사용되는 자바스크립트(JavaScript)와 그 프로그래밍 라이브러리인 p5.js을 통해 아주 매력적이고 시각적인 방식으로 코딩에 입문하세요. 이 책에서 습득할 수 있는 기술은 수많은 산업계에서도 호환되는 것이며, 웹 어플리케이션, 로봇 프로그래밍, 제너레이티브 아트를 제작하는 데에도 쓰입니다."
           book-5-order-a: "Apress에서 주문하기"
        -  book-5-order-b: "Amazon에서 주문하기"
        +  book-5-order-b: "아마존에서 주문하기"
         
         
         examples:
        
        From f6d5a649a4efd4468b7918b672614887b3be7c3d Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Tue, 5 May 2020 18:54:34 +0900
        Subject: [PATCH 15/36] korean translation updates
        
        ---
         .../pages/reference/assets/js/reference.js    | 20 +++++-----------
         .../reference/assets/js/reference.js.map      | 23 -------------------
         2 files changed, 6 insertions(+), 37 deletions(-)
        
        diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js
        index 5d8a62c1a3..ee120e52ea 100644
        --- a/src/templates/pages/reference/assets/js/reference.js
        +++ b/src/templates/pages/reference/assets/js/reference.js
        @@ -448,10 +448,10 @@ define('text',['module'], function (module) {
         });
         
         
        -define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\n<form>\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\n  <label class="sr-only" for="search_reference_field">Search reference</label>\n</form>\n\n';});
        +define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\r\n<form>\r\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\r\n  <label class="sr-only" for="search_reference_field">Search reference</label>\r\n</form>\r\n\r\n';});
         
         
        -define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\n\n  <strong><%=name%></strong>\n\n  <span class="small">\n    <% if (final) { %>\n    constant\n    <% } else if (itemtype) { %>\n    <%=itemtype%> \n    <% } %>\n\n    <% if (className) { %>\n    in <strong><%=className%></strong>\n    <% } %>\n\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\n    <% } %>\n  </span>\n\n</p>';});
        +define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\r\n\r\n  <strong><%=name%></strong>\r\n\r\n  <span class="small">\r\n    <% if (final) { %>\r\n    constant\r\n    <% } else if (itemtype) { %>\r\n    <%=itemtype%> \r\n    <% } %>\r\n\r\n    <% if (className) { %>\r\n    in <strong><%=className%></strong>\r\n    <% } %>\r\n\r\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\r\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\r\n    <% } %>\r\n  </span>\r\n\r\n</p>';});
         
         /*!
          * typeahead.js 0.10.2
        @@ -2303,7 +2303,7 @@ define('searchView',[
         });
         
         
        -define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\n  <div class="reference-group clearfix main-ref-page">  \n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\n    <div class="reference-subgroups clearfix main-ref-page">  \n    <% _.each(group.subgroups, function(subgroup, ind) { %>\n      <div class="reference-subgroup">\n        <% if (subgroup.name !== \'0\') { %>\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\n        <% } %>\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\n        <% _.each(subgroup.items, function(item) { %>\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\n        <% }); %>\n        </ul>\n      </div>\n    <% }); %>\n    </div>\n  </div>\n<% }); %>\n';});
        +define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\r\n  <div class="reference-group clearfix main-ref-page">  \r\n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\r\n    <div class="reference-subgroups clearfix main-ref-page">  \r\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\r\n      <div class="reference-subgroup">\r\n        <% if (subgroup.name !== \'0\') { %>\r\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\r\n        <% } %>\r\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\r\n        <% _.each(subgroup.items, function(item) { %>\r\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\r\n        <% }); %>\r\n        </ul>\r\n      </div>\r\n    <% }); %>\r\n    </div>\r\n  </div>\r\n<% }); %>\r\n';});
         
         define('listView',[
           'App',
        @@ -2445,17 +2445,13 @@ define('listView',[
         });
         
         
        -define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\n\n<% if (item.example) { %>\n<div class="example">\n  <h3 id="reference-example">Examples</h3>\n\n  <div class="example-content" data-alt="<%= item.alt %>">\n    <% _.each(item.example, function(example, i){ %>\n      <%= example %>\n    <% }); %>\n  </div>\n</div>\n<% } %>\n\n<div class="description">\n    \n  <h3 id="reference-description">Description</h3>\n\n  <% if (item.deprecated) { %>\n    <p>\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n    </p>\n  <% } %>\n      \n\n  <span class=\'description-text\'><%= item.description %></span>\n\n  <% if (item.extends) { %>\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\n  <% } %>\n\n  <% if (item.module === \'p5.sound\') { %>\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\n    </p>\n  <% } %>\n\n  <% if (item.constRefs) { %>\n    <p>Used by:\n  <%\n      var refs = item.constRefs;\n      for (var i = 0; i < refs.length; i ++) {\n        var ref = refs[i];\n        var name = ref;\n        if (name.substr(0, 3) === \'p5.\') {\n          name = name.substr(3);\n        }\n  if (i !== 0) {\n          if (i == refs.length - 1) {\n            %> and <%\n          } else {\n            %>, <%\n          }\n        }\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\n      }\n  %>\n    </p>\n  <% } %>\n</div>\n\n<% if (isConstructor || !isClass) { %>\n\n<div>\n  <h3 id="reference-syntax">Syntax</h3>\n  <p>\n    <% syntaxes.forEach(function(syntax) { %>\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\n    <% }) %>\n  </p>\n</div>\n\n\n<% if (item.params) { %>\n  <div class="params">\n    <h3 id="reference-parameters">Parameters</h3>\n    <ul aria-labelledby=\'reference-parameters\'>\n    <% for (var i=0; i<item.params.length; i++) { %>\n      <% var p = item.params[i] %>\n      <li>\n        <div class=\'paramname\'><%=p.name%></div>\n        <% if (p.type) { %>\n          <div class=\'paramtype\'>\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\n          <% if (p.optional) { %> (Optional)<% } %>\n          </div>\n        <% } %>\n      </li>\n    <% } %>\n    </ul>\n  </div>\n<% } %>\n\n<% if (item.return && item.return.type) { %>\n  <div>\n    <h3 id="reference-returns">Returns</h3>\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\n  </div>\n<% } %>\n\n<% } %>\n';});
        +define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\r\n\r\n<% if (item.example) { %>\r\n<div class="example">\r\n  <h3 id="reference-example">Examples</h3>\r\n\r\n  <div class="example-content" data-alt="<%= item.alt %>">\r\n    <% _.each(item.example, function(example, i){ %>\r\n      <%= example %>\r\n    <% }); %>\r\n  </div>\r\n</div>\r\n<% } %>\r\n\r\n<div class="description">\r\n    \r\n  <h3 id="reference-description">Description</h3>\r\n\r\n  <% if (item.deprecated) { %>\r\n    <p>\r\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\r\n    </p>\r\n  <% } %>\r\n      \r\n\r\n  <span class=\'description-text\'><%= item.description %></span>\r\n\r\n  <% if (item.extends) { %>\r\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\r\n  <% } %>\r\n\r\n  <% if (item.module === \'p5.sound\') { %>\r\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\r\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\r\n    </p>\r\n  <% } %>\r\n\r\n  <% if (item.constRefs) { %>\r\n    <p>Used by:\r\n  <%\r\n      var refs = item.constRefs;\r\n      for (var i = 0; i < refs.length; i ++) {\r\n        var ref = refs[i];\r\n        var name = ref;\r\n        if (name.substr(0, 3) === \'p5.\') {\r\n          name = name.substr(3);\r\n        }\r\n  if (i !== 0) {\r\n          if (i == refs.length - 1) {\r\n            %> and <%\r\n          } else {\r\n            %>, <%\r\n          }\r\n        }\r\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\r\n      }\r\n  %>\r\n    </p>\r\n  <% } %>\r\n</div>\r\n\r\n<% if (isConstructor || !isClass) { %>\r\n\r\n<div>\r\n  <h3 id="reference-syntax">Syntax</h3>\r\n  <p>\r\n    <% syntaxes.forEach(function(syntax) { %>\r\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\r\n    <% }) %>\r\n  </p>\r\n</div>\r\n\r\n\r\n<% if (item.params) { %>\r\n  <div class="params">\r\n    <h3 id="reference-parameters">Parameters</h3>\r\n    <ul aria-labelledby=\'reference-parameters\'>\r\n    <% for (var i=0; i<item.params.length; i++) { %>\r\n      <% var p = item.params[i] %>\r\n      <li>\r\n        <div class=\'paramname\'><%=p.name%></div>\r\n        <% if (p.type) { %>\r\n          <div class=\'paramtype\'>\r\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\r\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\r\n          <% if (p.optional) { %> (Optional)<% } %>\r\n          </div>\r\n        <% } %>\r\n      </li>\r\n    <% } %>\r\n    </ul>\r\n  </div>\r\n<% } %>\r\n\r\n<% if (item.return && item.return.type) { %>\r\n  <div>\r\n    <h3 id="reference-returns">Returns</h3>\r\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\r\n  </div>\r\n<% } %>\r\n\r\n<% } %>\r\n';});
         
         
        -<<<<<<< HEAD
        -define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n<div class="constructor">\n  <%=constructor%>\n</div>\n<% } %>\n\n<% let fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n  <h3 id=\'reference-fields\'>Fields</h3>\n  <ul aria-labelledby=\'reference-fields\'>\n  <% _.each(fields, function(item) { %>\n    <li>\n      <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>\n      <div class=\'paramtype\'><%= item.description %></div>\n    </li>\n  <% }); %>\n  </ul>\n<% } %>\n\n<% let methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n  <h3 id=\'reference-methods\'>Methods</h3>\n  <ul aria-labelledby=\'reference-methods\'>\n    <% _.each(methods, function(item) { %>\n      <li>\n        <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></div>\n        <div class=\'paramtype\'><%= item.description %></div>\n      </li>\n    <% }); %>\n  </ul>\n<% } %>\n';});
        -=======
         define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% let fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h3 id=\'reference-fields\'>Fields</h3>\r\n  <ul aria-labelledby=\'reference-fields\'>\r\n  <% _.each(fields, function(item) { %>\r\n    <li>\r\n      <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>\r\n      <div class=\'paramtype\'><%= item.description %></div>\r\n    </li>\r\n  <% }); %>\r\n  </ul>\r\n<% } %>\r\n\r\n<% let methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h3 id=\'reference-methods\'>Methods</h3>\r\n  <ul aria-labelledby=\'reference-methods\'>\r\n    <% _.each(methods, function(item) { %>\r\n      <li>\r\n        <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></div>\r\n        <div class=\'paramtype\'><%= item.description %></div>\r\n      </li>\r\n    <% }); %>\r\n  </ul>\r\n<% } %>\r\n';});
        ->>>>>>> 9d7b3cc9fce50f6e6a71953acd05eea4b0ee0f21
         
         
        -define('text!tpl/itemEnd.html',[],function () { return '\n<br><br>\n\n<div>\n<% if (item.file && item.line) { %>\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\n<% } %>\n</div>\n\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\n<br><br>\n';});
        +define('text!tpl/itemEnd.html',[],function () { return '\r\n<br><br>\r\n\r\n<div>\r\n<% if (item.file && item.line) { %>\r\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\r\n<% } %>\r\n</div>\r\n\r\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\r\n<br><br>\r\n';});
         
         // Copyright (C) 2006 Google Inc.
         //
        @@ -4339,7 +4335,7 @@ define('itemView',[
         });
         
         
        -define('text!tpl/menu.html',[],function () { return '<div>\n  <br>\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\n</div>\n\n<div id=\'collection-list-categories\'>\n<h2 class="sr-only" id="categories">Categories</h2>\n<% var i=0; %>\n<% var max=Math.floor(groups.length/4); %>\n<% var rem=groups.length%4; %>\n\n<% _.each(groups, function(group){ %>\n  <% var m = rem > 0 ? 1 : 0 %>\n  <% if (i === 0) { %>\n    <ul aria-labelledby="categories">\n    <% } %>\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\n    <% if (i === (max+m-1)) { %>\n    </ul>\n  \t<% rem-- %>\n  \t<% i=0 %>\n  <% } else { %>\n  \t<% i++ %>\n  <% } %>\n<% }); %>\n</div>\n';});
        +define('text!tpl/menu.html',[],function () { return '<div>\r\n  <br>\r\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\r\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\r\n</div>\r\n\r\n<div id=\'collection-list-categories\'>\r\n<h2 class="sr-only" id="categories">Categories</h2>\r\n<% var i=0; %>\r\n<% var max=Math.floor(groups.length/4); %>\r\n<% var rem=groups.length%4; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% var m = rem > 0 ? 1 : 0 %>\r\n  <% if (i === 0) { %>\r\n    <ul aria-labelledby="categories">\r\n    <% } %>\r\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\r\n    <% if (i === (max+m-1)) { %>\r\n    </ul>\r\n  \t<% rem-- %>\r\n  \t<% i=0 %>\r\n  <% } else { %>\r\n  \t<% i++ %>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
         
         define('menuView',[
           'App',
        @@ -4408,11 +4404,7 @@ define('menuView',[
         });
         
         
        -<<<<<<< HEAD
        -define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\n\n<p><%= module.description %></p>\n\n<div id="library-page" class="reference-group clearfix">  \n\n<% var t = 0; col = 0; %>\n\n<% _.each(groups, function(group){ %>\n  <% if (t == 0) { %> \n    <div class="column_<%=col%>">\n  <% } %>\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\n    <% if (group.hash) { %> </a><br> <% } %>\n  <% } %>\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\n    <% t++; %>\n  <% }); %>\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\n    </div>\n  <% } %>\n<% }); %>\n</div>\n';});
        -=======
         define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a><br> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
        ->>>>>>> 9d7b3cc9fce50f6e6a71953acd05eea4b0ee0f21
         
         define(
           'libraryView',[
        diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map
        index 98c60902f7..92c49461da 100644
        --- a/src/templates/pages/reference/assets/js/reference.js.map
        +++ b/src/templates/pages/reference/assets/js/reference.js.map
        @@ -29,28 +29,6 @@
           "file": "reference.js",
           "sourcesContent": [
             "(function () {\n",
        -<<<<<<< HEAD
        -    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define('documented-method',[], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    module.exports = factory();\n  } else {\n    root.DocumentedMethod = factory();\n  }\n}(this, function () {\n  function extend(target, src) {\n    Object.keys(src).forEach(function(prop) {\n      target[prop] = src[prop];\n    });\n    return target;\n  }\n\n  function DocumentedMethod(classitem) {\n    extend(this, classitem);\n\n    if (this.overloads) {\n      // Make each overload inherit properties from their parent\n      // classitem.\n      this.overloads = this.overloads.map(function(overload) {\n        return extend(Object.create(this), overload);\n      }, this);\n\n      if (this.params) {\n        throw new Error('params for overloaded methods should be undefined');\n      }\n\n      this.params = this._getMergedParams();\n    }\n  }\n\n  DocumentedMethod.prototype = {\n    // Merge parameters across all overloaded versions of this item.\n    _getMergedParams: function() {\n      var paramNames = {};\n      var params = [];\n\n      this.overloads.forEach(function(overload) {\n        if (!overload.params) {\n          return;\n        }\n        overload.params.forEach(function(param) {\n          if (param.name in paramNames) {\n            return;\n          }\n          paramNames[param.name] = param;\n          params.push(param);\n        });\n      });\n\n      return params;\n    }\n  };\n\n  return DocumentedMethod;\n}));\n\n",
        -    "/**\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/requirejs/text for details\n */\n/*jslint regexp: true */\n/*global require, XMLHttpRequest, ActiveXObject,\n  define, window, process, Packages,\n  java, location, Components, FileUtils */\n\ndefine('text',['module'], function (module) {\n    'use strict';\n\n    var text, fs, Cc, Ci, xpcIsWindows,\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = {},\n        masterConfig = (module.config && module.config()) || {};\n\n    text = {\n        version: '2.0.10',\n\n        strip: function (content) {\n            //Strips <?xml ...?> declarations so that external SVG and XML\n            //documents can be added to a document without worry. Also, if the string\n            //is an HTML document, only the part inside the body tag is returned.\n            if (content) {\n                content = content.replace(xmlRegExp, \"\");\n                var matches = content.match(bodyRegExp);\n                if (matches) {\n                    content = matches[1];\n                }\n            } else {\n                content = \"\";\n            }\n            return content;\n        },\n\n        jsEscape: function (content) {\n            return content.replace(/(['\\\\])/g, '\\\\$1')\n                .replace(/[\\f]/g, \"\\\\f\")\n                .replace(/[\\b]/g, \"\\\\b\")\n                .replace(/[\\n]/g, \"\\\\n\")\n                .replace(/[\\t]/g, \"\\\\t\")\n                .replace(/[\\r]/g, \"\\\\r\")\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\n        },\n\n        createXhr: masterConfig.createXhr || function () {\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n            var xhr, i, progId;\n            if (typeof XMLHttpRequest !== \"undefined\") {\n                return new XMLHttpRequest();\n            } else if (typeof ActiveXObject !== \"undefined\") {\n                for (i = 0; i < 3; i += 1) {\n                    progId = progIds[i];\n                    try {\n                        xhr = new ActiveXObject(progId);\n                    } catch (e) {}\n\n                    if (xhr) {\n                        progIds = [progId];  // so faster next time\n                        break;\n                    }\n                }\n            }\n\n            return xhr;\n        },\n\n        /**\n         * Parses a resource name into its component parts. Resource names\n         * look like: module/name.ext!strip, where the !strip part is\n         * optional.\n         * @param {String} name the resource name\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n         * where strip is a boolean.\n         */\n        parseName: function (name) {\n            var modName, ext, temp,\n                strip = false,\n                index = name.indexOf(\".\"),\n                isRelative = name.indexOf('./') === 0 ||\n                             name.indexOf('../') === 0;\n\n            if (index !== -1 && (!isRelative || index > 1)) {\n                modName = name.substring(0, index);\n                ext = name.substring(index + 1, name.length);\n            } else {\n                modName = name;\n            }\n\n            temp = ext || modName;\n            index = temp.indexOf(\"!\");\n            if (index !== -1) {\n                //Pull off the strip arg.\n                strip = temp.substring(index + 1) === \"strip\";\n                temp = temp.substring(0, index);\n                if (ext) {\n                    ext = temp;\n                } else {\n                    modName = temp;\n                }\n            }\n\n            return {\n                moduleName: modName,\n                ext: ext,\n                strip: strip\n            };\n        },\n\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n        /**\n         * Is an URL on another domain. Only works for browser use, returns\n         * false in non-browser environments. Only used to know if an\n         * optimized .js version of a text resource should be loaded\n         * instead.\n         * @param {String} url\n         * @returns Boolean\n         */\n        useXhr: function (url, protocol, hostname, port) {\n            var uProtocol, uHostName, uPort,\n                match = text.xdRegExp.exec(url);\n            if (!match) {\n                return true;\n            }\n            uProtocol = match[2];\n            uHostName = match[3];\n\n            uHostName = uHostName.split(':');\n            uPort = uHostName[1];\n            uHostName = uHostName[0];\n\n            return (!uProtocol || uProtocol === protocol) &&\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\n                   ((!uPort && !uHostName) || uPort === port);\n        },\n\n        finishLoad: function (name, strip, content, onLoad) {\n            content = strip ? text.strip(content) : content;\n            if (masterConfig.isBuild) {\n                buildMap[name] = content;\n            }\n            onLoad(content);\n        },\n\n        load: function (name, req, onLoad, config) {\n            //Name has format: some.module.filext!strip\n            //The strip part is optional.\n            //if strip is present, then that means only get the string contents\n            //inside a body tag in an HTML string. For XML/SVG content it means\n            //removing the <?xml ...?> declarations so the content can be inserted\n            //into the current doc without problems.\n\n            // Do not bother with the work if a build and text will\n            // not be inlined.\n            if (config.isBuild && !config.inlineText) {\n                onLoad();\n                return;\n            }\n\n            masterConfig.isBuild = config.isBuild;\n\n            var parsed = text.parseName(name),\n                nonStripName = parsed.moduleName +\n                    (parsed.ext ? '.' + parsed.ext : ''),\n                url = req.toUrl(nonStripName),\n                useXhr = (masterConfig.useXhr) ||\n                         text.useXhr;\n\n            // Do not load if it is an empty: url\n            if (url.indexOf('empty:') === 0) {\n                onLoad();\n                return;\n            }\n\n            //Load the text. Use XHR if possible and in a browser.\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                text.get(url, function (content) {\n                    text.finishLoad(name, parsed.strip, content, onLoad);\n                }, function (err) {\n                    if (onLoad.error) {\n                        onLoad.error(err);\n                    }\n                });\n            } else {\n                //Need to fetch the resource across domains. Assume\n                //the resource has been optimized into a JS module. Fetch\n                //by the module name + extension, but do not include the\n                //!strip part to avoid file system issues.\n                req([nonStripName], function (content) {\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                    parsed.strip, content, onLoad);\n                });\n            }\n        },\n\n        write: function (pluginName, moduleName, write, config) {\n            if (buildMap.hasOwnProperty(moduleName)) {\n                var content = text.jsEscape(buildMap[moduleName]);\n                write.asModule(pluginName + \"!\" + moduleName,\n                               \"define(function () { return '\" +\n                                   content +\n                               \"';});\\n\");\n            }\n        },\n\n        writeFile: function (pluginName, moduleName, req, write, config) {\n            var parsed = text.parseName(moduleName),\n                extPart = parsed.ext ? '.' + parsed.ext : '',\n                nonStripName = parsed.moduleName + extPart,\n                //Use a '.js' file name so that it indicates it is a\n                //script that can be loaded across domains.\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\n\n            //Leverage own load() method to load plugin value, but only\n            //write out values that do not have the strip argument,\n            //to avoid any potential issues with ! in file names.\n            text.load(nonStripName, req, function (value) {\n                //Use own write() method to construct full module value.\n                //But need to create shell that translates writeFile's\n                //write() to the right interface.\n                var textWrite = function (contents) {\n                    return write(fileName, contents);\n                };\n                textWrite.asModule = function (moduleName, contents) {\n                    return write.asModule(moduleName, fileName, contents);\n                };\n\n                text.write(pluginName, nonStripName, textWrite, config);\n            }, config);\n        }\n    };\n\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\n            typeof process !== \"undefined\" &&\n            process.versions &&\n            !!process.versions.node &&\n            !process.versions['node-webkit'])) {\n        //Using special require.nodeRequire, something added by r.js.\n        fs = require.nodeRequire('fs');\n\n        text.get = function (url, callback, errback) {\n            try {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            } catch (e) {\n                errback(e);\n            }\n        };\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\n            text.createXhr())) {\n        text.get = function (url, callback, errback, headers) {\n            var xhr = text.createXhr(), header;\n            xhr.open('GET', url, true);\n\n            //Allow plugins direct access to xhr headers\n            if (headers) {\n                for (header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                    }\n                }\n            }\n\n            //Allow overrides specified in config\n            if (masterConfig.onXhr) {\n                masterConfig.onXhr(xhr, url);\n            }\n\n            xhr.onreadystatechange = function (evt) {\n                var status, err;\n                //Do not explicitly handle errors, those should be\n                //visible via console output in the browser.\n                if (xhr.readyState === 4) {\n                    status = xhr.status;\n                    if (status > 399 && status < 600) {\n                        //An http 4xx or 5xx error. Signal an error.\n                        err = new Error(url + ' HTTP status: ' + status);\n                        err.xhr = xhr;\n                        errback(err);\n                    } else {\n                        callback(xhr.responseText);\n                    }\n\n                    if (masterConfig.onXhrComplete) {\n                        masterConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            };\n            xhr.send(null);\n        };\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\n        //Why Java, why is this so awkward?\n        text.get = function (url, callback) {\n            var stringBuffer, line,\n                encoding = \"utf-8\",\n                file = new java.io.File(url),\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                content = '';\n            try {\n                stringBuffer = new java.lang.StringBuffer();\n                line = input.readLine();\n\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                // http://www.unicode.org/faq/utf_bom.html\n\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\n                    // Eat the BOM, since we've already found the encoding on this file,\n                    // and we plan to concatenating this buffer with others; the BOM should\n                    // only appear at the top of a file.\n                    line = line.substring(1);\n                }\n\n                if (line !== null) {\n                    stringBuffer.append(line);\n                }\n\n                while ((line = input.readLine()) !== null) {\n                    stringBuffer.append(lineSeparator);\n                    stringBuffer.append(line);\n                }\n                //Make sure we return a JavaScript string and not a Java string.\n                content = String(stringBuffer.toString()); //String\n            } finally {\n                input.close();\n            }\n            callback(content);\n        };\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\n            typeof Components !== 'undefined' && Components.classes &&\n            Components.interfaces)) {\n        //Avert your gaze!\n        Cc = Components.classes,\n        Ci = Components.interfaces;\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\n\n        text.get = function (url, callback) {\n            var inStream, convertStream, fileObj,\n                readData = {};\n\n            if (xpcIsWindows) {\n                url = url.replace(/\\//g, '\\\\');\n            }\n\n            fileObj = new FileUtils.File(url);\n\n            //XPCOM, you so crazy\n            try {\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\n                           .createInstance(Ci.nsIFileInputStream);\n                inStream.init(fileObj, 1, 0, false);\n\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\n                                .createInstance(Ci.nsIConverterInputStream);\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\n\n                convertStream.readString(inStream.available(), readData);\n                convertStream.close();\n                inStream.close();\n                callback(readData.value);\n            } catch (e) {\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\n            }\n        };\n    }\n    return text;\n});\n\n",
        -    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\n<form>\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\n</form>\\n\\n';});\n\n",
        -    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\n\\n  <strong><%=name%></strong>\\n\\n  <span class=\"small\">\\n    <% if (final) { %>\\n    constant\\n    <% } else if (itemtype) { %>\\n    <%=itemtype%> \\n    <% } %>\\n\\n    <% if (className) { %>\\n    in <strong><%=className%></strong>\\n    <% } %>\\n\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\n    <% } %>\\n  </span>\\n\\n</p>';});\n\n",
        -    "/*!\n * typeahead.js 0.10.2\n * https://github.com/twitter/typeahead.js\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\n */\ndefine('typeahead',[], function() {\n\n//(function($) {\n\n\n    var _ = {\n        isMsie: function() {\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\n        },\n        isBlankString: function(str) {\n            return !str || /^\\s*$/.test(str);\n        },\n        escapeRegExChars: function(str) {\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n        },\n        isString: function(obj) {\n            return typeof obj === \"string\";\n        },\n        isNumber: function(obj) {\n            return typeof obj === \"number\";\n        },\n        isArray: $.isArray,\n        isFunction: $.isFunction,\n        isObject: $.isPlainObject,\n        isUndefined: function(obj) {\n            return typeof obj === \"undefined\";\n        },\n        bind: $.proxy,\n        each: function(collection, cb) {\n            $.each(collection, reverseArgs);\n            function reverseArgs(index, value) {\n                return cb(value, index);\n            }\n        },\n        map: $.map,\n        filter: $.grep,\n        every: function(obj, test) {\n            var result = true;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (!(result = test.call(null, val, key, obj))) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        some: function(obj, test) {\n            var result = false;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (result = test.call(null, val, key, obj)) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        mixin: $.extend,\n        getUniqueId: function() {\n            var counter = 0;\n            return function() {\n                return counter++;\n            };\n        }(),\n        templatify: function templatify(obj) {\n            return $.isFunction(obj) ? obj : template;\n            function template() {\n                return String(obj);\n            }\n        },\n        defer: function(fn) {\n            setTimeout(fn, 0);\n        },\n        debounce: function(func, wait, immediate) {\n            var timeout, result;\n            return function() {\n                var context = this, args = arguments, later, callNow;\n                later = function() {\n                    timeout = null;\n                    if (!immediate) {\n                        result = func.apply(context, args);\n                    }\n                };\n                callNow = immediate && !timeout;\n                clearTimeout(timeout);\n                timeout = setTimeout(later, wait);\n                if (callNow) {\n                    result = func.apply(context, args);\n                }\n                return result;\n            };\n        },\n        throttle: function(func, wait) {\n            var context, args, timeout, result, previous, later;\n            previous = 0;\n            later = function() {\n                previous = new Date();\n                timeout = null;\n                result = func.apply(context, args);\n            };\n            return function() {\n                var now = new Date(), remaining = wait - (now - previous);\n                context = this;\n                args = arguments;\n                if (remaining <= 0) {\n                    clearTimeout(timeout);\n                    timeout = null;\n                    previous = now;\n                    result = func.apply(context, args);\n                } else if (!timeout) {\n                    timeout = setTimeout(later, remaining);\n                }\n                return result;\n            };\n        },\n        noop: function() {}\n    };\n    var VERSION = \"0.10.2\";\n    var tokenizers = function(root) {\n        return {\n            nonword: nonword,\n            whitespace: whitespace,\n            obj: {\n                nonword: getObjTokenizer(nonword),\n                whitespace: getObjTokenizer(whitespace)\n            }\n        };\n        function whitespace(s) {\n            return s.split(/\\s+/);\n        }\n        function nonword(s) {\n            return s.split(/\\W+/);\n        }\n        function getObjTokenizer(tokenizer) {\n            return function setKey(key) {\n                return function tokenize(o) {\n                    return tokenizer(o[key]);\n                };\n            };\n        }\n    }();\n    var LruCache = function() {\n        function LruCache(maxSize) {\n            this.maxSize = maxSize || 100;\n            this.size = 0;\n            this.hash = {};\n            this.list = new List();\n        }\n        _.mixin(LruCache.prototype, {\n            set: function set(key, val) {\n                var tailItem = this.list.tail, node;\n                if (this.size >= this.maxSize) {\n                    this.list.remove(tailItem);\n                    delete this.hash[tailItem.key];\n                }\n                if (node = this.hash[key]) {\n                    node.val = val;\n                    this.list.moveToFront(node);\n                } else {\n                    node = new Node(key, val);\n                    this.list.add(node);\n                    this.hash[key] = node;\n                    this.size++;\n                }\n            },\n            get: function get(key) {\n                var node = this.hash[key];\n                if (node) {\n                    this.list.moveToFront(node);\n                    return node.val;\n                }\n            }\n        });\n        function List() {\n            this.head = this.tail = null;\n        }\n        _.mixin(List.prototype, {\n            add: function add(node) {\n                if (this.head) {\n                    node.next = this.head;\n                    this.head.prev = node;\n                }\n                this.head = node;\n                this.tail = this.tail || node;\n            },\n            remove: function remove(node) {\n                node.prev ? node.prev.next = node.next : this.head = node.next;\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\n            },\n            moveToFront: function(node) {\n                this.remove(node);\n                this.add(node);\n            }\n        });\n        function Node(key, val) {\n            this.key = key;\n            this.val = val;\n            this.prev = this.next = null;\n        }\n        return LruCache;\n    }();\n    var PersistentStorage = function() {\n        var ls, methods;\n        try {\n            ls = window.localStorage;\n            ls.setItem(\"~~~\", \"!\");\n            ls.removeItem(\"~~~\");\n        } catch (err) {\n            ls = null;\n        }\n        function PersistentStorage(namespace) {\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\n            this.ttlKey = \"__ttl__\";\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\n        }\n        if (ls && window.JSON) {\n            methods = {\n                _prefix: function(key) {\n                    return this.prefix + key;\n                },\n                _ttlKey: function(key) {\n                    return this._prefix(key) + this.ttlKey;\n                },\n                get: function(key) {\n                    if (this.isExpired(key)) {\n                        this.remove(key);\n                    }\n                    return decode(ls.getItem(this._prefix(key)));\n                },\n                set: function(key, val, ttl) {\n                    if (_.isNumber(ttl)) {\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\n                    } else {\n                        ls.removeItem(this._ttlKey(key));\n                    }\n                    return ls.setItem(this._prefix(key), encode(val));\n                },\n                remove: function(key) {\n                    ls.removeItem(this._ttlKey(key));\n                    ls.removeItem(this._prefix(key));\n                    return this;\n                },\n                clear: function() {\n                    var i, key, keys = [], len = ls.length;\n                    for (i = 0; i < len; i++) {\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\n                            keys.push(key.replace(this.keyMatcher, \"\"));\n                        }\n                    }\n                    for (i = keys.length; i--; ) {\n                        this.remove(keys[i]);\n                    }\n                    return this;\n                },\n                isExpired: function(key) {\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\n                }\n            };\n        } else {\n            methods = {\n                get: _.noop,\n                set: _.noop,\n                remove: _.noop,\n                clear: _.noop,\n                isExpired: _.noop\n            };\n        }\n        _.mixin(PersistentStorage.prototype, methods);\n        return PersistentStorage;\n        function now() {\n            return new Date().getTime();\n        }\n        function encode(val) {\n            return JSON.stringify(_.isUndefined(val) ? null : val);\n        }\n        function decode(val) {\n            return JSON.parse(val);\n        }\n    }();\n    var Transport = function() {\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\n        function Transport(o) {\n            o = o || {};\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\n        }\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\n            maxPendingRequests = num;\n        };\n        Transport.resetCache = function clearCache() {\n            requestCache = new LruCache(10);\n        };\n        _.mixin(Transport.prototype, {\n            _get: function(url, o, cb) {\n                var that = this, jqXhr;\n                if (jqXhr = pendingRequests[url]) {\n                    jqXhr.done(done).fail(fail);\n                } else if (pendingRequestsCount < maxPendingRequests) {\n                    pendingRequestsCount++;\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\n                } else {\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\n                }\n                function done(resp) {\n                    cb && cb(null, resp);\n                    requestCache.set(url, resp);\n                }\n                function fail() {\n                    cb && cb(true);\n                }\n                function always() {\n                    pendingRequestsCount--;\n                    delete pendingRequests[url];\n                    if (that.onDeckRequestArgs) {\n                        that._get.apply(that, that.onDeckRequestArgs);\n                        that.onDeckRequestArgs = null;\n                    }\n                }\n            },\n            get: function(url, o, cb) {\n                var resp;\n                if (_.isFunction(o)) {\n                    cb = o;\n                    o = {};\n                }\n                if (resp = requestCache.get(url)) {\n                    _.defer(function() {\n                        cb && cb(null, resp);\n                    });\n                } else {\n                    this._get(url, o, cb);\n                }\n                return !!resp;\n            }\n        });\n        return Transport;\n        function callbackToDeferred(fn) {\n            return function customSendWrapper(url, o) {\n                var deferred = $.Deferred();\n                fn(url, o, onSuccess, onError);\n                return deferred;\n                function onSuccess(resp) {\n                    _.defer(function() {\n                        deferred.resolve(resp);\n                    });\n                }\n                function onError(err) {\n                    _.defer(function() {\n                        deferred.reject(err);\n                    });\n                }\n            };\n        }\n    }();\n    var SearchIndex = function() {\n        function SearchIndex(o) {\n            o = o || {};\n            if (!o.datumTokenizer || !o.queryTokenizer) {\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\n            }\n            this.datumTokenizer = o.datumTokenizer;\n            this.queryTokenizer = o.queryTokenizer;\n            this.reset();\n        }\n        _.mixin(SearchIndex.prototype, {\n            bootstrap: function bootstrap(o) {\n                this.datums = o.datums;\n                this.trie = o.trie;\n            },\n            add: function(data) {\n                var that = this;\n                data = _.isArray(data) ? data : [ data ];\n                _.each(data, function(datum) {\n                    var id, tokens;\n                    id = that.datums.push(datum) - 1;\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\n                    _.each(tokens, function(token) {\n                        var node, chars, ch;\n                        node = that.trie;\n                        chars = token.split(\"\");\n                        while (ch = chars.shift()) {\n                            node = node.children[ch] || (node.children[ch] = newNode());\n                            node.ids.push(id);\n                        }\n                    });\n                });\n            },\n            get: function get(query) {\n                var that = this, tokens, matches;\n                tokens = normalizeTokens(this.queryTokenizer(query));\n                _.each(tokens, function(token) {\n                    var node, chars, ch, ids;\n                    if (matches && matches.length === 0) {\n                        return false;\n                    }\n                    node = that.trie;\n                    chars = token.split(\"\");\n                    while (node && (ch = chars.shift())) {\n                        node = node.children[ch];\n                    }\n                    if (node && chars.length === 0) {\n                        ids = node.ids.slice(0);\n                        matches = matches ? getIntersection(matches, ids) : ids;\n                    } else {\n                        matches = [];\n                        return false;\n                    }\n                });\n                return matches ? _.map(unique(matches), function(id) {\n                    return that.datums[id];\n                }) : [];\n            },\n            reset: function reset() {\n                this.datums = [];\n                this.trie = newNode();\n            },\n            serialize: function serialize() {\n                return {\n                    datums: this.datums,\n                    trie: this.trie\n                };\n            }\n        });\n        return SearchIndex;\n        function normalizeTokens(tokens) {\n            tokens = _.filter(tokens, function(token) {\n                return !!token;\n            });\n            tokens = _.map(tokens, function(token) {\n                return token.toLowerCase();\n            });\n            return tokens;\n        }\n        function newNode() {\n            return {\n                ids: [],\n                children: {}\n            };\n        }\n        function unique(array) {\n            var seen = {}, uniques = [];\n            for (var i = 0; i < array.length; i++) {\n                if (!seen[array[i]]) {\n                    seen[array[i]] = true;\n                    uniques.push(array[i]);\n                }\n            }\n            return uniques;\n        }\n        function getIntersection(arrayA, arrayB) {\n            var ai = 0, bi = 0, intersection = [];\n            arrayA = arrayA.sort(compare);\n            arrayB = arrayB.sort(compare);\n            while (ai < arrayA.length && bi < arrayB.length) {\n                if (arrayA[ai] < arrayB[bi]) {\n                    ai++;\n                } else if (arrayA[ai] > arrayB[bi]) {\n                    bi++;\n                } else {\n                    intersection.push(arrayA[ai]);\n                    ai++;\n                    bi++;\n                }\n            }\n            return intersection;\n            function compare(a, b) {\n                return a - b;\n            }\n        }\n    }();\n    var oParser = function() {\n        return {\n            local: getLocal,\n            prefetch: getPrefetch,\n            remote: getRemote\n        };\n        function getLocal(o) {\n            return o.local || null;\n        }\n        function getPrefetch(o) {\n            var prefetch, defaults;\n            defaults = {\n                url: null,\n                thumbprint: \"\",\n                ttl: 24 * 60 * 60 * 1e3,\n                filter: null,\n                ajax: {}\n            };\n            if (prefetch = o.prefetch || null) {\n                prefetch = _.isString(prefetch) ? {\n                    url: prefetch\n                } : prefetch;\n                prefetch = _.mixin(defaults, prefetch);\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\n            }\n            return prefetch;\n        }\n        function getRemote(o) {\n            var remote, defaults;\n            defaults = {\n                url: null,\n                wildcard: \"%QUERY\",\n                replace: null,\n                rateLimitBy: \"debounce\",\n                rateLimitWait: 300,\n                send: null,\n                filter: null,\n                ajax: {}\n            };\n            if (remote = o.remote || null) {\n                remote = _.isString(remote) ? {\n                    url: remote\n                } : remote;\n                remote = _.mixin(defaults, remote);\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\n                remote.ajax.type = remote.ajax.type || \"GET\";\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\n                delete remote.rateLimitBy;\n                delete remote.rateLimitWait;\n                !remote.url && $.error(\"remote requires url to be set\");\n            }\n            return remote;\n            function byDebounce(wait) {\n                return function(fn) {\n                    return _.debounce(fn, wait);\n                };\n            }\n            function byThrottle(wait) {\n                return function(fn) {\n                    return _.throttle(fn, wait);\n                };\n            }\n        }\n    }();\n    (function(root) {\n        var old, keys;\n        old = root.Bloodhound;\n        keys = {\n            data: \"data\",\n            protocol: \"protocol\",\n            thumbprint: \"thumbprint\"\n        };\n        root.Bloodhound = Bloodhound;\n        function Bloodhound(o) {\n            if (!o || !o.local && !o.prefetch && !o.remote) {\n                $.error(\"one of local, prefetch, or remote is required\");\n            }\n            this.limit = o.limit || 5;\n            this.sorter = getSorter(o.sorter);\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\n            this.local = oParser.local(o);\n            this.prefetch = oParser.prefetch(o);\n            this.remote = oParser.remote(o);\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\n            this.index = new SearchIndex({\n                datumTokenizer: o.datumTokenizer,\n                queryTokenizer: o.queryTokenizer\n            });\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\n        }\n        Bloodhound.noConflict = function noConflict() {\n            root.Bloodhound = old;\n            return Bloodhound;\n        };\n        Bloodhound.tokenizers = tokenizers;\n        _.mixin(Bloodhound.prototype, {\n            _loadPrefetch: function loadPrefetch(o) {\n                var that = this, serialized, deferred;\n                if (serialized = this._readFromStorage(o.thumbprint)) {\n                    this.index.bootstrap(serialized);\n                    deferred = $.Deferred().resolve();\n                } else {\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\n                }\n                return deferred;\n                function handlePrefetchResponse(resp) {\n                    that.clear();\n                    that.add(o.filter ? o.filter(resp) : resp);\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\n                }\n            },\n            _getFromRemote: function getFromRemote(query, cb) {\n                var that = this, url, uriEncodedQuery;\n                query = query || \"\";\n                uriEncodedQuery = encodeURIComponent(query);\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\n                function handleRemoteResponse(err, resp) {\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\n                }\n            },\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\n                if (this.storage) {\n                    this.storage.set(keys.data, data, ttl);\n                    this.storage.set(keys.protocol, location.protocol, ttl);\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\n                }\n            },\n            _readFromStorage: function readFromStorage(thumbprint) {\n                var stored = {}, isExpired;\n                if (this.storage) {\n                    stored.data = this.storage.get(keys.data);\n                    stored.protocol = this.storage.get(keys.protocol);\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\n                }\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\n                return stored.data && !isExpired ? stored.data : null;\n            },\n            _initialize: function initialize() {\n                var that = this, local = this.local, deferred;\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\n                local && deferred.done(addLocalToIndex);\n                this.transport = this.remote ? new Transport(this.remote) : null;\n                return this.initPromise = deferred.promise();\n                function addLocalToIndex() {\n                    that.add(_.isFunction(local) ? local() : local);\n                }\n            },\n            initialize: function initialize(force) {\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\n            },\n            add: function add(data) {\n                this.index.add(data);\n            },\n            get: function get(query, cb) {\n                var that = this, matches = [], cacheHit = false;\n                matches = this.index.get(query);\n                matches = this.sorter(matches).slice(0, this.limit);\n                if (matches.length < this.limit && this.transport) {\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\n                }\n                if (!cacheHit) {\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\n                }\n                function returnRemoteMatches(remoteMatches) {\n                    var matchesWithBackfill = matches.slice(0);\n                    _.each(remoteMatches, function(remoteMatch) {\n                        var isDuplicate;\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\n                            return that.dupDetector(remoteMatch, match);\n                        });\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\n                        return matchesWithBackfill.length < that.limit;\n                    });\n                    cb && cb(that.sorter(matchesWithBackfill));\n                }\n            },\n            clear: function clear() {\n                this.index.reset();\n            },\n            clearPrefetchCache: function clearPrefetchCache() {\n                this.storage && this.storage.clear();\n            },\n            clearRemoteCache: function clearRemoteCache() {\n                this.transport && Transport.resetCache();\n            },\n            ttAdapter: function ttAdapter() {\n                return _.bind(this.get, this);\n            }\n        });\n        return Bloodhound;\n        function getSorter(sortFn) {\n            return _.isFunction(sortFn) ? sort : noSort;\n            function sort(array) {\n                return array.sort(sortFn);\n            }\n            function noSort(array) {\n                return array;\n            }\n        }\n        function ignoreDuplicates() {\n            return false;\n        }\n    })(this);\n    var html = {\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\n        suggestions: '<span class=\"tt-suggestions\"></span>',\n        suggestion: '<div class=\"tt-suggestion\"></div>'\n    };\n    var css = {\n        wrapper: {\n            position: \"relative\",\n            display: \"inline-block\"\n        },\n        hint: {\n            position: \"absolute\",\n            top: \"0\",\n            left: \"0\",\n            borderColor: \"transparent\",\n            boxShadow: \"none\"\n        },\n        input: {\n            position: \"relative\",\n            verticalAlign: \"top\",\n            backgroundColor: \"transparent\"\n        },\n        inputWithNoHint: {\n            position: \"relative\",\n            verticalAlign: \"top\"\n        },\n        dropdown: {\n            position: \"absolute\",\n            top: \"100%\",\n            left: \"0\",\n            zIndex: \"100\",\n            display: \"none\"\n        },\n        suggestions: {\n            display: \"block\"\n        },\n        suggestion: {\n            whiteSpace: \"nowrap\",\n            cursor: \"pointer\"\n        },\n        suggestionChild: {\n            whiteSpace: \"normal\"\n        },\n        ltr: {\n            left: \"0\",\n            right: \"auto\"\n        },\n        rtl: {\n            left: \"auto\",\n            right: \" 0\"\n        }\n    };\n    if (_.isMsie()) {\n        _.mixin(css.input, {\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\n        });\n    }\n    if (_.isMsie() && _.isMsie() <= 7) {\n        _.mixin(css.input, {\n            marginTop: \"-1px\"\n        });\n    }\n    var EventBus = function() {\n        var namespace = \"typeahead:\";\n        function EventBus(o) {\n            if (!o || !o.el) {\n                $.error(\"EventBus initialized without el\");\n            }\n            this.$el = $(o.el);\n        }\n        _.mixin(EventBus.prototype, {\n            trigger: function(type) {\n                var args = [].slice.call(arguments, 1);\n                this.$el.trigger(namespace + type, args);\n            }\n        });\n        return EventBus;\n    }();\n    var EventEmitter = function() {\n        var splitter = /\\s+/, nextTick = getNextTick();\n        return {\n            onSync: onSync,\n            onAsync: onAsync,\n            off: off,\n            trigger: trigger\n        };\n        function on(method, types, cb, context) {\n            var type;\n            if (!cb) {\n                return this;\n            }\n            types = types.split(splitter);\n            cb = context ? bindContext(cb, context) : cb;\n            this._callbacks = this._callbacks || {};\n            while (type = types.shift()) {\n                this._callbacks[type] = this._callbacks[type] || {\n                    sync: [],\n                    async: []\n                };\n                this._callbacks[type][method].push(cb);\n            }\n            return this;\n        }\n        function onAsync(types, cb, context) {\n            return on.call(this, \"async\", types, cb, context);\n        }\n        function onSync(types, cb, context) {\n            return on.call(this, \"sync\", types, cb, context);\n        }\n        function off(types) {\n            var type;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            while (type = types.shift()) {\n                delete this._callbacks[type];\n            }\n            return this;\n        }\n        function trigger(types) {\n            var type, callbacks, args, syncFlush, asyncFlush;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            args = [].slice.call(arguments, 1);\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\n                syncFlush() && nextTick(asyncFlush);\n            }\n            return this;\n        }\n        function getFlush(callbacks, context, args) {\n            return flush;\n            function flush() {\n                var cancelled;\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\n                    cancelled = callbacks[i].apply(context, args) === false;\n                }\n                return !cancelled;\n            }\n        }\n        function getNextTick() {\n            var nextTickFn;\n            if (window.setImmediate) {\n                nextTickFn = function nextTickSetImmediate(fn) {\n                    setImmediate(function() {\n                        fn();\n                    });\n                };\n            } else {\n                nextTickFn = function nextTickSetTimeout(fn) {\n                    setTimeout(function() {\n                        fn();\n                    }, 0);\n                };\n            }\n            return nextTickFn;\n        }\n        function bindContext(fn, context) {\n            return fn.bind ? fn.bind(context) : function() {\n                fn.apply(context, [].slice.call(arguments, 0));\n            };\n        }\n    }();\n    var highlight = function(doc) {\n        var defaults = {\n            node: null,\n            pattern: null,\n            tagName: \"strong\",\n            className: null,\n            wordsOnly: false,\n            caseSensitive: false\n        };\n        return function hightlight(o) {\n            var regex;\n            o = _.mixin({}, defaults, o);\n            if (!o.node || !o.pattern) {\n                return;\n            }\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\n            traverse(o.node, hightlightTextNode);\n            function hightlightTextNode(textNode) {\n                var match, patternNode;\n                if (match = regex.exec(textNode.data)) {\n                    wrapperNode = doc.createElement(o.tagName);\n                    o.className && (wrapperNode.className = o.className);\n                    patternNode = textNode.splitText(match.index);\n                    patternNode.splitText(match[0].length);\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\n                }\n                return !!match;\n            }\n            function traverse(el, hightlightTextNode) {\n                var childNode, TEXT_NODE_TYPE = 3;\n                for (var i = 0; i < el.childNodes.length; i++) {\n                    childNode = el.childNodes[i];\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\n                        i += hightlightTextNode(childNode) ? 1 : 0;\n                    } else {\n                        traverse(childNode, hightlightTextNode);\n                    }\n                }\n            }\n        };\n        function getRegex(patterns, caseSensitive, wordsOnly) {\n            var escapedPatterns = [], regexStr;\n            for (var i = 0; i < patterns.length; i++) {\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\n            }\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\n        }\n    }(window.document);\n    var Input = function() {\n        var specialKeyCodeMap;\n        specialKeyCodeMap = {\n            9: \"tab\",\n            27: \"esc\",\n            37: \"left\",\n            39: \"right\",\n            13: \"enter\",\n            38: \"up\",\n            40: \"down\"\n        };\n        function Input(o) {\n            var that = this, onBlur, onFocus, onKeydown, onInput;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"input is missing\");\n            }\n            onBlur = _.bind(this._onBlur, this);\n            onFocus = _.bind(this._onFocus, this);\n            onKeydown = _.bind(this._onKeydown, this);\n            onInput = _.bind(this._onInput, this);\n            this.$hint = $(o.hint);\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\n            if (this.$hint.length === 0) {\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\n            }\n            if (!_.isMsie()) {\n                this.$input.on(\"input.tt\", onInput);\n            } else {\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\n                        return;\n                    }\n                    _.defer(_.bind(that._onInput, that, $e));\n                });\n            }\n            this.query = this.$input.val();\n            this.$overflowHelper = buildOverflowHelper(this.$input);\n        }\n        Input.normalizeQuery = function(str) {\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\n        };\n        _.mixin(Input.prototype, EventEmitter, {\n            _onBlur: function onBlur() {\n                this.resetInputValue();\n                this.trigger(\"blurred\");\n            },\n            _onFocus: function onFocus() {\n                this.trigger(\"focused\");\n            },\n            _onKeydown: function onKeydown($e) {\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\n                this._managePreventDefault(keyName, $e);\n                if (keyName && this._shouldTrigger(keyName, $e)) {\n                    this.trigger(keyName + \"Keyed\", $e);\n                }\n            },\n            _onInput: function onInput() {\n                this._checkInputValue();\n            },\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\n                var preventDefault, hintValue, inputValue;\n                switch (keyName) {\n                  case \"tab\":\n                    hintValue = this.getHint();\n                    inputValue = this.getInputValue();\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\n                    break;\n\n                  case \"up\":\n                  case \"down\":\n                    preventDefault = !withModifier($e);\n                    break;\n\n                  default:\n                    preventDefault = false;\n                }\n                preventDefault && $e.preventDefault();\n            },\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\n                var trigger;\n                switch (keyName) {\n                  case \"tab\":\n                    trigger = !withModifier($e);\n                    break;\n\n                  default:\n                    trigger = true;\n                }\n                return trigger;\n            },\n            _checkInputValue: function checkInputValue() {\n                var inputValue, areEquivalent, hasDifferentWhitespace;\n                inputValue = this.getInputValue();\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\n                if (!areEquivalent) {\n                    this.trigger(\"queryChanged\", this.query = inputValue);\n                } else if (hasDifferentWhitespace) {\n                    this.trigger(\"whitespaceChanged\", this.query);\n                }\n            },\n            focus: function focus() {\n                this.$input.focus();\n            },\n            blur: function blur() {\n                this.$input.blur();\n            },\n            getQuery: function getQuery() {\n                return this.query;\n            },\n            setQuery: function setQuery(query) {\n                this.query = query;\n            },\n            getInputValue: function getInputValue() {\n                return this.$input.val();\n            },\n            setInputValue: function setInputValue(value, silent) {\n                this.$input.val(value);\n                silent ? this.clearHint() : this._checkInputValue();\n            },\n            resetInputValue: function resetInputValue() {\n                this.setInputValue(this.query, true);\n            },\n            getHint: function getHint() {\n                return this.$hint.val();\n            },\n            setHint: function setHint(value) {\n                this.$hint.val(value);\n            },\n            clearHint: function clearHint() {\n                this.setHint(\"\");\n            },\n            clearHintIfInvalid: function clearHintIfInvalid() {\n                var val, hint, valIsPrefixOfHint, isValid;\n                val = this.getInputValue();\n                hint = this.getHint();\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\n                !isValid && this.clearHint();\n            },\n            getLanguageDirection: function getLanguageDirection() {\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\n            },\n            hasOverflow: function hasOverflow() {\n                var constraint = this.$input.width() - 2;\n                this.$overflowHelper.text(this.getInputValue());\n                return this.$overflowHelper.width() >= constraint;\n            },\n            isCursorAtEnd: function() {\n                var valueLength, selectionStart, range;\n                valueLength = this.$input.val().length;\n                selectionStart = this.$input[0].selectionStart;\n                if (_.isNumber(selectionStart)) {\n                    return selectionStart === valueLength;\n                } else if (document.selection) {\n                    range = document.selection.createRange();\n                    range.moveStart(\"character\", -valueLength);\n                    return valueLength === range.text.length;\n                }\n                return true;\n            },\n            destroy: function destroy() {\n                this.$hint.off(\".tt\");\n                this.$input.off(\".tt\");\n                this.$hint = this.$input = this.$overflowHelper = null;\n            }\n        });\n        return Input;\n        function buildOverflowHelper($input) {\n            return $('<pre aria-hidden=\"true\"></pre>').css({\n                position: \"absolute\",\n                visibility: \"hidden\",\n                whiteSpace: \"pre\",\n                fontFamily: $input.css(\"font-family\"),\n                fontSize: $input.css(\"font-size\"),\n                fontStyle: $input.css(\"font-style\"),\n                fontVariant: $input.css(\"font-variant\"),\n                fontWeight: $input.css(\"font-weight\"),\n                wordSpacing: $input.css(\"word-spacing\"),\n                letterSpacing: $input.css(\"letter-spacing\"),\n                textIndent: $input.css(\"text-indent\"),\n                textRendering: $input.css(\"text-rendering\"),\n                textTransform: $input.css(\"text-transform\")\n            }).insertAfter($input);\n        }\n        function areQueriesEquivalent(a, b) {\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\n        }\n        function withModifier($e) {\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\n        }\n    }();\n    var Dataset = function() {\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\n        function Dataset(o) {\n            o = o || {};\n            o.templates = o.templates || {};\n            if (!o.source) {\n                $.error(\"missing source\");\n            }\n            if (o.name && !isValidName(o.name)) {\n                $.error(\"invalid dataset name: \" + o.name);\n            }\n            this.query = null;\n            this.highlight = !!o.highlight;\n            this.name = o.name || _.getUniqueId();\n            this.source = o.source;\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\n            this.templates = getTemplates(o.templates, this.displayFn);\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\n        }\n        Dataset.extractDatasetName = function extractDatasetName(el) {\n            return $(el).data(datasetKey);\n        };\n        Dataset.extractValue = function extractDatum(el) {\n            return $(el).data(valueKey);\n        };\n        Dataset.extractDatum = function extractDatum(el) {\n            return $(el).data(datumKey);\n        };\n        _.mixin(Dataset.prototype, EventEmitter, {\n            _render: function render(query, suggestions) {\n                if (!this.$el) {\n                    return;\n                }\n                var that = this, hasSuggestions;\n                this.$el.empty();\n                hasSuggestions = suggestions && suggestions.length;\n                if (!hasSuggestions && this.templates.empty) {\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                } else if (hasSuggestions) {\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                }\n                this.trigger(\"rendered\");\n                function getEmptyHtml() {\n                    return that.templates.empty({\n                        query: query,\n                        isEmpty: true\n                    });\n                }\n                function getSuggestionsHtml() {\n                    var $suggestions, nodes;\n                    $suggestions = $(html.suggestions).css(css.suggestions);\n                    nodes = _.map(suggestions, getSuggestionNode);\n                    $suggestions.append.apply($suggestions, nodes);\n                    that.highlight && highlight({\n                        node: $suggestions[0],\n                        pattern: query\n                    });\n                    return $suggestions;\n                    function getSuggestionNode(suggestion) {\n                        var $el;\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\n                        $el.children().each(function() {\n                            $(this).css(css.suggestionChild);\n                        });\n                        return $el;\n                    }\n                }\n                function getHeaderHtml() {\n                    return that.templates.header({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n                function getFooterHtml() {\n                    return that.templates.footer({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n            },\n            getRoot: function getRoot() {\n                return this.$el;\n            },\n            update: function update(query) {\n                var that = this;\n                this.query = query;\n                this.canceled = false;\n                this.source(query, render);\n                function render(suggestions) {\n                    if (!that.canceled && query === that.query) {\n                        that._render(query, suggestions);\n                    }\n                }\n            },\n            cancel: function cancel() {\n                this.canceled = true;\n            },\n            clear: function clear() {\n                this.cancel();\n                this.$el.empty();\n                this.trigger(\"rendered\");\n            },\n            isEmpty: function isEmpty() {\n                return this.$el.is(\":empty\");\n            },\n            destroy: function destroy() {\n                this.$el = null;\n            }\n        });\n        return Dataset;\n        function getDisplayFn(display) {\n            display = display || \"value\";\n            return _.isFunction(display) ? display : displayFn;\n            function displayFn(obj) {\n                return obj[display];\n            }\n        }\n        function getTemplates(templates, displayFn) {\n            return {\n                empty: templates.empty && _.templatify(templates.empty),\n                header: templates.header && _.templatify(templates.header),\n                footer: templates.footer && _.templatify(templates.footer),\n                suggestion: templates.suggestion || suggestionTemplate\n            };\n            function suggestionTemplate(context) {\n                return \"<p>\" + displayFn(context) + \"</p>\";\n            }\n        }\n        function isValidName(str) {\n            return /^[_a-zA-Z0-9-]+$/.test(str);\n        }\n    }();\n    var Dropdown = function() {\n        function Dropdown(o) {\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\n            o = o || {};\n            if (!o.menu) {\n                $.error(\"menu is required\");\n            }\n            this.isOpen = false;\n            this.isEmpty = true;\n            this.datasets = _.map(o.datasets, initializeDataset);\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\n            _.each(this.datasets, function(dataset) {\n                that.$menu.append(dataset.getRoot());\n                dataset.onSync(\"rendered\", that._onRendered, that);\n            });\n        }\n        _.mixin(Dropdown.prototype, EventEmitter, {\n            _onSuggestionClick: function onSuggestionClick($e) {\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\n            },\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\n                this._removeCursor();\n                this._setCursor($($e.currentTarget), true);\n            },\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\n                this._removeCursor();\n            },\n            _onRendered: function onRendered() {\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\n                this.trigger(\"datasetRendered\");\n                function isDatasetEmpty(dataset) {\n                    return dataset.isEmpty();\n                }\n            },\n            _hide: function() {\n                this.$menu.hide();\n            },\n            _show: function() {\n                this.$menu.css(\"display\", \"block\");\n            },\n            _getSuggestions: function getSuggestions() {\n                return this.$menu.find(\".tt-suggestion\");\n            },\n            _getCursor: function getCursor() {\n                return this.$menu.find(\".tt-cursor\").first();\n            },\n            _setCursor: function setCursor($el, silent) {\n                $el.first().addClass(\"tt-cursor\");\n                !silent && this.trigger(\"cursorMoved\");\n            },\n            _removeCursor: function removeCursor() {\n                this._getCursor().removeClass(\"tt-cursor\");\n            },\n            _moveCursor: function moveCursor(increment) {\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\n                if (!this.isOpen) {\n                    return;\n                }\n                $oldCursor = this._getCursor();\n                $suggestions = this._getSuggestions();\n                this._removeCursor();\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\n                if (newCursorIndex === -1) {\n                    this.trigger(\"cursorRemoved\");\n                    return;\n                } else if (newCursorIndex < -1) {\n                    newCursorIndex = $suggestions.length - 1;\n                }\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\n                this._ensureVisible($newCursor);\n            },\n            _ensureVisible: function ensureVisible($el) {\n                var elTop, elBottom, menuScrollTop, menuHeight;\n                elTop = $el.position().top;\n                elBottom = elTop + $el.outerHeight(true);\n                menuScrollTop = this.$menu.scrollTop();\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\n                if (elTop < 0) {\n                    this.$menu.scrollTop(menuScrollTop + elTop);\n                } else if (menuHeight < elBottom) {\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\n                }\n            },\n            close: function close() {\n                if (this.isOpen) {\n                    this.isOpen = false;\n                    this._removeCursor();\n                    this._hide();\n                    this.trigger(\"closed\");\n                }\n            },\n            open: function open() {\n                if (!this.isOpen) {\n                    this.isOpen = true;\n                    !this.isEmpty && this._show();\n                    this.trigger(\"opened\");\n                }\n            },\n            setLanguageDirection: function setLanguageDirection(dir) {\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\n            },\n            moveCursorUp: function moveCursorUp() {\n                this._moveCursor(-1);\n            },\n            moveCursorDown: function moveCursorDown() {\n                this._moveCursor(+1);\n            },\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\n                var datum = null;\n                if ($el.length) {\n                    datum = {\n                        raw: Dataset.extractDatum($el),\n                        value: Dataset.extractValue($el),\n                        datasetName: Dataset.extractDatasetName($el)\n                    };\n                }\n                return datum;\n            },\n            getDatumForCursor: function getDatumForCursor() {\n                return this.getDatumForSuggestion(this._getCursor().first());\n            },\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\n                return this.getDatumForSuggestion(this._getSuggestions().first());\n            },\n            update: function update(query) {\n                _.each(this.datasets, updateDataset);\n                function updateDataset(dataset) {\n                    dataset.update(query);\n                }\n            },\n            empty: function empty() {\n                _.each(this.datasets, clearDataset);\n                this.isEmpty = true;\n                function clearDataset(dataset) {\n                    dataset.clear();\n                }\n            },\n            isVisible: function isVisible() {\n                return this.isOpen && !this.isEmpty;\n            },\n            destroy: function destroy() {\n                this.$menu.off(\".tt\");\n                this.$menu = null;\n                _.each(this.datasets, destroyDataset);\n                function destroyDataset(dataset) {\n                    dataset.destroy();\n                }\n            }\n        });\n        return Dropdown;\n        function initializeDataset(oDataset) {\n            return new Dataset(oDataset);\n        }\n    }();\n    var Typeahead = function() {\n        var attrsKey = \"ttAttrs\";\n        function Typeahead(o) {\n            var $menu, $input, $hint;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"missing input\");\n            }\n            this.isActivated = false;\n            this.autoselect = !!o.autoselect;\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\n            this.$node = buildDomStructure(o.input, o.withHint);\n            $menu = this.$node.find(\".tt-dropdown-menu\");\n            $input = this.$node.find(\".tt-input\");\n            $hint = this.$node.find(\".tt-hint\");\n            $input.on(\"blur.tt\", function($e) {\n                var active, isActive, hasActive;\n                active = document.activeElement;\n                isActive = $menu.is(active);\n                hasActive = $menu.has(active).length > 0;\n                if (_.isMsie() && (isActive || hasActive)) {\n                    $e.preventDefault();\n                    $e.stopImmediatePropagation();\n                    _.defer(function() {\n                        $input.focus();\n                    });\n                }\n            });\n            $menu.on(\"mousedown.tt\", function($e) {\n                $e.preventDefault();\n            });\n            this.eventBus = o.eventBus || new EventBus({\n                el: $input\n            });\n            this.dropdown = new Dropdown({\n                menu: $menu,\n                datasets: o.datasets\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\n            this.input = new Input({\n                input: $input,\n                hint: $hint\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\n            this._setLanguageDirection();\n        }\n        _.mixin(Typeahead.prototype, {\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\n                var datum;\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\n                    this._select(datum);\n                }\n            },\n            _onCursorMoved: function onCursorMoved() {\n                var datum = this.dropdown.getDatumForCursor();\n                this.input.setInputValue(datum.value, true);\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\n            },\n            _onCursorRemoved: function onCursorRemoved() {\n                this.input.resetInputValue();\n                this._updateHint();\n            },\n            _onDatasetRendered: function onDatasetRendered() {\n                this._updateHint();\n            },\n            _onOpened: function onOpened() {\n                this._updateHint();\n                this.eventBus.trigger(\"opened\");\n            },\n            _onClosed: function onClosed() {\n                this.input.clearHint();\n                this.eventBus.trigger(\"closed\");\n            },\n            _onFocused: function onFocused() {\n                this.isActivated = true;\n                this.dropdown.open();\n            },\n            _onBlurred: function onBlurred() {\n                this.isActivated = false;\n                this.dropdown.empty();\n                this.dropdown.close();\n                this.setVal(\"\", true); //LM\n            },\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\n                var cursorDatum, topSuggestionDatum;\n                cursorDatum = this.dropdown.getDatumForCursor();\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\n                if (cursorDatum) {\n                    this._select(cursorDatum);\n                    $e.preventDefault();\n                } else if (this.autoselect && topSuggestionDatum) {\n                    this._select(topSuggestionDatum);\n                    $e.preventDefault();\n                }\n            },\n            _onTabKeyed: function onTabKeyed(type, $e) {\n                var datum;\n                if (datum = this.dropdown.getDatumForCursor()) {\n                    this._select(datum);\n                    $e.preventDefault();\n                } else {\n                    this._autocomplete(true);\n                }\n            },\n            _onEscKeyed: function onEscKeyed() {\n                this.dropdown.close();\n                this.input.resetInputValue();\n            },\n            _onUpKeyed: function onUpKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\n                this.dropdown.open();\n            },\n            _onDownKeyed: function onDownKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\n                this.dropdown.open();\n            },\n            _onLeftKeyed: function onLeftKeyed() {\n                this.dir === \"rtl\" && this._autocomplete();\n            },\n            _onRightKeyed: function onRightKeyed() {\n                this.dir === \"ltr\" && this._autocomplete();\n            },\n            _onQueryChanged: function onQueryChanged(e, query) {\n                this.input.clearHintIfInvalid();\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\n                this.dropdown.open();\n                this._setLanguageDirection();\n            },\n            _onWhitespaceChanged: function onWhitespaceChanged() {\n                this._updateHint();\n                this.dropdown.open();\n            },\n            _setLanguageDirection: function setLanguageDirection() {\n                var dir;\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\n                    this.dir = dir;\n                    this.$node.css(\"direction\", dir);\n                    this.dropdown.setLanguageDirection(dir);\n                }\n            },\n            _updateHint: function updateHint() {\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\n                datum = this.dropdown.getDatumForTopSuggestion();\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\n                    val = this.input.getInputValue();\n                    query = Input.normalizeQuery(val);\n                    escapedQuery = _.escapeRegExChars(query);\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\n                    match = frontMatchRegEx.exec(datum.value);\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\n                } else {\n                    this.input.clearHint();\n                }\n            },\n            _autocomplete: function autocomplete(laxCursor) {\n                var hint, query, isCursorAtEnd, datum;\n                hint = this.input.getHint();\n                query = this.input.getQuery();\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\n                if (hint && query !== hint && isCursorAtEnd) {\n                    datum = this.dropdown.getDatumForTopSuggestion();\n                    datum && this.input.setInputValue(datum.value);\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\n                }\n            },\n            _select: function select(datum) {\n                this.input.setQuery(datum.value);\n                this.input.setInputValue(datum.value, true);\n                this._setLanguageDirection();\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\n                this.dropdown.close();\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\n            },\n            open: function open() {\n                this.dropdown.open();\n            },\n            close: function close() {\n                this.dropdown.close();\n            },\n            setVal: function setVal(val) {\n                if (this.isActivated) {\n                    this.input.setInputValue(val);\n                } else {\n                    this.input.setQuery(val);\n                    this.input.setInputValue(val, true);\n                }\n                this._setLanguageDirection();\n            },\n            getVal: function getVal() {\n                return this.input.getQuery();\n            },\n            destroy: function destroy() {\n                this.input.destroy();\n                this.dropdown.destroy();\n                destroyDomStructure(this.$node);\n                this.$node = null;\n            }\n        });\n        return Typeahead;\n        function buildDomStructure(input, withHint) {\n            var $input, $wrapper, $dropdown, $hint;\n            $input = $(input);\n            $wrapper = $(html.wrapper).css(css.wrapper);\n            $dropdown = $(html.dropdown).css(css.dropdown);\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\n                autocomplete: \"off\",\n                spellcheck: \"false\"\n            });\n            $input.data(attrsKey, {\n                dir: $input.attr(\"dir\"),\n                autocomplete: $input.attr(\"autocomplete\"),\n                spellcheck: $input.attr(\"spellcheck\"),\n                style: $input.attr(\"style\")\n            });\n            $input.addClass(\"tt-input\").attr({\n                autocomplete: \"off\",\n                spellcheck: false\n            }).css(withHint ? css.input : css.inputWithNoHint);\n            try {\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\n            } catch (e) {}\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\n        }\n        function getBackgroundStyles($el) {\n            return {\n                backgroundAttachment: $el.css(\"background-attachment\"),\n                backgroundClip: $el.css(\"background-clip\"),\n                backgroundColor: $el.css(\"background-color\"),\n                backgroundImage: $el.css(\"background-image\"),\n                backgroundOrigin: $el.css(\"background-origin\"),\n                backgroundPosition: $el.css(\"background-position\"),\n                backgroundRepeat: $el.css(\"background-repeat\"),\n                backgroundSize: $el.css(\"background-size\")\n            };\n        }\n        function destroyDomStructure($node) {\n            var $input = $node.find(\".tt-input\");\n            _.each($input.data(attrsKey), function(val, key) {\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\n            });\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\n            $node.remove();\n        }\n    }();\n    (function() {\n        var old, typeaheadKey, methods;\n        old = $.fn.typeahead;\n        typeaheadKey = \"ttTypeahead\";\n        methods = {\n            initialize: function initialize(o, datasets) {\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\n                o = o || {};\n                return this.each(attach);\n                function attach() {\n                    var $input = $(this), eventBus, typeahead;\n                    _.each(datasets, function(d) {\n                        d.highlight = !!o.highlight;\n                    });\n                    typeahead = new Typeahead({\n                        input: $input,\n                        eventBus: eventBus = new EventBus({\n                            el: $input\n                        }),\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\n                        minLength: o.minLength,\n                        autoselect: o.autoselect,\n                        datasets: datasets\n                    });\n                    $input.data(typeaheadKey, typeahead);\n                }\n            },\n            open: function open() {\n                return this.each(openTypeahead);\n                function openTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.open();\n                    }\n                }\n            },\n            close: function close() {\n                return this.each(closeTypeahead);\n                function closeTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.close();\n                    }\n                }\n            },\n            val: function val(newVal) {\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\n                function setVal() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.setVal(newVal);\n                    }\n                }\n                function getVal($input) {\n                    var typeahead, query;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        query = typeahead.getVal();\n                    }\n                    return query;\n                }\n            },\n            destroy: function destroy() {\n                return this.each(unattach);\n                function unattach() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.destroy();\n                        $input.removeData(typeaheadKey);\n                    }\n                }\n            }\n        };\n        $.fn.typeahead = function(method) {\n            if (methods[method]) {\n                return methods[method].apply(this, [].slice.call(arguments, 1));\n            } else {\n                return methods.initialize.apply(this, arguments);\n            }\n        };\n        $.fn.typeahead.noConflict = function noConflict() {\n            $.fn.typeahead = old;\n            return this;\n        };\n    })();\n    \n    \n    \n//})(window.jQuery);\n\n\n});\n",
        -    "define('searchView',[\n  'App',\n  // Templates\n  'text!tpl/search.html',\n  'text!tpl/search_suggestion.html',\n  // Tools\n  'typeahead'\n], function(App, searchTpl, suggestionTpl) {\n\n  var searchView = Backbone.View.extend({\n    el: '#search',\n    /**\n     * Init.\n     */\n    init: function() {\n      var tpl = _.template(searchTpl);\n      var className = 'form-control input-lg';\n      var placeholder = 'Search reference';\n      this.searchHtml = tpl({\n        'placeholder': placeholder,\n        'className': className\n      });\n      this.items = App.classes.concat(App.allItems);\n\n      return this;\n    },\n    /**\n     * Render input field with Typehead activated.\n     */\n    render: function() {\n      // Append the view to the dom\n      this.$el.append(this.searchHtml);\n\n      // Render Typeahead\n      var $searchInput = this.$el.find('input[type=text]');\n      this.typeaheadRender($searchInput);\n      this.typeaheadEvents($searchInput);\n\n      return this;\n    },\n    /**\n     * Apply Twitter Typeahead to the search input field.\n     * @param {jquery} $input\n     */\n    typeaheadRender: function($input) {\n      var self = this;\n      $input.typeahead(null, {\n        'displayKey': 'name',\n        'minLength': 2,\n        //'highlight': true,\n        'source': self.substringMatcher(this.items),\n        'templates': {\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\n          'suggestion': _.template(suggestionTpl)\n        }\n      });\n    },\n    /**\n     * Setup typeahead custom events (item selected).\n     */\n    typeaheadEvents: function($input) {\n      var self = this;\n      $input.on('typeahead:selected', function(e, item, datasetName) {\n        var selectedItem = self.items[item.idx];\n        select(selectedItem);\n      });\n      $input.on('keydown', function(e) {\n        if (e.which === 13) { // enter\n          var txt = $input.val();\n          var f = _.find(self.items, function(it) { return it.name == txt; });\n          if (f) {\n            select(f);\n          }\n        } else if (e.which === 27) {\n          $input.blur();\n        }\n      });\n\n      function select(selectedItem) {\n        var hash = App.router.getHash(selectedItem);//\n        App.router.navigate(hash, {'trigger': true});\n        $('#item').focus();\n      }\n    },\n    /**\n     * substringMatcher function for Typehead (search for strings in an array).\n     * @param {array} array\n     * @returns {Function}\n     */\n    substringMatcher: function(array) {\n      return function findMatches(query, callback) {\n        var matches = [], substrRegex, arrayLength = array.length;\n\n        // regex used to determine if a string contains the substring `query`\n        substrRegex = new RegExp(query, 'i');\n\n        // iterate through the pool of strings and for any string that\n        // contains the substring `query`, add it to the `matches` array\n        for (var i=0; i < arrayLength; i++) {\n          var item = array[i];\n          if (substrRegex.test(item.name)) {\n            // typeahead expects suggestions to be a js object\n            matches.push({\n              'itemtype': item.itemtype,\n              'name': item.name,\n              'className': item.class,\n              'is_constructor': !!item.is_constructor,\n              'final': item.final,\n              'idx': i\n            });\n          }\n        }\n\n        callback(matches);\n      };\n    }\n\n  });\n\n  return searchView;\n\n});\n\n",
        -    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\n  <div class=\"reference-group clearfix main-ref-page\">  \\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\n      <div class=\"reference-subgroup\">\\n        <% if (subgroup.name !== \\'0\\') { %>\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\n        <% } %>\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\n        <% _.each(subgroup.items, function(item) { %>\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\n        <% }); %>\\n        </ul>\\n      </div>\\n    <% }); %>\\n    </div>\\n  </div>\\n<% }); %>\\n';});\n\n",
        -    "define('listView',[\n  'App',\n  // Templates\n  'text!tpl/list.html'\n], function (App, listTpl) {\n  var striptags = function(html) {\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.textContent;\n  };\n\n  var listView = Backbone.View.extend({\n    el: '#list',\n    events: {},\n    /**\n     * Init.\n     */\n    init: function () {\n      this.listTpl = _.template(listTpl);\n\n      return this;\n    },\n    /**\n     * Render the list.\n     */\n    render: function (items, listCollection) {\n      if (items && listCollection) {\n        var self = this;\n\n        // Render items and group them by module\n        // module === group\n        this.groups = {};\n        _.each(items, function (item, i) {\n\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n\n            var group = item.module || '_';\n            var subgroup = item.submodule || '_';\n            if (group === subgroup) {\n              subgroup = '0';\n            }\n            var hash = App.router.getHash(item);\n\n            // fixes broken links for #/p5/> and #/p5/>=\n            item.hash = item.hash.replace('>', '&gt;');\n\n            // Create a group list\n            if (!self.groups[group]) {\n              self.groups[group] = {\n                name: group.replace('_', '&nbsp;'),\n                subgroups: {}\n              };\n            }\n\n            // Create a subgroup list\n            if (!self.groups[group].subgroups[subgroup]) {\n              self.groups[group].subgroups[subgroup] = {\n                name: subgroup.replace('_', '&nbsp;'),\n                items: []\n              };\n            }\n\n            // hide the un-interesting constants\n            if (group === 'Constants' && !item.example)\n              return;\n\n            if (item.class === 'p5') {\n\n              self.groups[group].subgroups[subgroup].items.push(item);\n\n            } else {\n\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\n                function(i){ return i.name == item.class; });\n\n              if (!found) {\n\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\n                var ind = hash.lastIndexOf('/');\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\n                self.groups[group].subgroups[subgroup].items.push({\n                  name: item.class,\n                  hash: hash\n                });\n              }\n\n            }\n          }\n        });\n\n        // Put the <li> items html into the list <ul>\n        var listHtml = self.listTpl({\n          'striptags': striptags,\n          'title': self.capitalizeFirst(listCollection),\n          'groups': self.groups,\n          'listCollection': listCollection\n        });\n\n        // Render the view\n        this.$el.html(listHtml);\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Show a list of items.\n     * @param {array} items Array of item objects.\n     * @returns {object} This view.\n     */\n    show: function (listGroup) {\n      if (App[listGroup]) {\n        this.render(App[listGroup], listGroup);\n      }\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function (str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n\n\n\n  });\n\n  return listView;\n\n});\n\n",
        -    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\n\\n<% if (item.example) { %>\\n<div class=\"example\">\\n  <h3 id=\"reference-example\">Examples</h3>\\n\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\n    <% _.each(item.example, function(example, i){ %>\\n      <%= example %>\\n    <% }); %>\\n  </div>\\n</div>\\n<% } %>\\n\\n<div class=\"description\">\\n    \\n  <h3 id=\"reference-description\">Description</h3>\\n\\n  <% if (item.deprecated) { %>\\n    <p>\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n    </p>\\n  <% } %>\\n      \\n\\n  <span class=\\'description-text\\'><%= item.description %></span>\\n\\n  <% if (item.extends) { %>\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\n  <% } %>\\n\\n  <% if (item.module === \\'p5.sound\\') { %>\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\n    </p>\\n  <% } %>\\n\\n  <% if (item.constRefs) { %>\\n    <p>Used by:\\n  <%\\n      var refs = item.constRefs;\\n      for (var i = 0; i < refs.length; i ++) {\\n        var ref = refs[i];\\n        var name = ref;\\n        if (name.substr(0, 3) === \\'p5.\\') {\\n          name = name.substr(3);\\n        }\\n  if (i !== 0) {\\n          if (i == refs.length - 1) {\\n            %> and <%\\n          } else {\\n            %>, <%\\n          }\\n        }\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\n      }\\n  %>\\n    </p>\\n  <% } %>\\n</div>\\n\\n<% if (isConstructor || !isClass) { %>\\n\\n<div>\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\n  <p>\\n    <% syntaxes.forEach(function(syntax) { %>\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\n    <% }) %>\\n  </p>\\n</div>\\n\\n\\n<% if (item.params) { %>\\n  <div class=\"params\">\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\n    <% for (var i=0; i<item.params.length; i++) { %>\\n      <% var p = item.params[i] %>\\n      <li>\\n        <div class=\\'paramname\\'><%=p.name%></div>\\n        <% if (p.type) { %>\\n          <div class=\\'paramtype\\'>\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\n          <% if (p.optional) { %> (Optional)<% } %>\\n          </div>\\n        <% } %>\\n      </li>\\n    <% } %>\\n    </ul>\\n  </div>\\n<% } %>\\n\\n<% if (item.return && item.return.type) { %>\\n  <div>\\n    <h3 id=\"reference-returns\">Returns</h3>\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\n  </div>\\n<% } %>\\n\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n<div class=\"constructor\">\\n  <%=constructor%>\\n</div>\\n<% } %>\\n\\n<% let fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n  <h3 id=\\'reference-fields\\'>Fields</h3>\\n  <ul aria-labelledby=\\'reference-fields\\'>\\n  <% _.each(fields, function(item) { %>\\n    <li>\\n      <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%></a></div>\\n      <div class=\\'paramtype\\'><%= item.description %></div>\\n    </li>\\n  <% }); %>\\n  </ul>\\n<% } %>\\n\\n<% let methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n  <h3 id=\\'reference-methods\\'>Methods</h3>\\n  <ul aria-labelledby=\\'reference-methods\\'>\\n    <% _.each(methods, function(item) { %>\\n      <li>\\n        <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></div>\\n        <div class=\\'paramtype\\'><%= item.description %></div>\\n      </li>\\n    <% }); %>\\n  </ul>\\n<% } %>\\n';});\n\n",
        -    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\n<br><br>\\n\\n<div>\\n<% if (item.file && item.line) { %>\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\n<% } %>\\n</div>\\n\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\n<br><br>\\n';});\n\n",
        -    "// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n * <p>\n * For a fairly comprehensive set of languages see the\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n * file that came with this source.  At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n * <p>\n * Usage: <ol>\n * <li> include this source file in an html page via\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\n * <li> define style rules.  See the example page for examples.\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n\ndefine(\"prettify\", function(){});\n\n",
        -    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function(App, itemTpl, classTpl, endTpl) {\n  'use strict';\n\n  var appVersion = App.project.version || 'master';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function() {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) {\n        syntax += 'new ';\n      } else if (cleanItem.static && cleanItem.class) {\n        syntax += cleanItem.class + '.';\n      }\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i = 0; i < cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) {\n              syntax += '[';\n            }\n            syntax += p.name;\n            if (p.optdefault) {\n              syntax += '=' + p.optdefault;\n            }\n            if (p.optional) {\n              syntax += ']';\n            }\n            if (i !== cleanItem.params.length - 1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function(item) {\n      if (item) {\n        var itemHtml = '';\n        var cleanItem = this.clean(item);\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\n        var collectionName = isClass\n            ? 'Constructor'\n            : this.capitalizeFirst(cleanItem.itemtype),\n          isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c) {\n            return c.name === cleanItem.name;\n          });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n        } else {\n          cleanItem.constRefs =\n            item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode(cleanItem.name);\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === 'method') {\n          App.pageView.appendToDocumentTitle(item.name + '()');\n        } else {\n          App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts)\n              .data('alt')\n              .split('\\n');\n\n            var canvases = $('.cnv_div');\n            for (var j = 0; j < alts.length; j++) {\n              if (j < canvases.length) {\n                $(canvases[j]).append(\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\n                );\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function(item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function(item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      $('#item').focus();\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function() {\n      this.$el.html(\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\n      );\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function(str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n});\n\n",
        -    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\n  <br>\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\n</div>\\n\\n<div id=\\'collection-list-categories\\'>\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\n<% var i=0; %>\\n<% var max=Math.floor(groups.length/4); %>\\n<% var rem=groups.length%4; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% var m = rem > 0 ? 1 : 0 %>\\n  <% if (i === 0) { %>\\n    <ul aria-labelledby=\"categories\">\\n    <% } %>\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\n    <% if (i === (max+m-1)) { %>\\n    </ul>\\n  \\t<% rem-- %>\\n  \\t<% i=0 %>\\n  <% } else { %>\\n  \\t<% i++ %>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define('menuView',[\n  'App',\n  'text!tpl/menu.html'\n], function(App, menuTpl) {\n\n  var menuView = Backbone.View.extend({\n    el: '#collection-list-nav',\n    /**\n     * Init.\n     * @returns {object} This view.\n     */\n    init: function() {\n      this.menuTpl = _.template(menuTpl);\n      return this;\n    },\n    /**\n     * Render.\n     * @returns {object} This view.\n     */\n    render: function() {\n\n      var groups = [];\n      _.each(App.modules, function (item, i) {\n        if (!item.is_submodule) {\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n            groups.push(item.name);\n          }\n        }\n        //}\n      });\n\n      // Sort groups by name A-Z\n      groups.sort();\n\n      var menuHtml = this.menuTpl({\n        'groups': groups\n      });\n\n      // Render the view\n      this.$el.html(menuHtml);\n    },\n\n    hide: function() {\n      this.$el.hide();\n    },\n\n    show: function() {\n      this.$el.show();\n    },\n\n    /**\n     * Update the menu.\n     * @param {string} el The name of the current route.\n     */\n    update: function(menuItem) {\n      //console.log(menuItem);\n      // this.$menuItems.removeClass('active');\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\n\n    }\n  });\n\n  return menuView;\n\n});\n\n",
        -    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\n\\n<p><%= module.description %></p>\\n\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\n\\n<% var t = 0; col = 0; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% if (t == 0) { %> \\n    <div class=\"column_<%=col%>\">\\n  <% } %>\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\n    <% if (group.hash) { %> </a><br> <% } %>\\n  <% } %>\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\n    <% t++; %>\\n  <% }); %>\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\n    </div>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        -    "define(\n  'libraryView',[\n    'App',\n    // Templates\n    'text!tpl/library.html'\n  ],\n  function(App, libraryTpl) {\n    var libraryView = Backbone.View.extend({\n      el: '#list',\n      events: {},\n      /**\n       * Init.\n       */\n      init: function() {\n        this.libraryTpl = _.template(libraryTpl);\n\n        return this;\n      },\n      /**\n       * Render the list.\n       */\n      render: function(m, listCollection) {\n        if (m && listCollection) {\n          var self = this;\n\n          // Render items and group them by module\n          // module === group\n          this.groups = {};\n          _.each(m.items, function(item, i) {\n            var module = item.module || '_';\n            var group;\n            // Override default group with a selected category\n            // TODO: Overwriting with the first category might not be the best choice\n            // We might also want to have links for categories\n            if (item.category && item.category[0]) {\n              group = item.category[0];\n              // Populate item.hash\n              App.router.getHash(item);\n\n              // Create a group list without link hash\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: undefined,\n                  items: []\n                };\n              }\n            } else {\n              group = item.class || '_';\n              var hash = App.router.getHash(item);\n\n              var ind = hash.lastIndexOf('/');\n              hash = hash.substring(0, ind);\n\n              // Create a group list\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: hash,\n                  items: []\n                };\n              }\n            }\n\n            self.groups[group].items.push(item);\n          });\n\n          // Sort groups by name A-Z\n          self.groups = _.sortBy(self.groups, this.sortByName);\n\n          // Put the <li> items html into the list <ul>\n          var libraryHtml = self.libraryTpl({\n            title: self.capitalizeFirst(listCollection),\n            module: m.module,\n            totalItems: m.items.length,\n            groups: self.groups\n          });\n\n          // Render the view\n          this.$el.html(libraryHtml);\n        }\n\n        return this;\n      },\n      /**\n       * Show a list of items.\n       * @param {array} items Array of item objects.\n       * @returns {object} This view.\n       */\n      show: function(listGroup) {\n        if (App[listGroup]) {\n          this.render(App[listGroup], listGroup);\n        }\n        App.pageView.hideContentViews();\n\n        this.$el.show();\n\n        return this;\n      },\n      /**\n       * Helper method to capitalize the first letter of a string\n       * @param {string} str\n       * @returns {string} Returns the string.\n       */\n      capitalizeFirst: function(str) {\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\n      },\n      /**\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\n       * @param {string} a\n       * @param {string} b\n       * @returns {Array} Returns an array with elements sorted from A to Z.\n       */\n      sortAZ: function(a, b) {\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\n      },\n\n      sortByName: function(a, b) {\n        if (a.name === 'p5') return -1;\n        else return 0;\n      }\n    });\n\n    return libraryView;\n  }\n);\n\n",
        -    "define('pageView',[\n  'App',\n\n  // Views\n  'searchView',\n  'listView',\n  'itemView',\n  'menuView',\n  'libraryView'\n], function(App, searchView, listView, itemView, menuView, libraryView) {\n\n  // Store the original title parts so we can substitue different endings.\n  var _originalDocumentTitle = window.document.title;\n\n  var pageView = Backbone.View.extend({\n    el: 'body',\n    /**\n     * Init.\n     */\n    init: function() {\n      App.$container = $('#container');\n      App.contentViews = [];\n\n      return this;\n    },\n    /**\n     * Render.\n     */\n    render: function() {\n\n      // Menu view\n      if (!App.menuView) {\n        App.menuView = new menuView();\n        App.menuView.init().render();\n      }\n\n      // Item view\n      if (!App.itemView) {\n        App.itemView = new itemView();\n        App.itemView.init().render();\n        // Add the item view to the views array\n        App.contentViews.push(App.itemView);\n      }\n\n      // List view\n      if (!App.listView) {\n        App.listView = new listView();\n        App.listView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.listView);\n      }\n\n      // Library view\n      if (!App.libraryView) {\n        App.libraryView = new libraryView();\n        App.libraryView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.libraryView);\n      }\n\n      // Search\n      if (!App.searchView) {\n        App.searchView = new searchView();\n        App.searchView.init().render();\n      }\n      return this;\n    },\n    /**\n     * Hide item and list views.\n     * @returns {object} This view.\n     */\n    hideContentViews: function() {\n      _.each(App.contentViews, function(view, i) {\n        view.$el.hide();\n      });\n\n      return this;\n    },\n    /**\n     * Append the supplied name to the first part of original document title.\n     * If no name is supplied, the title will reset to the original one.\n     */\n    appendToDocumentTitle: function(name){\n      if(name){\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\n        window.document.title = [firstTitlePart, name].join(\" | \");\n      } else {\n        window.document.title = _originalDocumentTitle;\n      }\n    }    \n  });\n\n  return pageView;\n\n});\n\n",
        -    "define('router',[\n  'App'\n], function(App) {\n\n  'use strict'; //\n\n  var Router = Backbone.Router.extend({\n\n    routes: {\n      '': 'list',\n      'p5': 'list',\n      'p5/': 'list',\n      'classes': 'list',\n      'search': 'search',\n      'libraries/:lib': 'library',\n      ':searchClass(/:searchItem)': 'get'\n    },\n    /**\n     * Whether the json API data was loaded.\n     */\n    _initialized: false,\n    /**\n     * Initialize the app: load json API data and create searchable arrays.\n     */\n    init: function(callback) {\n      var self = this;\n      require(['pageView'], function(pageView) {\n\n        // If already initialized, move away from here!\n        if (self._initialized) {\n          if (callback)\n            callback();\n          return;\n        }\n\n        // Update initialization state: must be done now to avoid recursive mess\n        self._initialized = true;\n\n        // Render views\n        if (!App.pageView) {\n          App.pageView = new pageView();\n          App.pageView.init().render();\n        }\n\n        // If a callback is set (a route has already been called), run it\n        // otherwise, show the default list\n        if (callback)\n          callback();\n        else\n          self.list();\n      });\n    },\n    /**\n     * Start route. Simply check if initialized.\n     */\n    start: function() {\n      this.init();\n    },\n    /**\n     * Show item details by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     */\n    get: function(searchClass, searchItem) {\n\n      // if looking for a library page, redirect\n      if (searchClass === 'p5.sound' && !searchItem) {\n        window.location.hash = '/libraries/'+searchClass;\n        return;\n      }\n\n      var self = this;\n      this.init(function() {\n        var item = self.getItem(searchClass, searchItem);\n\n        App.menuView.hide();\n\n        if (item) {\n          App.itemView.show(item);\n        } else {\n          //App.itemView.nothingFound();\n\n          self.list();\n        }\n\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Returns one item object by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     * @returns {object} The item found or undefined if nothing was found.\n     */\n    getItem: function(searchClass, searchItem) {\n      var classes = App.classes,\n              items = App.allItems,\n              classesCount = classes.length,\n              itemsCount = items.length,\n              className = searchClass ? searchClass.toLowerCase() : undefined,\n              itemName = searchItem ? searchItem : undefined,\n              found;\n\n      // Only search for a class, if itemName is undefined\n      if (className && !itemName) {\n        for (var i = 0; i < classesCount; i++) {\n          if (classes[i].name.toLowerCase() === className) {\n            found = classes[i];\n            _.each(found.items, function(i, idx) {\n              i.hash = App.router.getHash(i);\n            });\n            break;\n          }\n        }\n        // Search for a class item\n      } else if (className && itemName) {\n        // Search case sensitively\n        for (var i = 0; i < itemsCount; i++) {\n          if (items[i].class.toLowerCase() === className &&\n            items[i].name === itemName) {\n            found = items[i];\n            break;\n          }\n        }\n\n        // If no match was found, fallback to search case insensitively\n        if(!found){\n          for (var i = 0; i < itemsCount; i++) {\n            if(items[i].class.toLowerCase() === className &&\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\n              found = items[i];\n              break;\n            }\n          }\n        }\n      }\n\n      return found;\n    },\n    /**\n     * List items.\n     * @param {string} collection The name of the collection to list.\n     */\n    list: function(collection) {\n\n      collection = 'allItems';\n\n      // Make sure collection is valid\n      if (App.collections.indexOf(collection) < 0) {\n        return;\n      }\n\n      this.init(function() {\n        App.menuView.show(collection);\n        App.menuView.update(collection);\n        App.listView.show(collection);\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Display information for a library.\n     * @param {string} collection The name of the collection to list.\n     */\n    library: function(collection) {\n      this.init(function() {\n        App.menuView.hide();\n        App.libraryView.show(collection.substring(3)); //remove p5.\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Close all content views.\n     */\n    search: function() {\n      this.init(function() {\n        App.menuView.hide();\n        App.pageView.hideContentViews();\n      });\n    },\n\n    /**\n     * Create an hash/url for the item.\n     * @param {Object} item A class, method, property or event object.\n     * @returns {String} The hash string, including the '#'.\n     */\n     getHash: function(item) {\n\n       if (!item.hash) {\n\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\n\n         if (item.class) {\n           var clsFunc = '#/' + item.class + '.' + item.name;\n           var idx = clsFunc.lastIndexOf('.');\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\n         } else {\n          item.hash = '#/' + item.name;\n         }\n       }\n\n       return item.hash;\n    }\n  });\n\n  \n  function styleCodeLinks() {\n    var links = document.getElementsByTagName(\"a\");\n    for (var iLink = 0; iLink < links.length; iLink++) {\n      var link = links[iLink];\n      if (link.hash.startsWith('#/p5')) {\n        link.classList.add('code');\n      }\n    }\n  }\n\n\n  // Get the router\n  App.router = new Router();\n\n  // Start history\n  Backbone.history.start();\n\n  return App.router;\n\n});\n\n",
        -    "/**\n * Define global App.\n */\nvar App = window.App || {};\ndefine('App', [],function() {\n  return App;\n});\n\n/**\n * Load json API data and start the router.\n * @param {module} App\n * @param {module} router\n */\nrequire([\n  'App',\n  './documented-method'], function(App, DocumentedMethod) {\n\n  // Set collections\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];\n\n  // Get json API data\n  $.getJSON('data.min.json', function(data) {\n    App.data = data;\n    App.classes = [];\n    App.methods = [];\n    App.properties = [];\n    App.events = [];\n    App.allItems = [];\n    App.sound = { items: [] };\n    App.dom = { items: [] };\n    App.modules = [];\n    App.project = data.project;\n\n\n    var modules = data.modules;\n\n    // Get class items (methods, properties, events)\n    _.each(modules, function(m, idx, array) {\n      App.modules.push(m);\n      if (m.name == \"p5.sound\") {\n        App.sound.module = m;\n      }\n    });\n\n\n    var items = data.classitems;\n    var classes = data.classes;\n\n    // Get classes\n    _.each(classes, function(c, idx, array) {\n      if (!c.private) {\n        App.classes.push(c);\n      }\n    });\n\n\n    // Get class items (methods, properties, events)\n    _.each(items, function(el, idx, array) {\n      if (el.itemtype) {\n        if (el.itemtype === \"method\") {\n          el = new DocumentedMethod(el);\n          App.methods.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"property\") {\n          App.properties.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"event\") {\n          App.events.push(el);\n          App.allItems.push(el);\n        }\n\n        // libraries\n        if (el.module === \"p5.sound\") {\n          App.sound.items.push(el);\n        }\n      }\n    });\n\n    _.each(App.classes, function(c, idx) {\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\n    });\n\n    require(['router']);\n  });\n});\n\ndefine(\"main\", function(){});\n\n",
        -=======
             "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\r\n(function (root, factory) {\r\n  if (typeof define === 'function' && define.amd) {\r\n    define('documented-method',[], factory);\r\n  } else if (typeof module === 'object' && module.exports) {\r\n    module.exports = factory();\r\n  } else {\r\n    root.DocumentedMethod = factory();\r\n  }\r\n}(this, function () {\r\n  function extend(target, src) {\r\n    Object.keys(src).forEach(function(prop) {\r\n      target[prop] = src[prop];\r\n    });\r\n    return target;\r\n  }\r\n\r\n  function DocumentedMethod(classitem) {\r\n    extend(this, classitem);\r\n\r\n    if (this.overloads) {\r\n      // Make each overload inherit properties from their parent\r\n      // classitem.\r\n      this.overloads = this.overloads.map(function(overload) {\r\n        return extend(Object.create(this), overload);\r\n      }, this);\r\n\r\n      if (this.params) {\r\n        throw new Error('params for overloaded methods should be undefined');\r\n      }\r\n\r\n      this.params = this._getMergedParams();\r\n    }\r\n  }\r\n\r\n  DocumentedMethod.prototype = {\r\n    // Merge parameters across all overloaded versions of this item.\r\n    _getMergedParams: function() {\r\n      var paramNames = {};\r\n      var params = [];\r\n\r\n      this.overloads.forEach(function(overload) {\r\n        if (!overload.params) {\r\n          return;\r\n        }\r\n        overload.params.forEach(function(param) {\r\n          if (param.name in paramNames) {\r\n            return;\r\n          }\r\n          paramNames[param.name] = param;\r\n          params.push(param);\r\n        });\r\n      });\r\n\r\n      return params;\r\n    }\r\n  };\r\n\r\n  return DocumentedMethod;\r\n}));\r\n\n",
             "/**\r\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\r\n * Available via the MIT or new BSD license.\r\n * see: http://github.com/requirejs/text for details\r\n */\r\n/*jslint regexp: true */\r\n/*global require, XMLHttpRequest, ActiveXObject,\r\n  define, window, process, Packages,\r\n  java, location, Components, FileUtils */\r\n\r\ndefine('text',['module'], function (module) {\r\n    'use strict';\r\n\r\n    var text, fs, Cc, Ci, xpcIsWindows,\r\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\r\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\r\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\r\n        hasLocation = typeof location !== 'undefined' && location.href,\r\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\r\n        defaultHostName = hasLocation && location.hostname,\r\n        defaultPort = hasLocation && (location.port || undefined),\r\n        buildMap = {},\r\n        masterConfig = (module.config && module.config()) || {};\r\n\r\n    text = {\r\n        version: '2.0.10',\r\n\r\n        strip: function (content) {\r\n            //Strips <?xml ...?> declarations so that external SVG and XML\r\n            //documents can be added to a document without worry. Also, if the string\r\n            //is an HTML document, only the part inside the body tag is returned.\r\n            if (content) {\r\n                content = content.replace(xmlRegExp, \"\");\r\n                var matches = content.match(bodyRegExp);\r\n                if (matches) {\r\n                    content = matches[1];\r\n                }\r\n            } else {\r\n                content = \"\";\r\n            }\r\n            return content;\r\n        },\r\n\r\n        jsEscape: function (content) {\r\n            return content.replace(/(['\\\\])/g, '\\\\$1')\r\n                .replace(/[\\f]/g, \"\\\\f\")\r\n                .replace(/[\\b]/g, \"\\\\b\")\r\n                .replace(/[\\n]/g, \"\\\\n\")\r\n                .replace(/[\\t]/g, \"\\\\t\")\r\n                .replace(/[\\r]/g, \"\\\\r\")\r\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\r\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\r\n        },\r\n\r\n        createXhr: masterConfig.createXhr || function () {\r\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\r\n            var xhr, i, progId;\r\n            if (typeof XMLHttpRequest !== \"undefined\") {\r\n                return new XMLHttpRequest();\r\n            } else if (typeof ActiveXObject !== \"undefined\") {\r\n                for (i = 0; i < 3; i += 1) {\r\n                    progId = progIds[i];\r\n                    try {\r\n                        xhr = new ActiveXObject(progId);\r\n                    } catch (e) {}\r\n\r\n                    if (xhr) {\r\n                        progIds = [progId];  // so faster next time\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            return xhr;\r\n        },\r\n\r\n        /**\r\n         * Parses a resource name into its component parts. Resource names\r\n         * look like: module/name.ext!strip, where the !strip part is\r\n         * optional.\r\n         * @param {String} name the resource name\r\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\r\n         * where strip is a boolean.\r\n         */\r\n        parseName: function (name) {\r\n            var modName, ext, temp,\r\n                strip = false,\r\n                index = name.indexOf(\".\"),\r\n                isRelative = name.indexOf('./') === 0 ||\r\n                             name.indexOf('../') === 0;\r\n\r\n            if (index !== -1 && (!isRelative || index > 1)) {\r\n                modName = name.substring(0, index);\r\n                ext = name.substring(index + 1, name.length);\r\n            } else {\r\n                modName = name;\r\n            }\r\n\r\n            temp = ext || modName;\r\n            index = temp.indexOf(\"!\");\r\n            if (index !== -1) {\r\n                //Pull off the strip arg.\r\n                strip = temp.substring(index + 1) === \"strip\";\r\n                temp = temp.substring(0, index);\r\n                if (ext) {\r\n                    ext = temp;\r\n                } else {\r\n                    modName = temp;\r\n                }\r\n            }\r\n\r\n            return {\r\n                moduleName: modName,\r\n                ext: ext,\r\n                strip: strip\r\n            };\r\n        },\r\n\r\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\r\n\r\n        /**\r\n         * Is an URL on another domain. Only works for browser use, returns\r\n         * false in non-browser environments. Only used to know if an\r\n         * optimized .js version of a text resource should be loaded\r\n         * instead.\r\n         * @param {String} url\r\n         * @returns Boolean\r\n         */\r\n        useXhr: function (url, protocol, hostname, port) {\r\n            var uProtocol, uHostName, uPort,\r\n                match = text.xdRegExp.exec(url);\r\n            if (!match) {\r\n                return true;\r\n            }\r\n            uProtocol = match[2];\r\n            uHostName = match[3];\r\n\r\n            uHostName = uHostName.split(':');\r\n            uPort = uHostName[1];\r\n            uHostName = uHostName[0];\r\n\r\n            return (!uProtocol || uProtocol === protocol) &&\r\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\r\n                   ((!uPort && !uHostName) || uPort === port);\r\n        },\r\n\r\n        finishLoad: function (name, strip, content, onLoad) {\r\n            content = strip ? text.strip(content) : content;\r\n            if (masterConfig.isBuild) {\r\n                buildMap[name] = content;\r\n            }\r\n            onLoad(content);\r\n        },\r\n\r\n        load: function (name, req, onLoad, config) {\r\n            //Name has format: some.module.filext!strip\r\n            //The strip part is optional.\r\n            //if strip is present, then that means only get the string contents\r\n            //inside a body tag in an HTML string. For XML/SVG content it means\r\n            //removing the <?xml ...?> declarations so the content can be inserted\r\n            //into the current doc without problems.\r\n\r\n            // Do not bother with the work if a build and text will\r\n            // not be inlined.\r\n            if (config.isBuild && !config.inlineText) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            masterConfig.isBuild = config.isBuild;\r\n\r\n            var parsed = text.parseName(name),\r\n                nonStripName = parsed.moduleName +\r\n                    (parsed.ext ? '.' + parsed.ext : ''),\r\n                url = req.toUrl(nonStripName),\r\n                useXhr = (masterConfig.useXhr) ||\r\n                         text.useXhr;\r\n\r\n            // Do not load if it is an empty: url\r\n            if (url.indexOf('empty:') === 0) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            //Load the text. Use XHR if possible and in a browser.\r\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\r\n                text.get(url, function (content) {\r\n                    text.finishLoad(name, parsed.strip, content, onLoad);\r\n                }, function (err) {\r\n                    if (onLoad.error) {\r\n                        onLoad.error(err);\r\n                    }\r\n                });\r\n            } else {\r\n                //Need to fetch the resource across domains. Assume\r\n                //the resource has been optimized into a JS module. Fetch\r\n                //by the module name + extension, but do not include the\r\n                //!strip part to avoid file system issues.\r\n                req([nonStripName], function (content) {\r\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\r\n                                    parsed.strip, content, onLoad);\r\n                });\r\n            }\r\n        },\r\n\r\n        write: function (pluginName, moduleName, write, config) {\r\n            if (buildMap.hasOwnProperty(moduleName)) {\r\n                var content = text.jsEscape(buildMap[moduleName]);\r\n                write.asModule(pluginName + \"!\" + moduleName,\r\n                               \"define(function () { return '\" +\r\n                                   content +\r\n                               \"';});\\n\");\r\n            }\r\n        },\r\n\r\n        writeFile: function (pluginName, moduleName, req, write, config) {\r\n            var parsed = text.parseName(moduleName),\r\n                extPart = parsed.ext ? '.' + parsed.ext : '',\r\n                nonStripName = parsed.moduleName + extPart,\r\n                //Use a '.js' file name so that it indicates it is a\r\n                //script that can be loaded across domains.\r\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\r\n\r\n            //Leverage own load() method to load plugin value, but only\r\n            //write out values that do not have the strip argument,\r\n            //to avoid any potential issues with ! in file names.\r\n            text.load(nonStripName, req, function (value) {\r\n                //Use own write() method to construct full module value.\r\n                //But need to create shell that translates writeFile's\r\n                //write() to the right interface.\r\n                var textWrite = function (contents) {\r\n                    return write(fileName, contents);\r\n                };\r\n                textWrite.asModule = function (moduleName, contents) {\r\n                    return write.asModule(moduleName, fileName, contents);\r\n                };\r\n\r\n                text.write(pluginName, nonStripName, textWrite, config);\r\n            }, config);\r\n        }\r\n    };\r\n\r\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\r\n            typeof process !== \"undefined\" &&\r\n            process.versions &&\r\n            !!process.versions.node &&\r\n            !process.versions['node-webkit'])) {\r\n        //Using special require.nodeRequire, something added by r.js.\r\n        fs = require.nodeRequire('fs');\r\n\r\n        text.get = function (url, callback, errback) {\r\n            try {\r\n                var file = fs.readFileSync(url, 'utf8');\r\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\r\n                if (file.indexOf('\\uFEFF') === 0) {\r\n                    file = file.substring(1);\r\n                }\r\n                callback(file);\r\n            } catch (e) {\r\n                errback(e);\r\n            }\r\n        };\r\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\r\n            text.createXhr())) {\r\n        text.get = function (url, callback, errback, headers) {\r\n            var xhr = text.createXhr(), header;\r\n            xhr.open('GET', url, true);\r\n\r\n            //Allow plugins direct access to xhr headers\r\n            if (headers) {\r\n                for (header in headers) {\r\n                    if (headers.hasOwnProperty(header)) {\r\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Allow overrides specified in config\r\n            if (masterConfig.onXhr) {\r\n                masterConfig.onXhr(xhr, url);\r\n            }\r\n\r\n            xhr.onreadystatechange = function (evt) {\r\n                var status, err;\r\n                //Do not explicitly handle errors, those should be\r\n                //visible via console output in the browser.\r\n                if (xhr.readyState === 4) {\r\n                    status = xhr.status;\r\n                    if (status > 399 && status < 600) {\r\n                        //An http 4xx or 5xx error. Signal an error.\r\n                        err = new Error(url + ' HTTP status: ' + status);\r\n                        err.xhr = xhr;\r\n                        errback(err);\r\n                    } else {\r\n                        callback(xhr.responseText);\r\n                    }\r\n\r\n                    if (masterConfig.onXhrComplete) {\r\n                        masterConfig.onXhrComplete(xhr, url);\r\n                    }\r\n                }\r\n            };\r\n            xhr.send(null);\r\n        };\r\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\r\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\r\n        //Why Java, why is this so awkward?\r\n        text.get = function (url, callback) {\r\n            var stringBuffer, line,\r\n                encoding = \"utf-8\",\r\n                file = new java.io.File(url),\r\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\r\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\r\n                content = '';\r\n            try {\r\n                stringBuffer = new java.lang.StringBuffer();\r\n                line = input.readLine();\r\n\r\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\r\n                // http://www.unicode.org/faq/utf_bom.html\r\n\r\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\r\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\r\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\r\n                    // Eat the BOM, since we've already found the encoding on this file,\r\n                    // and we plan to concatenating this buffer with others; the BOM should\r\n                    // only appear at the top of a file.\r\n                    line = line.substring(1);\r\n                }\r\n\r\n                if (line !== null) {\r\n                    stringBuffer.append(line);\r\n                }\r\n\r\n                while ((line = input.readLine()) !== null) {\r\n                    stringBuffer.append(lineSeparator);\r\n                    stringBuffer.append(line);\r\n                }\r\n                //Make sure we return a JavaScript string and not a Java string.\r\n                content = String(stringBuffer.toString()); //String\r\n            } finally {\r\n                input.close();\r\n            }\r\n            callback(content);\r\n        };\r\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\r\n            typeof Components !== 'undefined' && Components.classes &&\r\n            Components.interfaces)) {\r\n        //Avert your gaze!\r\n        Cc = Components.classes,\r\n        Ci = Components.interfaces;\r\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\r\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\r\n\r\n        text.get = function (url, callback) {\r\n            var inStream, convertStream, fileObj,\r\n                readData = {};\r\n\r\n            if (xpcIsWindows) {\r\n                url = url.replace(/\\//g, '\\\\');\r\n            }\r\n\r\n            fileObj = new FileUtils.File(url);\r\n\r\n            //XPCOM, you so crazy\r\n            try {\r\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\r\n                           .createInstance(Ci.nsIFileInputStream);\r\n                inStream.init(fileObj, 1, 0, false);\r\n\r\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\r\n                                .createInstance(Ci.nsIConverterInputStream);\r\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\r\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\r\n\r\n                convertStream.readString(inStream.available(), readData);\r\n                convertStream.close();\r\n                inStream.close();\r\n                callback(readData.value);\r\n            } catch (e) {\r\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\r\n            }\r\n        };\r\n    }\r\n    return text;\r\n});\r\n\n",
             "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\r\\n<form>\\r\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\r\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\r\\n</form>\\r\\n\\r\\n';});\n\n",
        @@ -71,7 +49,6 @@
             "define('pageView',[\r\n  'App',\r\n\r\n  // Views\r\n  'searchView',\r\n  'listView',\r\n  'itemView',\r\n  'menuView',\r\n  'libraryView'\r\n], function(App, searchView, listView, itemView, menuView, libraryView) {\r\n\r\n  // Store the original title parts so we can substitue different endings.\r\n  var _originalDocumentTitle = window.document.title;\r\n\r\n  var pageView = Backbone.View.extend({\r\n    el: 'body',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      App.$container = $('#container');\r\n      App.contentViews = [];\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     */\r\n    render: function() {\r\n\r\n      // Menu view\r\n      if (!App.menuView) {\r\n        App.menuView = new menuView();\r\n        App.menuView.init().render();\r\n      }\r\n\r\n      // Item view\r\n      if (!App.itemView) {\r\n        App.itemView = new itemView();\r\n        App.itemView.init().render();\r\n        // Add the item view to the views array\r\n        App.contentViews.push(App.itemView);\r\n      }\r\n\r\n      // List view\r\n      if (!App.listView) {\r\n        App.listView = new listView();\r\n        App.listView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.listView);\r\n      }\r\n\r\n      // Library view\r\n      if (!App.libraryView) {\r\n        App.libraryView = new libraryView();\r\n        App.libraryView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.libraryView);\r\n      }\r\n\r\n      // Search\r\n      if (!App.searchView) {\r\n        App.searchView = new searchView();\r\n        App.searchView.init().render();\r\n      }\r\n      return this;\r\n    },\r\n    /**\r\n     * Hide item and list views.\r\n     * @returns {object} This view.\r\n     */\r\n    hideContentViews: function() {\r\n      _.each(App.contentViews, function(view, i) {\r\n        view.$el.hide();\r\n      });\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Append the supplied name to the first part of original document title.\r\n     * If no name is supplied, the title will reset to the original one.\r\n     */\r\n    appendToDocumentTitle: function(name){\r\n      if(name){\r\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\r\n        window.document.title = [firstTitlePart, name].join(\" | \");\r\n      } else {\r\n        window.document.title = _originalDocumentTitle;\r\n      }\r\n    }    \r\n  });\r\n\r\n  return pageView;\r\n\r\n});\r\n\n",
             "define('router',[\r\n  'App'\r\n], function(App) {\r\n\r\n  'use strict'; //\r\n\r\n  var Router = Backbone.Router.extend({\r\n\r\n    routes: {\r\n      '': 'list',\r\n      'p5': 'list',\r\n      'p5/': 'list',\r\n      'classes': 'list',\r\n      'search': 'search',\r\n      'libraries/:lib': 'library',\r\n      ':searchClass(/:searchItem)': 'get'\r\n    },\r\n    /**\r\n     * Whether the json API data was loaded.\r\n     */\r\n    _initialized: false,\r\n    /**\r\n     * Initialize the app: load json API data and create searchable arrays.\r\n     */\r\n    init: function(callback) {\r\n      var self = this;\r\n      require(['pageView'], function(pageView) {\r\n\r\n        // If already initialized, move away from here!\r\n        if (self._initialized) {\r\n          if (callback)\r\n            callback();\r\n          return;\r\n        }\r\n\r\n        // Update initialization state: must be done now to avoid recursive mess\r\n        self._initialized = true;\r\n\r\n        // Render views\r\n        if (!App.pageView) {\r\n          App.pageView = new pageView();\r\n          App.pageView.init().render();\r\n        }\r\n\r\n        // If a callback is set (a route has already been called), run it\r\n        // otherwise, show the default list\r\n        if (callback)\r\n          callback();\r\n        else\r\n          self.list();\r\n      });\r\n    },\r\n    /**\r\n     * Start route. Simply check if initialized.\r\n     */\r\n    start: function() {\r\n      this.init();\r\n    },\r\n    /**\r\n     * Show item details by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     */\r\n    get: function(searchClass, searchItem) {\r\n\r\n      // if looking for a library page, redirect\r\n      if (searchClass === 'p5.sound' && !searchItem) {\r\n        window.location.hash = '/libraries/'+searchClass;\r\n        return;\r\n      }\r\n\r\n      var self = this;\r\n      this.init(function() {\r\n        var item = self.getItem(searchClass, searchItem);\r\n\r\n        App.menuView.hide();\r\n\r\n        if (item) {\r\n          App.itemView.show(item);\r\n        } else {\r\n          //App.itemView.nothingFound();\r\n\r\n          self.list();\r\n        }\r\n\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Returns one item object by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     * @returns {object} The item found or undefined if nothing was found.\r\n     */\r\n    getItem: function(searchClass, searchItem) {\r\n      var classes = App.classes,\r\n              items = App.allItems,\r\n              classesCount = classes.length,\r\n              itemsCount = items.length,\r\n              className = searchClass ? searchClass.toLowerCase() : undefined,\r\n              itemName = searchItem ? searchItem : undefined,\r\n              found;\r\n\r\n      // Only search for a class, if itemName is undefined\r\n      if (className && !itemName) {\r\n        for (var i = 0; i < classesCount; i++) {\r\n          if (classes[i].name.toLowerCase() === className) {\r\n            found = classes[i];\r\n            _.each(found.items, function(i, idx) {\r\n              i.hash = App.router.getHash(i);\r\n            });\r\n            break;\r\n          }\r\n        }\r\n        // Search for a class item\r\n      } else if (className && itemName) {\r\n        // Search case sensitively\r\n        for (var i = 0; i < itemsCount; i++) {\r\n          if (items[i].class.toLowerCase() === className &&\r\n            items[i].name === itemName) {\r\n            found = items[i];\r\n            break;\r\n          }\r\n        }\r\n\r\n        // If no match was found, fallback to search case insensitively\r\n        if(!found){\r\n          for (var i = 0; i < itemsCount; i++) {\r\n            if(items[i].class.toLowerCase() === className &&\r\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\r\n              found = items[i];\r\n              break;\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      return found;\r\n    },\r\n    /**\r\n     * List items.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    list: function(collection) {\r\n\r\n      collection = 'allItems';\r\n\r\n      // Make sure collection is valid\r\n      if (App.collections.indexOf(collection) < 0) {\r\n        return;\r\n      }\r\n\r\n      this.init(function() {\r\n        App.menuView.show(collection);\r\n        App.menuView.update(collection);\r\n        App.listView.show(collection);\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Display information for a library.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    library: function(collection) {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.libraryView.show(collection.substring(3)); //remove p5.\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Close all content views.\r\n     */\r\n    search: function() {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.pageView.hideContentViews();\r\n      });\r\n    },\r\n\r\n    /**\r\n     * Create an hash/url for the item.\r\n     * @param {Object} item A class, method, property or event object.\r\n     * @returns {String} The hash string, including the '#'.\r\n     */\r\n     getHash: function(item) {\r\n\r\n       if (!item.hash) {\r\n\r\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\r\n\r\n         if (item.class) {\r\n           var clsFunc = '#/' + item.class + '.' + item.name;\r\n           var idx = clsFunc.lastIndexOf('.');\r\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\r\n         } else {\r\n          item.hash = '#/' + item.name;\r\n         }\r\n       }\r\n\r\n       return item.hash;\r\n    }\r\n  });\r\n\r\n  \r\n  function styleCodeLinks() {\r\n    var links = document.getElementsByTagName(\"a\");\r\n    for (var iLink = 0; iLink < links.length; iLink++) {\r\n      var link = links[iLink];\r\n      if (link.hash.startsWith('#/p5')) {\r\n        link.classList.add('code');\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n  // Get the router\r\n  App.router = new Router();\r\n\r\n  // Start history\r\n  Backbone.history.start();\r\n\r\n  return App.router;\r\n\r\n});\r\n\n",
             "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
        ->>>>>>> 9d7b3cc9fce50f6e6a71953acd05eea4b0ee0f21
             "}());"
           ]
         }
        \ No newline at end of file
        
        From 868701a54d3c2421023e590576e39a7186be1de4 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Mon, 11 May 2020 13:19:05 +0900
        Subject: [PATCH 16/36] syncing reference.js and reference.js.map with the
         current master branch version
        
        ---
         .../pages/reference/assets/js/reference.js    | 16 ++++----
         .../reference/assets/js/reference.js.map      | 40 +++++++++----------
         2 files changed, 28 insertions(+), 28 deletions(-)
        
        diff --git a/src/templates/pages/reference/assets/js/reference.js b/src/templates/pages/reference/assets/js/reference.js
        index ee120e52ea..b5f849aaed 100644
        --- a/src/templates/pages/reference/assets/js/reference.js
        +++ b/src/templates/pages/reference/assets/js/reference.js
        @@ -448,10 +448,10 @@ define('text',['module'], function (module) {
         });
         
         
        -define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\r\n<form>\r\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\r\n  <label class="sr-only" for="search_reference_field">Search reference</label>\r\n</form>\r\n\r\n';});
        +define('text!tpl/search.html',[],function () { return '<h2 class="sr-only">search</h2>\n<form>\n  <input id="search_reference_field" type="text" class="<%=className%>" value="" placeholder="<%=placeholder%>" aria-label="search reference">\n  <label class="sr-only" for="search_reference_field">Search reference</label>\n</form>\n\n';});
         
         
        -define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\r\n\r\n  <strong><%=name%></strong>\r\n\r\n  <span class="small">\r\n    <% if (final) { %>\r\n    constant\r\n    <% } else if (itemtype) { %>\r\n    <%=itemtype%> \r\n    <% } %>\r\n\r\n    <% if (className) { %>\r\n    in <strong><%=className%></strong>\r\n    <% } %>\r\n\r\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\r\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\r\n    <% } %>\r\n  </span>\r\n\r\n</p>';});
        +define('text!tpl/search_suggestion.html',[],function () { return '<p id="index-<%=idx%>" class="search-suggestion">\n\n  <strong><%=name%></strong>\n\n  <span class="small">\n    <% if (final) { %>\n    constant\n    <% } else if (itemtype) { %>\n    <%=itemtype%> \n    <% } %>\n\n    <% if (className) { %>\n    in <strong><%=className%></strong>\n    <% } %>\n\n    <% if (typeof is_constructor !== \'undefined\' && is_constructor) { %>\n    <strong><span class="glyphicon glyphicon-star"></span> constructor</strong>\n    <% } %>\n  </span>\n\n</p>';});
         
         /*!
          * typeahead.js 0.10.2
        @@ -2303,7 +2303,7 @@ define('searchView',[
         });
         
         
        -define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\r\n  <div class="reference-group clearfix main-ref-page">  \r\n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\r\n    <div class="reference-subgroups clearfix main-ref-page">  \r\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\r\n      <div class="reference-subgroup">\r\n        <% if (subgroup.name !== \'0\') { %>\r\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\r\n        <% } %>\r\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\r\n        <% _.each(subgroup.items, function(item) { %>\r\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\r\n        <% }); %>\r\n        </ul>\r\n      </div>\r\n    <% }); %>\r\n    </div>\r\n  </div>\r\n<% }); %>\r\n';});
        +define('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\n  <div class="reference-group clearfix main-ref-page">  \n    <h2 class="group-name" id="group-<%=group.name%>" tab-index="-1"><%=group.name%></h2>\n    <div class="reference-subgroups clearfix main-ref-page">  \n    <% _.each(group.subgroups, function(subgroup, ind) { %>\n      <div class="reference-subgroup">\n        <% if (subgroup.name !== \'0\') { %>\n          <h3 id="<%=group.name%><%=ind%>" class="subgroup-name subgroup-<%=subgroup.name%>"><%=subgroup.name%></h3>\n        <% } %>\n        <ul aria-labelledby="<%=group.name%> <%=ind%>">\n        <% _.each(subgroup.items, function(item) { %>\n        <li><a href="<%=item.hash%>"><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></li>\n        <% }); %>\n        </ul>\n      </div>\n    <% }); %>\n    </div>\n  </div>\n<% }); %>\n';});
         
         define('listView',[
           'App',
        @@ -2445,13 +2445,13 @@ define('listView',[
         });
         
         
        -define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\r\n\r\n<% if (item.example) { %>\r\n<div class="example">\r\n  <h3 id="reference-example">Examples</h3>\r\n\r\n  <div class="example-content" data-alt="<%= item.alt %>">\r\n    <% _.each(item.example, function(example, i){ %>\r\n      <%= example %>\r\n    <% }); %>\r\n  </div>\r\n</div>\r\n<% } %>\r\n\r\n<div class="description">\r\n    \r\n  <h3 id="reference-description">Description</h3>\r\n\r\n  <% if (item.deprecated) { %>\r\n    <p>\r\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\r\n    </p>\r\n  <% } %>\r\n      \r\n\r\n  <span class=\'description-text\'><%= item.description %></span>\r\n\r\n  <% if (item.extends) { %>\r\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\r\n  <% } %>\r\n\r\n  <% if (item.module === \'p5.sound\') { %>\r\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\r\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\r\n    </p>\r\n  <% } %>\r\n\r\n  <% if (item.constRefs) { %>\r\n    <p>Used by:\r\n  <%\r\n      var refs = item.constRefs;\r\n      for (var i = 0; i < refs.length; i ++) {\r\n        var ref = refs[i];\r\n        var name = ref;\r\n        if (name.substr(0, 3) === \'p5.\') {\r\n          name = name.substr(3);\r\n        }\r\n  if (i !== 0) {\r\n          if (i == refs.length - 1) {\r\n            %> and <%\r\n          } else {\r\n            %>, <%\r\n          }\r\n        }\r\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\r\n      }\r\n  %>\r\n    </p>\r\n  <% } %>\r\n</div>\r\n\r\n<% if (isConstructor || !isClass) { %>\r\n\r\n<div>\r\n  <h3 id="reference-syntax">Syntax</h3>\r\n  <p>\r\n    <% syntaxes.forEach(function(syntax) { %>\r\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\r\n    <% }) %>\r\n  </p>\r\n</div>\r\n\r\n\r\n<% if (item.params) { %>\r\n  <div class="params">\r\n    <h3 id="reference-parameters">Parameters</h3>\r\n    <ul aria-labelledby=\'reference-parameters\'>\r\n    <% for (var i=0; i<item.params.length; i++) { %>\r\n      <% var p = item.params[i] %>\r\n      <li>\r\n        <div class=\'paramname\'><%=p.name%></div>\r\n        <% if (p.type) { %>\r\n          <div class=\'paramtype\'>\r\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\r\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\r\n          <% if (p.optional) { %> (Optional)<% } %>\r\n          </div>\r\n        <% } %>\r\n      </li>\r\n    <% } %>\r\n    </ul>\r\n  </div>\r\n<% } %>\r\n\r\n<% if (item.return && item.return.type) { %>\r\n  <div>\r\n    <h3 id="reference-returns">Returns</h3>\r\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\r\n  </div>\r\n<% } %>\r\n\r\n<% } %>\r\n';});
        +define('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\n\n<% if (item.example) { %>\n<div class="example">\n  <h3 id="reference-example">Examples</h3>\n\n  <div class="example-content" data-alt="<%= item.alt %>">\n    <% _.each(item.example, function(example, i){ %>\n      <%= example %>\n    <% }); %>\n  </div>\n</div>\n<% } %>\n\n<div class="description">\n    \n  <h3 id="reference-description">Description</h3>\n\n  <% if (item.deprecated) { %>\n    <p>\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\n    </p>\n  <% } %>\n      \n\n  <span class=\'description-text\'><%= item.description %></span>\n\n  <% if (item.extends) { %>\n    <p><span id="reference-extends">Extends</span> <a href="/reference/#/<%=item.extends%>" title="<%=item.extends%> reference"><%=item.extends%></a></p>\n  <% } %>\n\n  <% if (item.module === \'p5.sound\') { %>\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\n      <pre><code class="language-javascript">&lt;script src="path/to/p5.sound.js"&gt;&lt;/script&gt;</code></pre>\n    </p>\n  <% } %>\n\n  <% if (item.constRefs) { %>\n    <p>Used by:\n  <%\n      var refs = item.constRefs;\n      for (var i = 0; i < refs.length; i ++) {\n        var ref = refs[i];\n        var name = ref;\n        if (name.substr(0, 3) === \'p5.\') {\n          name = name.substr(3);\n        }\n  if (i !== 0) {\n          if (i == refs.length - 1) {\n            %> and <%\n          } else {\n            %>, <%\n          }\n        }\n        %><a href="./#/<%= ref.replace(\'.\', \'/\') %>"><%= name %>()</a><%\n      }\n  %>\n    </p>\n  <% } %>\n</div>\n\n<% if (isConstructor || !isClass) { %>\n\n<div>\n  <h3 id="reference-syntax">Syntax</h3>\n  <p>\n    <% syntaxes.forEach(function(syntax) { %>\n    <pre><code class="language-javascript"><%= syntax %></code></pre>\n    <% }) %>\n  </p>\n</div>\n\n\n<% if (item.params) { %>\n  <div class="params">\n    <h3 id="reference-parameters">Parameters</h3>\n    <ul aria-labelledby=\'reference-parameters\'>\n    <% for (var i=0; i<item.params.length; i++) { %>\n      <% var p = item.params[i] %>\n      <li>\n        <div class=\'paramname\'><%=p.name%></div>\n        <% if (p.type) { %>\n          <div class=\'paramtype\'>\n          <% var type = p.type.replace(/(p5\\.[A-Z][A-Za-z]*)/, \'<a href="#/$1">$1</a>\'); %>\n          <span class="param-type label label-info"><%=type%></span>: <%=p.description%>\n          <% if (p.optional) { %> (Optional)<% } %>\n          </div>\n        <% } %>\n      </li>\n    <% } %>\n    </ul>\n  </div>\n<% } %>\n\n<% if (item.return && item.return.type) { %>\n  <div>\n    <h3 id="reference-returns">Returns</h3>\n    <p class=\'returns\'><span class="param-type label label-info"><%=item.return.type%></span>: <%= item.return.description %></p>\n  </div>\n<% } %>\n\n<% } %>\n';});
         
         
        -define('text!tpl/class.html',[],function () { return '\r\n<% if (typeof constructor !== \'undefined\') { %>\r\n<div class="constructor">\r\n  <%=constructor%>\r\n</div>\r\n<% } %>\r\n\r\n<% let fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\r\n<% if (fields.length > 0) { %>\r\n  <h3 id=\'reference-fields\'>Fields</h3>\r\n  <ul aria-labelledby=\'reference-fields\'>\r\n  <% _.each(fields, function(item) { %>\r\n    <li>\r\n      <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>\r\n      <div class=\'paramtype\'><%= item.description %></div>\r\n    </li>\r\n  <% }); %>\r\n  </ul>\r\n<% } %>\r\n\r\n<% let methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\r\n<% if (methods.length > 0) { %>\r\n  <h3 id=\'reference-methods\'>Methods</h3>\r\n  <ul aria-labelledby=\'reference-methods\'>\r\n    <% _.each(methods, function(item) { %>\r\n      <li>\r\n        <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></div>\r\n        <div class=\'paramtype\'><%= item.description %></div>\r\n      </li>\r\n    <% }); %>\r\n  </ul>\r\n<% } %>\r\n';});
        +define('text!tpl/class.html',[],function () { return '\n<% if (typeof constructor !== \'undefined\') { %>\n<div class="constructor">\n  <%=constructor%>\n</div>\n<% } %>\n\n<% let fields = _.filter(things, function(item) { return item.itemtype === \'property\' && item.access !== \'private\' }); %>\n<% if (fields.length > 0) { %>\n  <h3 id=\'reference-fields\'>Fields</h3>\n  <ul aria-labelledby=\'reference-fields\'>\n  <% _.each(fields, function(item) { %>\n    <li>\n      <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%></a></div>\n      <div class=\'paramtype\'><%= item.description %></div>\n    </li>\n  <% }); %>\n  </ul>\n<% } %>\n\n<% let methods = _.filter(things, function(item) { return item.itemtype === \'method\' && item.access !== \'private\' }); %>\n<% if (methods.length > 0) { %>\n  <h3 id=\'reference-methods\'>Methods</h3>\n  <ul aria-labelledby=\'reference-methods\'>\n    <% _.each(methods, function(item) { %>\n      <li>\n        <div class=\'paramname\'><a href="<%=item.hash%>" <% if (item.module !== module) { %>class="addon"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a></div>\n        <div class=\'paramtype\'><%= item.description %></div>\n      </li>\n    <% }); %>\n  </ul>\n<% } %>\n';});
         
         
        -define('text!tpl/itemEnd.html',[],function () { return '\r\n<br><br>\r\n\r\n<div>\r\n<% if (item.file && item.line) { %>\r\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\r\n<% } %>\r\n</div>\r\n\r\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\r\n<br><br>\r\n';});
        +define('text!tpl/itemEnd.html',[],function () { return '\n<br><br>\n\n<div>\n<% if (item.file && item.line) { %>\n<span id="reference-error1">Notice any errors or typos?</span> <a href="https://github.com/processing/p5.js/issues"><span id="reference-contribute2">Please let us know.</span></a> <span id="reference-error3">Please feel free to edit</span> <a href="https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>" target="_blank" ><%= item.file %></a> <span id="reference-error5">and issue a pull request!</span>\n<% } %>\n</div>\n\n<a style="border-bottom:none !important;" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target=_blank><img src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" style="width:88px" alt="creative commons logo"/></a>\n<br><br>\n';});
         
         // Copyright (C) 2006 Google Inc.
         //
        @@ -4335,7 +4335,7 @@ define('itemView',[
         });
         
         
        -define('text!tpl/menu.html',[],function () { return '<div>\r\n  <br>\r\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\r\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\r\n</div>\r\n\r\n<div id=\'collection-list-categories\'>\r\n<h2 class="sr-only" id="categories">Categories</h2>\r\n<% var i=0; %>\r\n<% var max=Math.floor(groups.length/4); %>\r\n<% var rem=groups.length%4; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% var m = rem > 0 ? 1 : 0 %>\r\n  <% if (i === 0) { %>\r\n    <ul aria-labelledby="categories">\r\n    <% } %>\r\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\r\n    <% if (i === (max+m-1)) { %>\r\n    </ul>\r\n  \t<% rem-- %>\r\n  \t<% i=0 %>\r\n  <% } else { %>\r\n  \t<% i++ %>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
        +define('text!tpl/menu.html',[],function () { return '<div>\n  <br>\n  <span id="reference-description1">Can\'t find what you\'re looking for? You may want to check out</span>\n  <a href="#/libraries/p5.sound">p5.sound</a>.<br><a href=\'https://p5js.org/offline-reference/p5-reference.zip\' target=_blank><span id="reference-description3">You can also download an offline version of the reference.</span></a>\n</div>\n\n<div id=\'collection-list-categories\'>\n<h2 class="sr-only" id="categories">Categories</h2>\n<% var i=0; %>\n<% var max=Math.floor(groups.length/4); %>\n<% var rem=groups.length%4; %>\n\n<% _.each(groups, function(group){ %>\n  <% var m = rem > 0 ? 1 : 0 %>\n  <% if (i === 0) { %>\n    <ul aria-labelledby="categories">\n    <% } %>\n    <li><a href="#group-<%=group%>"><%=group%></a></li>\n    <% if (i === (max+m-1)) { %>\n    </ul>\n  \t<% rem-- %>\n  \t<% i=0 %>\n  <% } else { %>\n  \t<% i++ %>\n  <% } %>\n<% }); %>\n</div>\n';});
         
         define('menuView',[
           'App',
        @@ -4404,7 +4404,7 @@ define('menuView',[
         });
         
         
        -define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\r\n\r\n<p><%= module.description %></p>\r\n\r\n<div id="library-page" class="reference-group clearfix">  \r\n\r\n<% var t = 0; col = 0; %>\r\n\r\n<% _.each(groups, function(group){ %>\r\n  <% if (t == 0) { %> \r\n    <div class="column_<%=col%>">\r\n  <% } %>\r\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\r\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \r\n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\r\n    <% if (group.hash) { %> </a><br> <% } %>\r\n  <% } %>\r\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\r\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\r\n    <% t++; %>\r\n  <% }); %>\r\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\r\n    </div>\r\n  <% } %>\r\n<% }); %>\r\n</div>\r\n';});
        +define('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\n\n<p><%= module.description %></p>\n\n<div id="library-page" class="reference-group clearfix">  \n\n<% var t = 0; col = 0; %>\n\n<% _.each(groups, function(group){ %>\n  <% if (t == 0) { %> \n    <div class="column_<%=col%>">\n  <% } %>\n  <% if (group.name !== module.name && group.name !== \'p5\') { %>\n    <% if (group.hash) { %> <a href="<%=group.hash%>" <% if (group.module !== module.name) { %>class="core"<% } %>><% } %>  \n    <h4 class="group-name <% if (t == 0) { %> first<%}%>"><%=group.name%></h4>\n    <% if (group.hash) { %> </a><br> <% } %>\n  <% } %>\n  <% _.each(group.items.filter(function(item) {return item.access !== \'private\'}), function(item) { %>\n    <a href="<%=item.hash%>" <% if (item.module !== module.name) { %>class="core"<% } %>><%=item.name%><% if (item.itemtype === \'method\') { %>()<%}%></a><br>\n    <% t++; %>\n  <% }); %>\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\n    </div>\n  <% } %>\n<% }); %>\n</div>\n';});
         
         define(
           'libraryView',[
        diff --git a/src/templates/pages/reference/assets/js/reference.js.map b/src/templates/pages/reference/assets/js/reference.js.map
        index 92c49461da..abfb0b3794 100644
        --- a/src/templates/pages/reference/assets/js/reference.js.map
        +++ b/src/templates/pages/reference/assets/js/reference.js.map
        @@ -29,26 +29,26 @@
           "file": "reference.js",
           "sourcesContent": [
             "(function () {\n",
        -    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\r\n(function (root, factory) {\r\n  if (typeof define === 'function' && define.amd) {\r\n    define('documented-method',[], factory);\r\n  } else if (typeof module === 'object' && module.exports) {\r\n    module.exports = factory();\r\n  } else {\r\n    root.DocumentedMethod = factory();\r\n  }\r\n}(this, function () {\r\n  function extend(target, src) {\r\n    Object.keys(src).forEach(function(prop) {\r\n      target[prop] = src[prop];\r\n    });\r\n    return target;\r\n  }\r\n\r\n  function DocumentedMethod(classitem) {\r\n    extend(this, classitem);\r\n\r\n    if (this.overloads) {\r\n      // Make each overload inherit properties from their parent\r\n      // classitem.\r\n      this.overloads = this.overloads.map(function(overload) {\r\n        return extend(Object.create(this), overload);\r\n      }, this);\r\n\r\n      if (this.params) {\r\n        throw new Error('params for overloaded methods should be undefined');\r\n      }\r\n\r\n      this.params = this._getMergedParams();\r\n    }\r\n  }\r\n\r\n  DocumentedMethod.prototype = {\r\n    // Merge parameters across all overloaded versions of this item.\r\n    _getMergedParams: function() {\r\n      var paramNames = {};\r\n      var params = [];\r\n\r\n      this.overloads.forEach(function(overload) {\r\n        if (!overload.params) {\r\n          return;\r\n        }\r\n        overload.params.forEach(function(param) {\r\n          if (param.name in paramNames) {\r\n            return;\r\n          }\r\n          paramNames[param.name] = param;\r\n          params.push(param);\r\n        });\r\n      });\r\n\r\n      return params;\r\n    }\r\n  };\r\n\r\n  return DocumentedMethod;\r\n}));\r\n\n",
        -    "/**\r\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\r\n * Available via the MIT or new BSD license.\r\n * see: http://github.com/requirejs/text for details\r\n */\r\n/*jslint regexp: true */\r\n/*global require, XMLHttpRequest, ActiveXObject,\r\n  define, window, process, Packages,\r\n  java, location, Components, FileUtils */\r\n\r\ndefine('text',['module'], function (module) {\r\n    'use strict';\r\n\r\n    var text, fs, Cc, Ci, xpcIsWindows,\r\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\r\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\r\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\r\n        hasLocation = typeof location !== 'undefined' && location.href,\r\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\r\n        defaultHostName = hasLocation && location.hostname,\r\n        defaultPort = hasLocation && (location.port || undefined),\r\n        buildMap = {},\r\n        masterConfig = (module.config && module.config()) || {};\r\n\r\n    text = {\r\n        version: '2.0.10',\r\n\r\n        strip: function (content) {\r\n            //Strips <?xml ...?> declarations so that external SVG and XML\r\n            //documents can be added to a document without worry. Also, if the string\r\n            //is an HTML document, only the part inside the body tag is returned.\r\n            if (content) {\r\n                content = content.replace(xmlRegExp, \"\");\r\n                var matches = content.match(bodyRegExp);\r\n                if (matches) {\r\n                    content = matches[1];\r\n                }\r\n            } else {\r\n                content = \"\";\r\n            }\r\n            return content;\r\n        },\r\n\r\n        jsEscape: function (content) {\r\n            return content.replace(/(['\\\\])/g, '\\\\$1')\r\n                .replace(/[\\f]/g, \"\\\\f\")\r\n                .replace(/[\\b]/g, \"\\\\b\")\r\n                .replace(/[\\n]/g, \"\\\\n\")\r\n                .replace(/[\\t]/g, \"\\\\t\")\r\n                .replace(/[\\r]/g, \"\\\\r\")\r\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\r\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\r\n        },\r\n\r\n        createXhr: masterConfig.createXhr || function () {\r\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\r\n            var xhr, i, progId;\r\n            if (typeof XMLHttpRequest !== \"undefined\") {\r\n                return new XMLHttpRequest();\r\n            } else if (typeof ActiveXObject !== \"undefined\") {\r\n                for (i = 0; i < 3; i += 1) {\r\n                    progId = progIds[i];\r\n                    try {\r\n                        xhr = new ActiveXObject(progId);\r\n                    } catch (e) {}\r\n\r\n                    if (xhr) {\r\n                        progIds = [progId];  // so faster next time\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            return xhr;\r\n        },\r\n\r\n        /**\r\n         * Parses a resource name into its component parts. Resource names\r\n         * look like: module/name.ext!strip, where the !strip part is\r\n         * optional.\r\n         * @param {String} name the resource name\r\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\r\n         * where strip is a boolean.\r\n         */\r\n        parseName: function (name) {\r\n            var modName, ext, temp,\r\n                strip = false,\r\n                index = name.indexOf(\".\"),\r\n                isRelative = name.indexOf('./') === 0 ||\r\n                             name.indexOf('../') === 0;\r\n\r\n            if (index !== -1 && (!isRelative || index > 1)) {\r\n                modName = name.substring(0, index);\r\n                ext = name.substring(index + 1, name.length);\r\n            } else {\r\n                modName = name;\r\n            }\r\n\r\n            temp = ext || modName;\r\n            index = temp.indexOf(\"!\");\r\n            if (index !== -1) {\r\n                //Pull off the strip arg.\r\n                strip = temp.substring(index + 1) === \"strip\";\r\n                temp = temp.substring(0, index);\r\n                if (ext) {\r\n                    ext = temp;\r\n                } else {\r\n                    modName = temp;\r\n                }\r\n            }\r\n\r\n            return {\r\n                moduleName: modName,\r\n                ext: ext,\r\n                strip: strip\r\n            };\r\n        },\r\n\r\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\r\n\r\n        /**\r\n         * Is an URL on another domain. Only works for browser use, returns\r\n         * false in non-browser environments. Only used to know if an\r\n         * optimized .js version of a text resource should be loaded\r\n         * instead.\r\n         * @param {String} url\r\n         * @returns Boolean\r\n         */\r\n        useXhr: function (url, protocol, hostname, port) {\r\n            var uProtocol, uHostName, uPort,\r\n                match = text.xdRegExp.exec(url);\r\n            if (!match) {\r\n                return true;\r\n            }\r\n            uProtocol = match[2];\r\n            uHostName = match[3];\r\n\r\n            uHostName = uHostName.split(':');\r\n            uPort = uHostName[1];\r\n            uHostName = uHostName[0];\r\n\r\n            return (!uProtocol || uProtocol === protocol) &&\r\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\r\n                   ((!uPort && !uHostName) || uPort === port);\r\n        },\r\n\r\n        finishLoad: function (name, strip, content, onLoad) {\r\n            content = strip ? text.strip(content) : content;\r\n            if (masterConfig.isBuild) {\r\n                buildMap[name] = content;\r\n            }\r\n            onLoad(content);\r\n        },\r\n\r\n        load: function (name, req, onLoad, config) {\r\n            //Name has format: some.module.filext!strip\r\n            //The strip part is optional.\r\n            //if strip is present, then that means only get the string contents\r\n            //inside a body tag in an HTML string. For XML/SVG content it means\r\n            //removing the <?xml ...?> declarations so the content can be inserted\r\n            //into the current doc without problems.\r\n\r\n            // Do not bother with the work if a build and text will\r\n            // not be inlined.\r\n            if (config.isBuild && !config.inlineText) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            masterConfig.isBuild = config.isBuild;\r\n\r\n            var parsed = text.parseName(name),\r\n                nonStripName = parsed.moduleName +\r\n                    (parsed.ext ? '.' + parsed.ext : ''),\r\n                url = req.toUrl(nonStripName),\r\n                useXhr = (masterConfig.useXhr) ||\r\n                         text.useXhr;\r\n\r\n            // Do not load if it is an empty: url\r\n            if (url.indexOf('empty:') === 0) {\r\n                onLoad();\r\n                return;\r\n            }\r\n\r\n            //Load the text. Use XHR if possible and in a browser.\r\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\r\n                text.get(url, function (content) {\r\n                    text.finishLoad(name, parsed.strip, content, onLoad);\r\n                }, function (err) {\r\n                    if (onLoad.error) {\r\n                        onLoad.error(err);\r\n                    }\r\n                });\r\n            } else {\r\n                //Need to fetch the resource across domains. Assume\r\n                //the resource has been optimized into a JS module. Fetch\r\n                //by the module name + extension, but do not include the\r\n                //!strip part to avoid file system issues.\r\n                req([nonStripName], function (content) {\r\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\r\n                                    parsed.strip, content, onLoad);\r\n                });\r\n            }\r\n        },\r\n\r\n        write: function (pluginName, moduleName, write, config) {\r\n            if (buildMap.hasOwnProperty(moduleName)) {\r\n                var content = text.jsEscape(buildMap[moduleName]);\r\n                write.asModule(pluginName + \"!\" + moduleName,\r\n                               \"define(function () { return '\" +\r\n                                   content +\r\n                               \"';});\\n\");\r\n            }\r\n        },\r\n\r\n        writeFile: function (pluginName, moduleName, req, write, config) {\r\n            var parsed = text.parseName(moduleName),\r\n                extPart = parsed.ext ? '.' + parsed.ext : '',\r\n                nonStripName = parsed.moduleName + extPart,\r\n                //Use a '.js' file name so that it indicates it is a\r\n                //script that can be loaded across domains.\r\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\r\n\r\n            //Leverage own load() method to load plugin value, but only\r\n            //write out values that do not have the strip argument,\r\n            //to avoid any potential issues with ! in file names.\r\n            text.load(nonStripName, req, function (value) {\r\n                //Use own write() method to construct full module value.\r\n                //But need to create shell that translates writeFile's\r\n                //write() to the right interface.\r\n                var textWrite = function (contents) {\r\n                    return write(fileName, contents);\r\n                };\r\n                textWrite.asModule = function (moduleName, contents) {\r\n                    return write.asModule(moduleName, fileName, contents);\r\n                };\r\n\r\n                text.write(pluginName, nonStripName, textWrite, config);\r\n            }, config);\r\n        }\r\n    };\r\n\r\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\r\n            typeof process !== \"undefined\" &&\r\n            process.versions &&\r\n            !!process.versions.node &&\r\n            !process.versions['node-webkit'])) {\r\n        //Using special require.nodeRequire, something added by r.js.\r\n        fs = require.nodeRequire('fs');\r\n\r\n        text.get = function (url, callback, errback) {\r\n            try {\r\n                var file = fs.readFileSync(url, 'utf8');\r\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\r\n                if (file.indexOf('\\uFEFF') === 0) {\r\n                    file = file.substring(1);\r\n                }\r\n                callback(file);\r\n            } catch (e) {\r\n                errback(e);\r\n            }\r\n        };\r\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\r\n            text.createXhr())) {\r\n        text.get = function (url, callback, errback, headers) {\r\n            var xhr = text.createXhr(), header;\r\n            xhr.open('GET', url, true);\r\n\r\n            //Allow plugins direct access to xhr headers\r\n            if (headers) {\r\n                for (header in headers) {\r\n                    if (headers.hasOwnProperty(header)) {\r\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\r\n                    }\r\n                }\r\n            }\r\n\r\n            //Allow overrides specified in config\r\n            if (masterConfig.onXhr) {\r\n                masterConfig.onXhr(xhr, url);\r\n            }\r\n\r\n            xhr.onreadystatechange = function (evt) {\r\n                var status, err;\r\n                //Do not explicitly handle errors, those should be\r\n                //visible via console output in the browser.\r\n                if (xhr.readyState === 4) {\r\n                    status = xhr.status;\r\n                    if (status > 399 && status < 600) {\r\n                        //An http 4xx or 5xx error. Signal an error.\r\n                        err = new Error(url + ' HTTP status: ' + status);\r\n                        err.xhr = xhr;\r\n                        errback(err);\r\n                    } else {\r\n                        callback(xhr.responseText);\r\n                    }\r\n\r\n                    if (masterConfig.onXhrComplete) {\r\n                        masterConfig.onXhrComplete(xhr, url);\r\n                    }\r\n                }\r\n            };\r\n            xhr.send(null);\r\n        };\r\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\r\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\r\n        //Why Java, why is this so awkward?\r\n        text.get = function (url, callback) {\r\n            var stringBuffer, line,\r\n                encoding = \"utf-8\",\r\n                file = new java.io.File(url),\r\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\r\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\r\n                content = '';\r\n            try {\r\n                stringBuffer = new java.lang.StringBuffer();\r\n                line = input.readLine();\r\n\r\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\r\n                // http://www.unicode.org/faq/utf_bom.html\r\n\r\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\r\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\r\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\r\n                    // Eat the BOM, since we've already found the encoding on this file,\r\n                    // and we plan to concatenating this buffer with others; the BOM should\r\n                    // only appear at the top of a file.\r\n                    line = line.substring(1);\r\n                }\r\n\r\n                if (line !== null) {\r\n                    stringBuffer.append(line);\r\n                }\r\n\r\n                while ((line = input.readLine()) !== null) {\r\n                    stringBuffer.append(lineSeparator);\r\n                    stringBuffer.append(line);\r\n                }\r\n                //Make sure we return a JavaScript string and not a Java string.\r\n                content = String(stringBuffer.toString()); //String\r\n            } finally {\r\n                input.close();\r\n            }\r\n            callback(content);\r\n        };\r\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\r\n            typeof Components !== 'undefined' && Components.classes &&\r\n            Components.interfaces)) {\r\n        //Avert your gaze!\r\n        Cc = Components.classes,\r\n        Ci = Components.interfaces;\r\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\r\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\r\n\r\n        text.get = function (url, callback) {\r\n            var inStream, convertStream, fileObj,\r\n                readData = {};\r\n\r\n            if (xpcIsWindows) {\r\n                url = url.replace(/\\//g, '\\\\');\r\n            }\r\n\r\n            fileObj = new FileUtils.File(url);\r\n\r\n            //XPCOM, you so crazy\r\n            try {\r\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\r\n                           .createInstance(Ci.nsIFileInputStream);\r\n                inStream.init(fileObj, 1, 0, false);\r\n\r\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\r\n                                .createInstance(Ci.nsIConverterInputStream);\r\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\r\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\r\n\r\n                convertStream.readString(inStream.available(), readData);\r\n                convertStream.close();\r\n                inStream.close();\r\n                callback(readData.value);\r\n            } catch (e) {\r\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\r\n            }\r\n        };\r\n    }\r\n    return text;\r\n});\r\n\n",
        -    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\r\\n<form>\\r\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\r\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\r\\n</form>\\r\\n\\r\\n';});\n\n",
        -    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\r\\n\\r\\n  <strong><%=name%></strong>\\r\\n\\r\\n  <span class=\"small\">\\r\\n    <% if (final) { %>\\r\\n    constant\\r\\n    <% } else if (itemtype) { %>\\r\\n    <%=itemtype%> \\r\\n    <% } %>\\r\\n\\r\\n    <% if (className) { %>\\r\\n    in <strong><%=className%></strong>\\r\\n    <% } %>\\r\\n\\r\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\r\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\r\\n    <% } %>\\r\\n  </span>\\r\\n\\r\\n</p>';});\n\n",
        -    "/*!\r\n * typeahead.js 0.10.2\r\n * https://github.com/twitter/typeahead.js\r\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\r\n */\r\ndefine('typeahead',[], function() {\r\n\r\n//(function($) {\r\n\r\n\r\n    var _ = {\r\n        isMsie: function() {\r\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\r\n        },\r\n        isBlankString: function(str) {\r\n            return !str || /^\\s*$/.test(str);\r\n        },\r\n        escapeRegExChars: function(str) {\r\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\r\n        },\r\n        isString: function(obj) {\r\n            return typeof obj === \"string\";\r\n        },\r\n        isNumber: function(obj) {\r\n            return typeof obj === \"number\";\r\n        },\r\n        isArray: $.isArray,\r\n        isFunction: $.isFunction,\r\n        isObject: $.isPlainObject,\r\n        isUndefined: function(obj) {\r\n            return typeof obj === \"undefined\";\r\n        },\r\n        bind: $.proxy,\r\n        each: function(collection, cb) {\r\n            $.each(collection, reverseArgs);\r\n            function reverseArgs(index, value) {\r\n                return cb(value, index);\r\n            }\r\n        },\r\n        map: $.map,\r\n        filter: $.grep,\r\n        every: function(obj, test) {\r\n            var result = true;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (!(result = test.call(null, val, key, obj))) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        some: function(obj, test) {\r\n            var result = false;\r\n            if (!obj) {\r\n                return result;\r\n            }\r\n            $.each(obj, function(key, val) {\r\n                if (result = test.call(null, val, key, obj)) {\r\n                    return false;\r\n                }\r\n            });\r\n            return !!result;\r\n        },\r\n        mixin: $.extend,\r\n        getUniqueId: function() {\r\n            var counter = 0;\r\n            return function() {\r\n                return counter++;\r\n            };\r\n        }(),\r\n        templatify: function templatify(obj) {\r\n            return $.isFunction(obj) ? obj : template;\r\n            function template() {\r\n                return String(obj);\r\n            }\r\n        },\r\n        defer: function(fn) {\r\n            setTimeout(fn, 0);\r\n        },\r\n        debounce: function(func, wait, immediate) {\r\n            var timeout, result;\r\n            return function() {\r\n                var context = this, args = arguments, later, callNow;\r\n                later = function() {\r\n                    timeout = null;\r\n                    if (!immediate) {\r\n                        result = func.apply(context, args);\r\n                    }\r\n                };\r\n                callNow = immediate && !timeout;\r\n                clearTimeout(timeout);\r\n                timeout = setTimeout(later, wait);\r\n                if (callNow) {\r\n                    result = func.apply(context, args);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        throttle: function(func, wait) {\r\n            var context, args, timeout, result, previous, later;\r\n            previous = 0;\r\n            later = function() {\r\n                previous = new Date();\r\n                timeout = null;\r\n                result = func.apply(context, args);\r\n            };\r\n            return function() {\r\n                var now = new Date(), remaining = wait - (now - previous);\r\n                context = this;\r\n                args = arguments;\r\n                if (remaining <= 0) {\r\n                    clearTimeout(timeout);\r\n                    timeout = null;\r\n                    previous = now;\r\n                    result = func.apply(context, args);\r\n                } else if (!timeout) {\r\n                    timeout = setTimeout(later, remaining);\r\n                }\r\n                return result;\r\n            };\r\n        },\r\n        noop: function() {}\r\n    };\r\n    var VERSION = \"0.10.2\";\r\n    var tokenizers = function(root) {\r\n        return {\r\n            nonword: nonword,\r\n            whitespace: whitespace,\r\n            obj: {\r\n                nonword: getObjTokenizer(nonword),\r\n                whitespace: getObjTokenizer(whitespace)\r\n            }\r\n        };\r\n        function whitespace(s) {\r\n            return s.split(/\\s+/);\r\n        }\r\n        function nonword(s) {\r\n            return s.split(/\\W+/);\r\n        }\r\n        function getObjTokenizer(tokenizer) {\r\n            return function setKey(key) {\r\n                return function tokenize(o) {\r\n                    return tokenizer(o[key]);\r\n                };\r\n            };\r\n        }\r\n    }();\r\n    var LruCache = function() {\r\n        function LruCache(maxSize) {\r\n            this.maxSize = maxSize || 100;\r\n            this.size = 0;\r\n            this.hash = {};\r\n            this.list = new List();\r\n        }\r\n        _.mixin(LruCache.prototype, {\r\n            set: function set(key, val) {\r\n                var tailItem = this.list.tail, node;\r\n                if (this.size >= this.maxSize) {\r\n                    this.list.remove(tailItem);\r\n                    delete this.hash[tailItem.key];\r\n                }\r\n                if (node = this.hash[key]) {\r\n                    node.val = val;\r\n                    this.list.moveToFront(node);\r\n                } else {\r\n                    node = new Node(key, val);\r\n                    this.list.add(node);\r\n                    this.hash[key] = node;\r\n                    this.size++;\r\n                }\r\n            },\r\n            get: function get(key) {\r\n                var node = this.hash[key];\r\n                if (node) {\r\n                    this.list.moveToFront(node);\r\n                    return node.val;\r\n                }\r\n            }\r\n        });\r\n        function List() {\r\n            this.head = this.tail = null;\r\n        }\r\n        _.mixin(List.prototype, {\r\n            add: function add(node) {\r\n                if (this.head) {\r\n                    node.next = this.head;\r\n                    this.head.prev = node;\r\n                }\r\n                this.head = node;\r\n                this.tail = this.tail || node;\r\n            },\r\n            remove: function remove(node) {\r\n                node.prev ? node.prev.next = node.next : this.head = node.next;\r\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\r\n            },\r\n            moveToFront: function(node) {\r\n                this.remove(node);\r\n                this.add(node);\r\n            }\r\n        });\r\n        function Node(key, val) {\r\n            this.key = key;\r\n            this.val = val;\r\n            this.prev = this.next = null;\r\n        }\r\n        return LruCache;\r\n    }();\r\n    var PersistentStorage = function() {\r\n        var ls, methods;\r\n        try {\r\n            ls = window.localStorage;\r\n            ls.setItem(\"~~~\", \"!\");\r\n            ls.removeItem(\"~~~\");\r\n        } catch (err) {\r\n            ls = null;\r\n        }\r\n        function PersistentStorage(namespace) {\r\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\r\n            this.ttlKey = \"__ttl__\";\r\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\r\n        }\r\n        if (ls && window.JSON) {\r\n            methods = {\r\n                _prefix: function(key) {\r\n                    return this.prefix + key;\r\n                },\r\n                _ttlKey: function(key) {\r\n                    return this._prefix(key) + this.ttlKey;\r\n                },\r\n                get: function(key) {\r\n                    if (this.isExpired(key)) {\r\n                        this.remove(key);\r\n                    }\r\n                    return decode(ls.getItem(this._prefix(key)));\r\n                },\r\n                set: function(key, val, ttl) {\r\n                    if (_.isNumber(ttl)) {\r\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\r\n                    } else {\r\n                        ls.removeItem(this._ttlKey(key));\r\n                    }\r\n                    return ls.setItem(this._prefix(key), encode(val));\r\n                },\r\n                remove: function(key) {\r\n                    ls.removeItem(this._ttlKey(key));\r\n                    ls.removeItem(this._prefix(key));\r\n                    return this;\r\n                },\r\n                clear: function() {\r\n                    var i, key, keys = [], len = ls.length;\r\n                    for (i = 0; i < len; i++) {\r\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\r\n                            keys.push(key.replace(this.keyMatcher, \"\"));\r\n                        }\r\n                    }\r\n                    for (i = keys.length; i--; ) {\r\n                        this.remove(keys[i]);\r\n                    }\r\n                    return this;\r\n                },\r\n                isExpired: function(key) {\r\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\r\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\r\n                }\r\n            };\r\n        } else {\r\n            methods = {\r\n                get: _.noop,\r\n                set: _.noop,\r\n                remove: _.noop,\r\n                clear: _.noop,\r\n                isExpired: _.noop\r\n            };\r\n        }\r\n        _.mixin(PersistentStorage.prototype, methods);\r\n        return PersistentStorage;\r\n        function now() {\r\n            return new Date().getTime();\r\n        }\r\n        function encode(val) {\r\n            return JSON.stringify(_.isUndefined(val) ? null : val);\r\n        }\r\n        function decode(val) {\r\n            return JSON.parse(val);\r\n        }\r\n    }();\r\n    var Transport = function() {\r\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\r\n        function Transport(o) {\r\n            o = o || {};\r\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\r\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\r\n        }\r\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\r\n            maxPendingRequests = num;\r\n        };\r\n        Transport.resetCache = function clearCache() {\r\n            requestCache = new LruCache(10);\r\n        };\r\n        _.mixin(Transport.prototype, {\r\n            _get: function(url, o, cb) {\r\n                var that = this, jqXhr;\r\n                if (jqXhr = pendingRequests[url]) {\r\n                    jqXhr.done(done).fail(fail);\r\n                } else if (pendingRequestsCount < maxPendingRequests) {\r\n                    pendingRequestsCount++;\r\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\r\n                } else {\r\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\r\n                }\r\n                function done(resp) {\r\n                    cb && cb(null, resp);\r\n                    requestCache.set(url, resp);\r\n                }\r\n                function fail() {\r\n                    cb && cb(true);\r\n                }\r\n                function always() {\r\n                    pendingRequestsCount--;\r\n                    delete pendingRequests[url];\r\n                    if (that.onDeckRequestArgs) {\r\n                        that._get.apply(that, that.onDeckRequestArgs);\r\n                        that.onDeckRequestArgs = null;\r\n                    }\r\n                }\r\n            },\r\n            get: function(url, o, cb) {\r\n                var resp;\r\n                if (_.isFunction(o)) {\r\n                    cb = o;\r\n                    o = {};\r\n                }\r\n                if (resp = requestCache.get(url)) {\r\n                    _.defer(function() {\r\n                        cb && cb(null, resp);\r\n                    });\r\n                } else {\r\n                    this._get(url, o, cb);\r\n                }\r\n                return !!resp;\r\n            }\r\n        });\r\n        return Transport;\r\n        function callbackToDeferred(fn) {\r\n            return function customSendWrapper(url, o) {\r\n                var deferred = $.Deferred();\r\n                fn(url, o, onSuccess, onError);\r\n                return deferred;\r\n                function onSuccess(resp) {\r\n                    _.defer(function() {\r\n                        deferred.resolve(resp);\r\n                    });\r\n                }\r\n                function onError(err) {\r\n                    _.defer(function() {\r\n                        deferred.reject(err);\r\n                    });\r\n                }\r\n            };\r\n        }\r\n    }();\r\n    var SearchIndex = function() {\r\n        function SearchIndex(o) {\r\n            o = o || {};\r\n            if (!o.datumTokenizer || !o.queryTokenizer) {\r\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\r\n            }\r\n            this.datumTokenizer = o.datumTokenizer;\r\n            this.queryTokenizer = o.queryTokenizer;\r\n            this.reset();\r\n        }\r\n        _.mixin(SearchIndex.prototype, {\r\n            bootstrap: function bootstrap(o) {\r\n                this.datums = o.datums;\r\n                this.trie = o.trie;\r\n            },\r\n            add: function(data) {\r\n                var that = this;\r\n                data = _.isArray(data) ? data : [ data ];\r\n                _.each(data, function(datum) {\r\n                    var id, tokens;\r\n                    id = that.datums.push(datum) - 1;\r\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\r\n                    _.each(tokens, function(token) {\r\n                        var node, chars, ch;\r\n                        node = that.trie;\r\n                        chars = token.split(\"\");\r\n                        while (ch = chars.shift()) {\r\n                            node = node.children[ch] || (node.children[ch] = newNode());\r\n                            node.ids.push(id);\r\n                        }\r\n                    });\r\n                });\r\n            },\r\n            get: function get(query) {\r\n                var that = this, tokens, matches;\r\n                tokens = normalizeTokens(this.queryTokenizer(query));\r\n                _.each(tokens, function(token) {\r\n                    var node, chars, ch, ids;\r\n                    if (matches && matches.length === 0) {\r\n                        return false;\r\n                    }\r\n                    node = that.trie;\r\n                    chars = token.split(\"\");\r\n                    while (node && (ch = chars.shift())) {\r\n                        node = node.children[ch];\r\n                    }\r\n                    if (node && chars.length === 0) {\r\n                        ids = node.ids.slice(0);\r\n                        matches = matches ? getIntersection(matches, ids) : ids;\r\n                    } else {\r\n                        matches = [];\r\n                        return false;\r\n                    }\r\n                });\r\n                return matches ? _.map(unique(matches), function(id) {\r\n                    return that.datums[id];\r\n                }) : [];\r\n            },\r\n            reset: function reset() {\r\n                this.datums = [];\r\n                this.trie = newNode();\r\n            },\r\n            serialize: function serialize() {\r\n                return {\r\n                    datums: this.datums,\r\n                    trie: this.trie\r\n                };\r\n            }\r\n        });\r\n        return SearchIndex;\r\n        function normalizeTokens(tokens) {\r\n            tokens = _.filter(tokens, function(token) {\r\n                return !!token;\r\n            });\r\n            tokens = _.map(tokens, function(token) {\r\n                return token.toLowerCase();\r\n            });\r\n            return tokens;\r\n        }\r\n        function newNode() {\r\n            return {\r\n                ids: [],\r\n                children: {}\r\n            };\r\n        }\r\n        function unique(array) {\r\n            var seen = {}, uniques = [];\r\n            for (var i = 0; i < array.length; i++) {\r\n                if (!seen[array[i]]) {\r\n                    seen[array[i]] = true;\r\n                    uniques.push(array[i]);\r\n                }\r\n            }\r\n            return uniques;\r\n        }\r\n        function getIntersection(arrayA, arrayB) {\r\n            var ai = 0, bi = 0, intersection = [];\r\n            arrayA = arrayA.sort(compare);\r\n            arrayB = arrayB.sort(compare);\r\n            while (ai < arrayA.length && bi < arrayB.length) {\r\n                if (arrayA[ai] < arrayB[bi]) {\r\n                    ai++;\r\n                } else if (arrayA[ai] > arrayB[bi]) {\r\n                    bi++;\r\n                } else {\r\n                    intersection.push(arrayA[ai]);\r\n                    ai++;\r\n                    bi++;\r\n                }\r\n            }\r\n            return intersection;\r\n            function compare(a, b) {\r\n                return a - b;\r\n            }\r\n        }\r\n    }();\r\n    var oParser = function() {\r\n        return {\r\n            local: getLocal,\r\n            prefetch: getPrefetch,\r\n            remote: getRemote\r\n        };\r\n        function getLocal(o) {\r\n            return o.local || null;\r\n        }\r\n        function getPrefetch(o) {\r\n            var prefetch, defaults;\r\n            defaults = {\r\n                url: null,\r\n                thumbprint: \"\",\r\n                ttl: 24 * 60 * 60 * 1e3,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (prefetch = o.prefetch || null) {\r\n                prefetch = _.isString(prefetch) ? {\r\n                    url: prefetch\r\n                } : prefetch;\r\n                prefetch = _.mixin(defaults, prefetch);\r\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\r\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\r\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\r\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\r\n            }\r\n            return prefetch;\r\n        }\r\n        function getRemote(o) {\r\n            var remote, defaults;\r\n            defaults = {\r\n                url: null,\r\n                wildcard: \"%QUERY\",\r\n                replace: null,\r\n                rateLimitBy: \"debounce\",\r\n                rateLimitWait: 300,\r\n                send: null,\r\n                filter: null,\r\n                ajax: {}\r\n            };\r\n            if (remote = o.remote || null) {\r\n                remote = _.isString(remote) ? {\r\n                    url: remote\r\n                } : remote;\r\n                remote = _.mixin(defaults, remote);\r\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\r\n                remote.ajax.type = remote.ajax.type || \"GET\";\r\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\r\n                delete remote.rateLimitBy;\r\n                delete remote.rateLimitWait;\r\n                !remote.url && $.error(\"remote requires url to be set\");\r\n            }\r\n            return remote;\r\n            function byDebounce(wait) {\r\n                return function(fn) {\r\n                    return _.debounce(fn, wait);\r\n                };\r\n            }\r\n            function byThrottle(wait) {\r\n                return function(fn) {\r\n                    return _.throttle(fn, wait);\r\n                };\r\n            }\r\n        }\r\n    }();\r\n    (function(root) {\r\n        var old, keys;\r\n        old = root.Bloodhound;\r\n        keys = {\r\n            data: \"data\",\r\n            protocol: \"protocol\",\r\n            thumbprint: \"thumbprint\"\r\n        };\r\n        root.Bloodhound = Bloodhound;\r\n        function Bloodhound(o) {\r\n            if (!o || !o.local && !o.prefetch && !o.remote) {\r\n                $.error(\"one of local, prefetch, or remote is required\");\r\n            }\r\n            this.limit = o.limit || 5;\r\n            this.sorter = getSorter(o.sorter);\r\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\r\n            this.local = oParser.local(o);\r\n            this.prefetch = oParser.prefetch(o);\r\n            this.remote = oParser.remote(o);\r\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\r\n            this.index = new SearchIndex({\r\n                datumTokenizer: o.datumTokenizer,\r\n                queryTokenizer: o.queryTokenizer\r\n            });\r\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\r\n        }\r\n        Bloodhound.noConflict = function noConflict() {\r\n            root.Bloodhound = old;\r\n            return Bloodhound;\r\n        };\r\n        Bloodhound.tokenizers = tokenizers;\r\n        _.mixin(Bloodhound.prototype, {\r\n            _loadPrefetch: function loadPrefetch(o) {\r\n                var that = this, serialized, deferred;\r\n                if (serialized = this._readFromStorage(o.thumbprint)) {\r\n                    this.index.bootstrap(serialized);\r\n                    deferred = $.Deferred().resolve();\r\n                } else {\r\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\r\n                }\r\n                return deferred;\r\n                function handlePrefetchResponse(resp) {\r\n                    that.clear();\r\n                    that.add(o.filter ? o.filter(resp) : resp);\r\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\r\n                }\r\n            },\r\n            _getFromRemote: function getFromRemote(query, cb) {\r\n                var that = this, url, uriEncodedQuery;\r\n                query = query || \"\";\r\n                uriEncodedQuery = encodeURIComponent(query);\r\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\r\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\r\n                function handleRemoteResponse(err, resp) {\r\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\r\n                }\r\n            },\r\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\r\n                if (this.storage) {\r\n                    this.storage.set(keys.data, data, ttl);\r\n                    this.storage.set(keys.protocol, location.protocol, ttl);\r\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\r\n                }\r\n            },\r\n            _readFromStorage: function readFromStorage(thumbprint) {\r\n                var stored = {}, isExpired;\r\n                if (this.storage) {\r\n                    stored.data = this.storage.get(keys.data);\r\n                    stored.protocol = this.storage.get(keys.protocol);\r\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\r\n                }\r\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\r\n                return stored.data && !isExpired ? stored.data : null;\r\n            },\r\n            _initialize: function initialize() {\r\n                var that = this, local = this.local, deferred;\r\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\r\n                local && deferred.done(addLocalToIndex);\r\n                this.transport = this.remote ? new Transport(this.remote) : null;\r\n                return this.initPromise = deferred.promise();\r\n                function addLocalToIndex() {\r\n                    that.add(_.isFunction(local) ? local() : local);\r\n                }\r\n            },\r\n            initialize: function initialize(force) {\r\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\r\n            },\r\n            add: function add(data) {\r\n                this.index.add(data);\r\n            },\r\n            get: function get(query, cb) {\r\n                var that = this, matches = [], cacheHit = false;\r\n                matches = this.index.get(query);\r\n                matches = this.sorter(matches).slice(0, this.limit);\r\n                if (matches.length < this.limit && this.transport) {\r\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\r\n                }\r\n                if (!cacheHit) {\r\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\r\n                }\r\n                function returnRemoteMatches(remoteMatches) {\r\n                    var matchesWithBackfill = matches.slice(0);\r\n                    _.each(remoteMatches, function(remoteMatch) {\r\n                        var isDuplicate;\r\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\r\n                            return that.dupDetector(remoteMatch, match);\r\n                        });\r\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\r\n                        return matchesWithBackfill.length < that.limit;\r\n                    });\r\n                    cb && cb(that.sorter(matchesWithBackfill));\r\n                }\r\n            },\r\n            clear: function clear() {\r\n                this.index.reset();\r\n            },\r\n            clearPrefetchCache: function clearPrefetchCache() {\r\n                this.storage && this.storage.clear();\r\n            },\r\n            clearRemoteCache: function clearRemoteCache() {\r\n                this.transport && Transport.resetCache();\r\n            },\r\n            ttAdapter: function ttAdapter() {\r\n                return _.bind(this.get, this);\r\n            }\r\n        });\r\n        return Bloodhound;\r\n        function getSorter(sortFn) {\r\n            return _.isFunction(sortFn) ? sort : noSort;\r\n            function sort(array) {\r\n                return array.sort(sortFn);\r\n            }\r\n            function noSort(array) {\r\n                return array;\r\n            }\r\n        }\r\n        function ignoreDuplicates() {\r\n            return false;\r\n        }\r\n    })(this);\r\n    var html = {\r\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\r\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\r\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\r\n        suggestions: '<span class=\"tt-suggestions\"></span>',\r\n        suggestion: '<div class=\"tt-suggestion\"></div>'\r\n    };\r\n    var css = {\r\n        wrapper: {\r\n            position: \"relative\",\r\n            display: \"inline-block\"\r\n        },\r\n        hint: {\r\n            position: \"absolute\",\r\n            top: \"0\",\r\n            left: \"0\",\r\n            borderColor: \"transparent\",\r\n            boxShadow: \"none\"\r\n        },\r\n        input: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\",\r\n            backgroundColor: \"transparent\"\r\n        },\r\n        inputWithNoHint: {\r\n            position: \"relative\",\r\n            verticalAlign: \"top\"\r\n        },\r\n        dropdown: {\r\n            position: \"absolute\",\r\n            top: \"100%\",\r\n            left: \"0\",\r\n            zIndex: \"100\",\r\n            display: \"none\"\r\n        },\r\n        suggestions: {\r\n            display: \"block\"\r\n        },\r\n        suggestion: {\r\n            whiteSpace: \"nowrap\",\r\n            cursor: \"pointer\"\r\n        },\r\n        suggestionChild: {\r\n            whiteSpace: \"normal\"\r\n        },\r\n        ltr: {\r\n            left: \"0\",\r\n            right: \"auto\"\r\n        },\r\n        rtl: {\r\n            left: \"auto\",\r\n            right: \" 0\"\r\n        }\r\n    };\r\n    if (_.isMsie()) {\r\n        _.mixin(css.input, {\r\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\r\n        });\r\n    }\r\n    if (_.isMsie() && _.isMsie() <= 7) {\r\n        _.mixin(css.input, {\r\n            marginTop: \"-1px\"\r\n        });\r\n    }\r\n    var EventBus = function() {\r\n        var namespace = \"typeahead:\";\r\n        function EventBus(o) {\r\n            if (!o || !o.el) {\r\n                $.error(\"EventBus initialized without el\");\r\n            }\r\n            this.$el = $(o.el);\r\n        }\r\n        _.mixin(EventBus.prototype, {\r\n            trigger: function(type) {\r\n                var args = [].slice.call(arguments, 1);\r\n                this.$el.trigger(namespace + type, args);\r\n            }\r\n        });\r\n        return EventBus;\r\n    }();\r\n    var EventEmitter = function() {\r\n        var splitter = /\\s+/, nextTick = getNextTick();\r\n        return {\r\n            onSync: onSync,\r\n            onAsync: onAsync,\r\n            off: off,\r\n            trigger: trigger\r\n        };\r\n        function on(method, types, cb, context) {\r\n            var type;\r\n            if (!cb) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            cb = context ? bindContext(cb, context) : cb;\r\n            this._callbacks = this._callbacks || {};\r\n            while (type = types.shift()) {\r\n                this._callbacks[type] = this._callbacks[type] || {\r\n                    sync: [],\r\n                    async: []\r\n                };\r\n                this._callbacks[type][method].push(cb);\r\n            }\r\n            return this;\r\n        }\r\n        function onAsync(types, cb, context) {\r\n            return on.call(this, \"async\", types, cb, context);\r\n        }\r\n        function onSync(types, cb, context) {\r\n            return on.call(this, \"sync\", types, cb, context);\r\n        }\r\n        function off(types) {\r\n            var type;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            while (type = types.shift()) {\r\n                delete this._callbacks[type];\r\n            }\r\n            return this;\r\n        }\r\n        function trigger(types) {\r\n            var type, callbacks, args, syncFlush, asyncFlush;\r\n            if (!this._callbacks) {\r\n                return this;\r\n            }\r\n            types = types.split(splitter);\r\n            args = [].slice.call(arguments, 1);\r\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\r\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\r\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\r\n                syncFlush() && nextTick(asyncFlush);\r\n            }\r\n            return this;\r\n        }\r\n        function getFlush(callbacks, context, args) {\r\n            return flush;\r\n            function flush() {\r\n                var cancelled;\r\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\r\n                    cancelled = callbacks[i].apply(context, args) === false;\r\n                }\r\n                return !cancelled;\r\n            }\r\n        }\r\n        function getNextTick() {\r\n            var nextTickFn;\r\n            if (window.setImmediate) {\r\n                nextTickFn = function nextTickSetImmediate(fn) {\r\n                    setImmediate(function() {\r\n                        fn();\r\n                    });\r\n                };\r\n            } else {\r\n                nextTickFn = function nextTickSetTimeout(fn) {\r\n                    setTimeout(function() {\r\n                        fn();\r\n                    }, 0);\r\n                };\r\n            }\r\n            return nextTickFn;\r\n        }\r\n        function bindContext(fn, context) {\r\n            return fn.bind ? fn.bind(context) : function() {\r\n                fn.apply(context, [].slice.call(arguments, 0));\r\n            };\r\n        }\r\n    }();\r\n    var highlight = function(doc) {\r\n        var defaults = {\r\n            node: null,\r\n            pattern: null,\r\n            tagName: \"strong\",\r\n            className: null,\r\n            wordsOnly: false,\r\n            caseSensitive: false\r\n        };\r\n        return function hightlight(o) {\r\n            var regex;\r\n            o = _.mixin({}, defaults, o);\r\n            if (!o.node || !o.pattern) {\r\n                return;\r\n            }\r\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\r\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\r\n            traverse(o.node, hightlightTextNode);\r\n            function hightlightTextNode(textNode) {\r\n                var match, patternNode;\r\n                if (match = regex.exec(textNode.data)) {\r\n                    wrapperNode = doc.createElement(o.tagName);\r\n                    o.className && (wrapperNode.className = o.className);\r\n                    patternNode = textNode.splitText(match.index);\r\n                    patternNode.splitText(match[0].length);\r\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\r\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\r\n                }\r\n                return !!match;\r\n            }\r\n            function traverse(el, hightlightTextNode) {\r\n                var childNode, TEXT_NODE_TYPE = 3;\r\n                for (var i = 0; i < el.childNodes.length; i++) {\r\n                    childNode = el.childNodes[i];\r\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\r\n                        i += hightlightTextNode(childNode) ? 1 : 0;\r\n                    } else {\r\n                        traverse(childNode, hightlightTextNode);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        function getRegex(patterns, caseSensitive, wordsOnly) {\r\n            var escapedPatterns = [], regexStr;\r\n            for (var i = 0; i < patterns.length; i++) {\r\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\r\n            }\r\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\r\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\r\n        }\r\n    }(window.document);\r\n    var Input = function() {\r\n        var specialKeyCodeMap;\r\n        specialKeyCodeMap = {\r\n            9: \"tab\",\r\n            27: \"esc\",\r\n            37: \"left\",\r\n            39: \"right\",\r\n            13: \"enter\",\r\n            38: \"up\",\r\n            40: \"down\"\r\n        };\r\n        function Input(o) {\r\n            var that = this, onBlur, onFocus, onKeydown, onInput;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"input is missing\");\r\n            }\r\n            onBlur = _.bind(this._onBlur, this);\r\n            onFocus = _.bind(this._onFocus, this);\r\n            onKeydown = _.bind(this._onKeydown, this);\r\n            onInput = _.bind(this._onInput, this);\r\n            this.$hint = $(o.hint);\r\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\r\n            if (this.$hint.length === 0) {\r\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\r\n            }\r\n            if (!_.isMsie()) {\r\n                this.$input.on(\"input.tt\", onInput);\r\n            } else {\r\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\r\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\r\n                        return;\r\n                    }\r\n                    _.defer(_.bind(that._onInput, that, $e));\r\n                });\r\n            }\r\n            this.query = this.$input.val();\r\n            this.$overflowHelper = buildOverflowHelper(this.$input);\r\n        }\r\n        Input.normalizeQuery = function(str) {\r\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\r\n        };\r\n        _.mixin(Input.prototype, EventEmitter, {\r\n            _onBlur: function onBlur() {\r\n                this.resetInputValue();\r\n                this.trigger(\"blurred\");\r\n            },\r\n            _onFocus: function onFocus() {\r\n                this.trigger(\"focused\");\r\n            },\r\n            _onKeydown: function onKeydown($e) {\r\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\r\n                this._managePreventDefault(keyName, $e);\r\n                if (keyName && this._shouldTrigger(keyName, $e)) {\r\n                    this.trigger(keyName + \"Keyed\", $e);\r\n                }\r\n            },\r\n            _onInput: function onInput() {\r\n                this._checkInputValue();\r\n            },\r\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\r\n                var preventDefault, hintValue, inputValue;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    hintValue = this.getHint();\r\n                    inputValue = this.getInputValue();\r\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\r\n                    break;\r\n\r\n                  case \"up\":\r\n                  case \"down\":\r\n                    preventDefault = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    preventDefault = false;\r\n                }\r\n                preventDefault && $e.preventDefault();\r\n            },\r\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\r\n                var trigger;\r\n                switch (keyName) {\r\n                  case \"tab\":\r\n                    trigger = !withModifier($e);\r\n                    break;\r\n\r\n                  default:\r\n                    trigger = true;\r\n                }\r\n                return trigger;\r\n            },\r\n            _checkInputValue: function checkInputValue() {\r\n                var inputValue, areEquivalent, hasDifferentWhitespace;\r\n                inputValue = this.getInputValue();\r\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\r\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\r\n                if (!areEquivalent) {\r\n                    this.trigger(\"queryChanged\", this.query = inputValue);\r\n                } else if (hasDifferentWhitespace) {\r\n                    this.trigger(\"whitespaceChanged\", this.query);\r\n                }\r\n            },\r\n            focus: function focus() {\r\n                this.$input.focus();\r\n            },\r\n            blur: function blur() {\r\n                this.$input.blur();\r\n            },\r\n            getQuery: function getQuery() {\r\n                return this.query;\r\n            },\r\n            setQuery: function setQuery(query) {\r\n                this.query = query;\r\n            },\r\n            getInputValue: function getInputValue() {\r\n                return this.$input.val();\r\n            },\r\n            setInputValue: function setInputValue(value, silent) {\r\n                this.$input.val(value);\r\n                silent ? this.clearHint() : this._checkInputValue();\r\n            },\r\n            resetInputValue: function resetInputValue() {\r\n                this.setInputValue(this.query, true);\r\n            },\r\n            getHint: function getHint() {\r\n                return this.$hint.val();\r\n            },\r\n            setHint: function setHint(value) {\r\n                this.$hint.val(value);\r\n            },\r\n            clearHint: function clearHint() {\r\n                this.setHint(\"\");\r\n            },\r\n            clearHintIfInvalid: function clearHintIfInvalid() {\r\n                var val, hint, valIsPrefixOfHint, isValid;\r\n                val = this.getInputValue();\r\n                hint = this.getHint();\r\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\r\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\r\n                !isValid && this.clearHint();\r\n            },\r\n            getLanguageDirection: function getLanguageDirection() {\r\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\r\n            },\r\n            hasOverflow: function hasOverflow() {\r\n                var constraint = this.$input.width() - 2;\r\n                this.$overflowHelper.text(this.getInputValue());\r\n                return this.$overflowHelper.width() >= constraint;\r\n            },\r\n            isCursorAtEnd: function() {\r\n                var valueLength, selectionStart, range;\r\n                valueLength = this.$input.val().length;\r\n                selectionStart = this.$input[0].selectionStart;\r\n                if (_.isNumber(selectionStart)) {\r\n                    return selectionStart === valueLength;\r\n                } else if (document.selection) {\r\n                    range = document.selection.createRange();\r\n                    range.moveStart(\"character\", -valueLength);\r\n                    return valueLength === range.text.length;\r\n                }\r\n                return true;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$hint.off(\".tt\");\r\n                this.$input.off(\".tt\");\r\n                this.$hint = this.$input = this.$overflowHelper = null;\r\n            }\r\n        });\r\n        return Input;\r\n        function buildOverflowHelper($input) {\r\n            return $('<pre aria-hidden=\"true\"></pre>').css({\r\n                position: \"absolute\",\r\n                visibility: \"hidden\",\r\n                whiteSpace: \"pre\",\r\n                fontFamily: $input.css(\"font-family\"),\r\n                fontSize: $input.css(\"font-size\"),\r\n                fontStyle: $input.css(\"font-style\"),\r\n                fontVariant: $input.css(\"font-variant\"),\r\n                fontWeight: $input.css(\"font-weight\"),\r\n                wordSpacing: $input.css(\"word-spacing\"),\r\n                letterSpacing: $input.css(\"letter-spacing\"),\r\n                textIndent: $input.css(\"text-indent\"),\r\n                textRendering: $input.css(\"text-rendering\"),\r\n                textTransform: $input.css(\"text-transform\")\r\n            }).insertAfter($input);\r\n        }\r\n        function areQueriesEquivalent(a, b) {\r\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\r\n        }\r\n        function withModifier($e) {\r\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\r\n        }\r\n    }();\r\n    var Dataset = function() {\r\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\r\n        function Dataset(o) {\r\n            o = o || {};\r\n            o.templates = o.templates || {};\r\n            if (!o.source) {\r\n                $.error(\"missing source\");\r\n            }\r\n            if (o.name && !isValidName(o.name)) {\r\n                $.error(\"invalid dataset name: \" + o.name);\r\n            }\r\n            this.query = null;\r\n            this.highlight = !!o.highlight;\r\n            this.name = o.name || _.getUniqueId();\r\n            this.source = o.source;\r\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\r\n            this.templates = getTemplates(o.templates, this.displayFn);\r\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\r\n        }\r\n        Dataset.extractDatasetName = function extractDatasetName(el) {\r\n            return $(el).data(datasetKey);\r\n        };\r\n        Dataset.extractValue = function extractDatum(el) {\r\n            return $(el).data(valueKey);\r\n        };\r\n        Dataset.extractDatum = function extractDatum(el) {\r\n            return $(el).data(datumKey);\r\n        };\r\n        _.mixin(Dataset.prototype, EventEmitter, {\r\n            _render: function render(query, suggestions) {\r\n                if (!this.$el) {\r\n                    return;\r\n                }\r\n                var that = this, hasSuggestions;\r\n                this.$el.empty();\r\n                hasSuggestions = suggestions && suggestions.length;\r\n                if (!hasSuggestions && this.templates.empty) {\r\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                } else if (hasSuggestions) {\r\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\r\n                }\r\n                this.trigger(\"rendered\");\r\n                function getEmptyHtml() {\r\n                    return that.templates.empty({\r\n                        query: query,\r\n                        isEmpty: true\r\n                    });\r\n                }\r\n                function getSuggestionsHtml() {\r\n                    var $suggestions, nodes;\r\n                    $suggestions = $(html.suggestions).css(css.suggestions);\r\n                    nodes = _.map(suggestions, getSuggestionNode);\r\n                    $suggestions.append.apply($suggestions, nodes);\r\n                    that.highlight && highlight({\r\n                        node: $suggestions[0],\r\n                        pattern: query\r\n                    });\r\n                    return $suggestions;\r\n                    function getSuggestionNode(suggestion) {\r\n                        var $el;\r\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\r\n                        $el.children().each(function() {\r\n                            $(this).css(css.suggestionChild);\r\n                        });\r\n                        return $el;\r\n                    }\r\n                }\r\n                function getHeaderHtml() {\r\n                    return that.templates.header({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n                function getFooterHtml() {\r\n                    return that.templates.footer({\r\n                        query: query,\r\n                        isEmpty: !hasSuggestions\r\n                    });\r\n                }\r\n            },\r\n            getRoot: function getRoot() {\r\n                return this.$el;\r\n            },\r\n            update: function update(query) {\r\n                var that = this;\r\n                this.query = query;\r\n                this.canceled = false;\r\n                this.source(query, render);\r\n                function render(suggestions) {\r\n                    if (!that.canceled && query === that.query) {\r\n                        that._render(query, suggestions);\r\n                    }\r\n                }\r\n            },\r\n            cancel: function cancel() {\r\n                this.canceled = true;\r\n            },\r\n            clear: function clear() {\r\n                this.cancel();\r\n                this.$el.empty();\r\n                this.trigger(\"rendered\");\r\n            },\r\n            isEmpty: function isEmpty() {\r\n                return this.$el.is(\":empty\");\r\n            },\r\n            destroy: function destroy() {\r\n                this.$el = null;\r\n            }\r\n        });\r\n        return Dataset;\r\n        function getDisplayFn(display) {\r\n            display = display || \"value\";\r\n            return _.isFunction(display) ? display : displayFn;\r\n            function displayFn(obj) {\r\n                return obj[display];\r\n            }\r\n        }\r\n        function getTemplates(templates, displayFn) {\r\n            return {\r\n                empty: templates.empty && _.templatify(templates.empty),\r\n                header: templates.header && _.templatify(templates.header),\r\n                footer: templates.footer && _.templatify(templates.footer),\r\n                suggestion: templates.suggestion || suggestionTemplate\r\n            };\r\n            function suggestionTemplate(context) {\r\n                return \"<p>\" + displayFn(context) + \"</p>\";\r\n            }\r\n        }\r\n        function isValidName(str) {\r\n            return /^[_a-zA-Z0-9-]+$/.test(str);\r\n        }\r\n    }();\r\n    var Dropdown = function() {\r\n        function Dropdown(o) {\r\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\r\n            o = o || {};\r\n            if (!o.menu) {\r\n                $.error(\"menu is required\");\r\n            }\r\n            this.isOpen = false;\r\n            this.isEmpty = true;\r\n            this.datasets = _.map(o.datasets, initializeDataset);\r\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\r\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\r\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\r\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\r\n            _.each(this.datasets, function(dataset) {\r\n                that.$menu.append(dataset.getRoot());\r\n                dataset.onSync(\"rendered\", that._onRendered, that);\r\n            });\r\n        }\r\n        _.mixin(Dropdown.prototype, EventEmitter, {\r\n            _onSuggestionClick: function onSuggestionClick($e) {\r\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\r\n            },\r\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\r\n                this._removeCursor();\r\n                this._setCursor($($e.currentTarget), true);\r\n            },\r\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\r\n                this._removeCursor();\r\n            },\r\n            _onRendered: function onRendered() {\r\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\r\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\r\n                this.trigger(\"datasetRendered\");\r\n                function isDatasetEmpty(dataset) {\r\n                    return dataset.isEmpty();\r\n                }\r\n            },\r\n            _hide: function() {\r\n                this.$menu.hide();\r\n            },\r\n            _show: function() {\r\n                this.$menu.css(\"display\", \"block\");\r\n            },\r\n            _getSuggestions: function getSuggestions() {\r\n                return this.$menu.find(\".tt-suggestion\");\r\n            },\r\n            _getCursor: function getCursor() {\r\n                return this.$menu.find(\".tt-cursor\").first();\r\n            },\r\n            _setCursor: function setCursor($el, silent) {\r\n                $el.first().addClass(\"tt-cursor\");\r\n                !silent && this.trigger(\"cursorMoved\");\r\n            },\r\n            _removeCursor: function removeCursor() {\r\n                this._getCursor().removeClass(\"tt-cursor\");\r\n            },\r\n            _moveCursor: function moveCursor(increment) {\r\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\r\n                if (!this.isOpen) {\r\n                    return;\r\n                }\r\n                $oldCursor = this._getCursor();\r\n                $suggestions = this._getSuggestions();\r\n                this._removeCursor();\r\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\r\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\r\n                if (newCursorIndex === -1) {\r\n                    this.trigger(\"cursorRemoved\");\r\n                    return;\r\n                } else if (newCursorIndex < -1) {\r\n                    newCursorIndex = $suggestions.length - 1;\r\n                }\r\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\r\n                this._ensureVisible($newCursor);\r\n            },\r\n            _ensureVisible: function ensureVisible($el) {\r\n                var elTop, elBottom, menuScrollTop, menuHeight;\r\n                elTop = $el.position().top;\r\n                elBottom = elTop + $el.outerHeight(true);\r\n                menuScrollTop = this.$menu.scrollTop();\r\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\r\n                if (elTop < 0) {\r\n                    this.$menu.scrollTop(menuScrollTop + elTop);\r\n                } else if (menuHeight < elBottom) {\r\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\r\n                }\r\n            },\r\n            close: function close() {\r\n                if (this.isOpen) {\r\n                    this.isOpen = false;\r\n                    this._removeCursor();\r\n                    this._hide();\r\n                    this.trigger(\"closed\");\r\n                }\r\n            },\r\n            open: function open() {\r\n                if (!this.isOpen) {\r\n                    this.isOpen = true;\r\n                    !this.isEmpty && this._show();\r\n                    this.trigger(\"opened\");\r\n                }\r\n            },\r\n            setLanguageDirection: function setLanguageDirection(dir) {\r\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\r\n            },\r\n            moveCursorUp: function moveCursorUp() {\r\n                this._moveCursor(-1);\r\n            },\r\n            moveCursorDown: function moveCursorDown() {\r\n                this._moveCursor(+1);\r\n            },\r\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\r\n                var datum = null;\r\n                if ($el.length) {\r\n                    datum = {\r\n                        raw: Dataset.extractDatum($el),\r\n                        value: Dataset.extractValue($el),\r\n                        datasetName: Dataset.extractDatasetName($el)\r\n                    };\r\n                }\r\n                return datum;\r\n            },\r\n            getDatumForCursor: function getDatumForCursor() {\r\n                return this.getDatumForSuggestion(this._getCursor().first());\r\n            },\r\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\r\n                return this.getDatumForSuggestion(this._getSuggestions().first());\r\n            },\r\n            update: function update(query) {\r\n                _.each(this.datasets, updateDataset);\r\n                function updateDataset(dataset) {\r\n                    dataset.update(query);\r\n                }\r\n            },\r\n            empty: function empty() {\r\n                _.each(this.datasets, clearDataset);\r\n                this.isEmpty = true;\r\n                function clearDataset(dataset) {\r\n                    dataset.clear();\r\n                }\r\n            },\r\n            isVisible: function isVisible() {\r\n                return this.isOpen && !this.isEmpty;\r\n            },\r\n            destroy: function destroy() {\r\n                this.$menu.off(\".tt\");\r\n                this.$menu = null;\r\n                _.each(this.datasets, destroyDataset);\r\n                function destroyDataset(dataset) {\r\n                    dataset.destroy();\r\n                }\r\n            }\r\n        });\r\n        return Dropdown;\r\n        function initializeDataset(oDataset) {\r\n            return new Dataset(oDataset);\r\n        }\r\n    }();\r\n    var Typeahead = function() {\r\n        var attrsKey = \"ttAttrs\";\r\n        function Typeahead(o) {\r\n            var $menu, $input, $hint;\r\n            o = o || {};\r\n            if (!o.input) {\r\n                $.error(\"missing input\");\r\n            }\r\n            this.isActivated = false;\r\n            this.autoselect = !!o.autoselect;\r\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\r\n            this.$node = buildDomStructure(o.input, o.withHint);\r\n            $menu = this.$node.find(\".tt-dropdown-menu\");\r\n            $input = this.$node.find(\".tt-input\");\r\n            $hint = this.$node.find(\".tt-hint\");\r\n            $input.on(\"blur.tt\", function($e) {\r\n                var active, isActive, hasActive;\r\n                active = document.activeElement;\r\n                isActive = $menu.is(active);\r\n                hasActive = $menu.has(active).length > 0;\r\n                if (_.isMsie() && (isActive || hasActive)) {\r\n                    $e.preventDefault();\r\n                    $e.stopImmediatePropagation();\r\n                    _.defer(function() {\r\n                        $input.focus();\r\n                    });\r\n                }\r\n            });\r\n            $menu.on(\"mousedown.tt\", function($e) {\r\n                $e.preventDefault();\r\n            });\r\n            this.eventBus = o.eventBus || new EventBus({\r\n                el: $input\r\n            });\r\n            this.dropdown = new Dropdown({\r\n                menu: $menu,\r\n                datasets: o.datasets\r\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\r\n            this.input = new Input({\r\n                input: $input,\r\n                hint: $hint\r\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\r\n            this._setLanguageDirection();\r\n        }\r\n        _.mixin(Typeahead.prototype, {\r\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\r\n                    this._select(datum);\r\n                }\r\n            },\r\n            _onCursorMoved: function onCursorMoved() {\r\n                var datum = this.dropdown.getDatumForCursor();\r\n                this.input.setInputValue(datum.value, true);\r\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\r\n            },\r\n            _onCursorRemoved: function onCursorRemoved() {\r\n                this.input.resetInputValue();\r\n                this._updateHint();\r\n            },\r\n            _onDatasetRendered: function onDatasetRendered() {\r\n                this._updateHint();\r\n            },\r\n            _onOpened: function onOpened() {\r\n                this._updateHint();\r\n                this.eventBus.trigger(\"opened\");\r\n            },\r\n            _onClosed: function onClosed() {\r\n                this.input.clearHint();\r\n                this.eventBus.trigger(\"closed\");\r\n            },\r\n            _onFocused: function onFocused() {\r\n                this.isActivated = true;\r\n                this.dropdown.open();\r\n            },\r\n            _onBlurred: function onBlurred() {\r\n                this.isActivated = false;\r\n                this.dropdown.empty();\r\n                this.dropdown.close();\r\n                this.setVal(\"\", true); //LM\r\n            },\r\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\r\n                var cursorDatum, topSuggestionDatum;\r\n                cursorDatum = this.dropdown.getDatumForCursor();\r\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\r\n                if (cursorDatum) {\r\n                    this._select(cursorDatum);\r\n                    $e.preventDefault();\r\n                } else if (this.autoselect && topSuggestionDatum) {\r\n                    this._select(topSuggestionDatum);\r\n                    $e.preventDefault();\r\n                }\r\n            },\r\n            _onTabKeyed: function onTabKeyed(type, $e) {\r\n                var datum;\r\n                if (datum = this.dropdown.getDatumForCursor()) {\r\n                    this._select(datum);\r\n                    $e.preventDefault();\r\n                } else {\r\n                    this._autocomplete(true);\r\n                }\r\n            },\r\n            _onEscKeyed: function onEscKeyed() {\r\n                this.dropdown.close();\r\n                this.input.resetInputValue();\r\n            },\r\n            _onUpKeyed: function onUpKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\r\n                this.dropdown.open();\r\n            },\r\n            _onDownKeyed: function onDownKeyed() {\r\n                var query = this.input.getQuery();\r\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\r\n                this.dropdown.open();\r\n            },\r\n            _onLeftKeyed: function onLeftKeyed() {\r\n                this.dir === \"rtl\" && this._autocomplete();\r\n            },\r\n            _onRightKeyed: function onRightKeyed() {\r\n                this.dir === \"ltr\" && this._autocomplete();\r\n            },\r\n            _onQueryChanged: function onQueryChanged(e, query) {\r\n                this.input.clearHintIfInvalid();\r\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\r\n                this.dropdown.open();\r\n                this._setLanguageDirection();\r\n            },\r\n            _onWhitespaceChanged: function onWhitespaceChanged() {\r\n                this._updateHint();\r\n                this.dropdown.open();\r\n            },\r\n            _setLanguageDirection: function setLanguageDirection() {\r\n                var dir;\r\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\r\n                    this.dir = dir;\r\n                    this.$node.css(\"direction\", dir);\r\n                    this.dropdown.setLanguageDirection(dir);\r\n                }\r\n            },\r\n            _updateHint: function updateHint() {\r\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\r\n                datum = this.dropdown.getDatumForTopSuggestion();\r\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\r\n                    val = this.input.getInputValue();\r\n                    query = Input.normalizeQuery(val);\r\n                    escapedQuery = _.escapeRegExChars(query);\r\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\r\n                    match = frontMatchRegEx.exec(datum.value);\r\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\r\n                } else {\r\n                    this.input.clearHint();\r\n                }\r\n            },\r\n            _autocomplete: function autocomplete(laxCursor) {\r\n                var hint, query, isCursorAtEnd, datum;\r\n                hint = this.input.getHint();\r\n                query = this.input.getQuery();\r\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\r\n                if (hint && query !== hint && isCursorAtEnd) {\r\n                    datum = this.dropdown.getDatumForTopSuggestion();\r\n                    datum && this.input.setInputValue(datum.value);\r\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\r\n                }\r\n            },\r\n            _select: function select(datum) {\r\n                this.input.setQuery(datum.value);\r\n                this.input.setInputValue(datum.value, true);\r\n                this._setLanguageDirection();\r\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\r\n                this.dropdown.close();\r\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\r\n            },\r\n            open: function open() {\r\n                this.dropdown.open();\r\n            },\r\n            close: function close() {\r\n                this.dropdown.close();\r\n            },\r\n            setVal: function setVal(val) {\r\n                if (this.isActivated) {\r\n                    this.input.setInputValue(val);\r\n                } else {\r\n                    this.input.setQuery(val);\r\n                    this.input.setInputValue(val, true);\r\n                }\r\n                this._setLanguageDirection();\r\n            },\r\n            getVal: function getVal() {\r\n                return this.input.getQuery();\r\n            },\r\n            destroy: function destroy() {\r\n                this.input.destroy();\r\n                this.dropdown.destroy();\r\n                destroyDomStructure(this.$node);\r\n                this.$node = null;\r\n            }\r\n        });\r\n        return Typeahead;\r\n        function buildDomStructure(input, withHint) {\r\n            var $input, $wrapper, $dropdown, $hint;\r\n            $input = $(input);\r\n            $wrapper = $(html.wrapper).css(css.wrapper);\r\n            $dropdown = $(html.dropdown).css(css.dropdown);\r\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\r\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: \"false\"\r\n            });\r\n            $input.data(attrsKey, {\r\n                dir: $input.attr(\"dir\"),\r\n                autocomplete: $input.attr(\"autocomplete\"),\r\n                spellcheck: $input.attr(\"spellcheck\"),\r\n                style: $input.attr(\"style\")\r\n            });\r\n            $input.addClass(\"tt-input\").attr({\r\n                autocomplete: \"off\",\r\n                spellcheck: false\r\n            }).css(withHint ? css.input : css.inputWithNoHint);\r\n            try {\r\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\r\n            } catch (e) {}\r\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\r\n        }\r\n        function getBackgroundStyles($el) {\r\n            return {\r\n                backgroundAttachment: $el.css(\"background-attachment\"),\r\n                backgroundClip: $el.css(\"background-clip\"),\r\n                backgroundColor: $el.css(\"background-color\"),\r\n                backgroundImage: $el.css(\"background-image\"),\r\n                backgroundOrigin: $el.css(\"background-origin\"),\r\n                backgroundPosition: $el.css(\"background-position\"),\r\n                backgroundRepeat: $el.css(\"background-repeat\"),\r\n                backgroundSize: $el.css(\"background-size\")\r\n            };\r\n        }\r\n        function destroyDomStructure($node) {\r\n            var $input = $node.find(\".tt-input\");\r\n            _.each($input.data(attrsKey), function(val, key) {\r\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\r\n            });\r\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\r\n            $node.remove();\r\n        }\r\n    }();\r\n    (function() {\r\n        var old, typeaheadKey, methods;\r\n        old = $.fn.typeahead;\r\n        typeaheadKey = \"ttTypeahead\";\r\n        methods = {\r\n            initialize: function initialize(o, datasets) {\r\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\r\n                o = o || {};\r\n                return this.each(attach);\r\n                function attach() {\r\n                    var $input = $(this), eventBus, typeahead;\r\n                    _.each(datasets, function(d) {\r\n                        d.highlight = !!o.highlight;\r\n                    });\r\n                    typeahead = new Typeahead({\r\n                        input: $input,\r\n                        eventBus: eventBus = new EventBus({\r\n                            el: $input\r\n                        }),\r\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\r\n                        minLength: o.minLength,\r\n                        autoselect: o.autoselect,\r\n                        datasets: datasets\r\n                    });\r\n                    $input.data(typeaheadKey, typeahead);\r\n                }\r\n            },\r\n            open: function open() {\r\n                return this.each(openTypeahead);\r\n                function openTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.open();\r\n                    }\r\n                }\r\n            },\r\n            close: function close() {\r\n                return this.each(closeTypeahead);\r\n                function closeTypeahead() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.close();\r\n                    }\r\n                }\r\n            },\r\n            val: function val(newVal) {\r\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\r\n                function setVal() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.setVal(newVal);\r\n                    }\r\n                }\r\n                function getVal($input) {\r\n                    var typeahead, query;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        query = typeahead.getVal();\r\n                    }\r\n                    return query;\r\n                }\r\n            },\r\n            destroy: function destroy() {\r\n                return this.each(unattach);\r\n                function unattach() {\r\n                    var $input = $(this), typeahead;\r\n                    if (typeahead = $input.data(typeaheadKey)) {\r\n                        typeahead.destroy();\r\n                        $input.removeData(typeaheadKey);\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        $.fn.typeahead = function(method) {\r\n            if (methods[method]) {\r\n                return methods[method].apply(this, [].slice.call(arguments, 1));\r\n            } else {\r\n                return methods.initialize.apply(this, arguments);\r\n            }\r\n        };\r\n        $.fn.typeahead.noConflict = function noConflict() {\r\n            $.fn.typeahead = old;\r\n            return this;\r\n        };\r\n    })();\r\n    \r\n    \r\n    \r\n//})(window.jQuery);\r\n\r\n\r\n});\n",
        -    "define('searchView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/search.html',\r\n  'text!tpl/search_suggestion.html',\r\n  // Tools\r\n  'typeahead'\r\n], function(App, searchTpl, suggestionTpl) {\r\n\r\n  var searchView = Backbone.View.extend({\r\n    el: '#search',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      var tpl = _.template(searchTpl);\r\n      var className = 'form-control input-lg';\r\n      var placeholder = 'Search reference';\r\n      this.searchHtml = tpl({\r\n        'placeholder': placeholder,\r\n        'className': className\r\n      });\r\n      this.items = App.classes.concat(App.allItems);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render input field with Typehead activated.\r\n     */\r\n    render: function() {\r\n      // Append the view to the dom\r\n      this.$el.append(this.searchHtml);\r\n\r\n      // Render Typeahead\r\n      var $searchInput = this.$el.find('input[type=text]');\r\n      this.typeaheadRender($searchInput);\r\n      this.typeaheadEvents($searchInput);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Apply Twitter Typeahead to the search input field.\r\n     * @param {jquery} $input\r\n     */\r\n    typeaheadRender: function($input) {\r\n      var self = this;\r\n      $input.typeahead(null, {\r\n        'displayKey': 'name',\r\n        'minLength': 2,\r\n        //'highlight': true,\r\n        'source': self.substringMatcher(this.items),\r\n        'templates': {\r\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\r\n          'suggestion': _.template(suggestionTpl)\r\n        }\r\n      });\r\n    },\r\n    /**\r\n     * Setup typeahead custom events (item selected).\r\n     */\r\n    typeaheadEvents: function($input) {\r\n      var self = this;\r\n      $input.on('typeahead:selected', function(e, item, datasetName) {\r\n        var selectedItem = self.items[item.idx];\r\n        select(selectedItem);\r\n      });\r\n      $input.on('keydown', function(e) {\r\n        if (e.which === 13) { // enter\r\n          var txt = $input.val();\r\n          var f = _.find(self.items, function(it) { return it.name == txt; });\r\n          if (f) {\r\n            select(f);\r\n          }\r\n        } else if (e.which === 27) {\r\n          $input.blur();\r\n        }\r\n      });\r\n\r\n      function select(selectedItem) {\r\n        var hash = App.router.getHash(selectedItem);//\r\n        App.router.navigate(hash, {'trigger': true});\r\n        $('#item').focus();\r\n      }\r\n    },\r\n    /**\r\n     * substringMatcher function for Typehead (search for strings in an array).\r\n     * @param {array} array\r\n     * @returns {Function}\r\n     */\r\n    substringMatcher: function(array) {\r\n      return function findMatches(query, callback) {\r\n        var matches = [], substrRegex, arrayLength = array.length;\r\n\r\n        // regex used to determine if a string contains the substring `query`\r\n        substrRegex = new RegExp(query, 'i');\r\n\r\n        // iterate through the pool of strings and for any string that\r\n        // contains the substring `query`, add it to the `matches` array\r\n        for (var i=0; i < arrayLength; i++) {\r\n          var item = array[i];\r\n          if (substrRegex.test(item.name)) {\r\n            // typeahead expects suggestions to be a js object\r\n            matches.push({\r\n              'itemtype': item.itemtype,\r\n              'name': item.name,\r\n              'className': item.class,\r\n              'is_constructor': !!item.is_constructor,\r\n              'final': item.final,\r\n              'idx': i\r\n            });\r\n          }\r\n        }\r\n\r\n        callback(matches);\r\n      };\r\n    }\r\n\r\n  });\r\n\r\n  return searchView;\r\n\r\n});\r\n\n",
        -    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\r\\n  <div class=\"reference-group clearfix main-ref-page\">  \\r\\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\r\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\r\\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\r\\n      <div class=\"reference-subgroup\">\\r\\n        <% if (subgroup.name !== \\'0\\') { %>\\r\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\r\\n        <% } %>\\r\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\r\\n        <% _.each(subgroup.items, function(item) { %>\\r\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\r\\n        <% }); %>\\r\\n        </ul>\\r\\n      </div>\\r\\n    <% }); %>\\r\\n    </div>\\r\\n  </div>\\r\\n<% }); %>\\r\\n';});\n\n",
        -    "define('listView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/list.html'\r\n], function (App, listTpl) {\r\n  var striptags = function(html) {\r\n    var div = document.createElement('div');\r\n    div.innerHTML = html;\r\n    return div.textContent;\r\n  };\r\n\r\n  var listView = Backbone.View.extend({\r\n    el: '#list',\r\n    events: {},\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function () {\r\n      this.listTpl = _.template(listTpl);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render the list.\r\n     */\r\n    render: function (items, listCollection) {\r\n      if (items && listCollection) {\r\n        var self = this;\r\n\r\n        // Render items and group them by module\r\n        // module === group\r\n        this.groups = {};\r\n        _.each(items, function (item, i) {\r\n\r\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n\r\n            var group = item.module || '_';\r\n            var subgroup = item.submodule || '_';\r\n            if (group === subgroup) {\r\n              subgroup = '0';\r\n            }\r\n            var hash = App.router.getHash(item);\r\n\r\n            // fixes broken links for #/p5/> and #/p5/>=\r\n            item.hash = item.hash.replace('>', '&gt;');\r\n\r\n            // Create a group list\r\n            if (!self.groups[group]) {\r\n              self.groups[group] = {\r\n                name: group.replace('_', '&nbsp;'),\r\n                subgroups: {}\r\n              };\r\n            }\r\n\r\n            // Create a subgroup list\r\n            if (!self.groups[group].subgroups[subgroup]) {\r\n              self.groups[group].subgroups[subgroup] = {\r\n                name: subgroup.replace('_', '&nbsp;'),\r\n                items: []\r\n              };\r\n            }\r\n\r\n            // hide the un-interesting constants\r\n            if (group === 'Constants' && !item.example)\r\n              return;\r\n\r\n            if (item.class === 'p5') {\r\n\r\n              self.groups[group].subgroups[subgroup].items.push(item);\r\n\r\n            } else {\r\n\r\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\r\n                function(i){ return i.name == item.class; });\r\n\r\n              if (!found) {\r\n\r\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\r\n                var ind = hash.lastIndexOf('/');\r\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\r\n                self.groups[group].subgroups[subgroup].items.push({\r\n                  name: item.class,\r\n                  hash: hash\r\n                });\r\n              }\r\n\r\n            }\r\n          }\r\n        });\r\n\r\n        // Put the <li> items html into the list <ul>\r\n        var listHtml = self.listTpl({\r\n          'striptags': striptags,\r\n          'title': self.capitalizeFirst(listCollection),\r\n          'groups': self.groups,\r\n          'listCollection': listCollection\r\n        });\r\n\r\n        // Render the view\r\n        this.$el.html(listHtml);\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a list of items.\r\n     * @param {array} items Array of item objects.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function (listGroup) {\r\n      if (App[listGroup]) {\r\n        this.render(App[listGroup], listGroup);\r\n      }\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function (str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n\r\n\r\n\r\n  });\r\n\r\n  return listView;\r\n\r\n});\r\n\n",
        -    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\r\\n\\r\\n<% if (item.example) { %>\\r\\n<div class=\"example\">\\r\\n  <h3 id=\"reference-example\">Examples</h3>\\r\\n\\r\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\r\\n    <% _.each(item.example, function(example, i){ %>\\r\\n      <%= example %>\\r\\n    <% }); %>\\r\\n  </div>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<div class=\"description\">\\r\\n    \\r\\n  <h3 id=\"reference-description\">Description</h3>\\r\\n\\r\\n  <% if (item.deprecated) { %>\\r\\n    <p>\\r\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n      \\r\\n\\r\\n  <span class=\\'description-text\\'><%= item.description %></span>\\r\\n\\r\\n  <% if (item.extends) { %>\\r\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.module === \\'p5.sound\\') { %>\\r\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\r\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\r\\n    </p>\\r\\n  <% } %>\\r\\n\\r\\n  <% if (item.constRefs) { %>\\r\\n    <p>Used by:\\r\\n  <%\\r\\n      var refs = item.constRefs;\\r\\n      for (var i = 0; i < refs.length; i ++) {\\r\\n        var ref = refs[i];\\r\\n        var name = ref;\\r\\n        if (name.substr(0, 3) === \\'p5.\\') {\\r\\n          name = name.substr(3);\\r\\n        }\\r\\n  if (i !== 0) {\\r\\n          if (i == refs.length - 1) {\\r\\n            %> and <%\\r\\n          } else {\\r\\n            %>, <%\\r\\n          }\\r\\n        }\\r\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\r\\n      }\\r\\n  %>\\r\\n    </p>\\r\\n  <% } %>\\r\\n</div>\\r\\n\\r\\n<% if (isConstructor || !isClass) { %>\\r\\n\\r\\n<div>\\r\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\r\\n  <p>\\r\\n    <% syntaxes.forEach(function(syntax) { %>\\r\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\r\\n    <% }) %>\\r\\n  </p>\\r\\n</div>\\r\\n\\r\\n\\r\\n<% if (item.params) { %>\\r\\n  <div class=\"params\">\\r\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\r\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\r\\n    <% for (var i=0; i<item.params.length; i++) { %>\\r\\n      <% var p = item.params[i] %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><%=p.name%></div>\\r\\n        <% if (p.type) { %>\\r\\n          <div class=\\'paramtype\\'>\\r\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\r\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\r\\n          <% if (p.optional) { %> (Optional)<% } %>\\r\\n          </div>\\r\\n        <% } %>\\r\\n      </li>\\r\\n    <% } %>\\r\\n    </ul>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% if (item.return && item.return.type) { %>\\r\\n  <div>\\r\\n    <h3 id=\"reference-returns\">Returns</h3>\\r\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\r\\n  </div>\\r\\n<% } %>\\r\\n\\r\\n<% } %>\\r\\n';});\n\n",
        -    "\ndefine('text!tpl/class.html',[],function () { return '\\r\\n<% if (typeof constructor !== \\'undefined\\') { %>\\r\\n<div class=\"constructor\">\\r\\n  <%=constructor%>\\r\\n</div>\\r\\n<% } %>\\r\\n\\r\\n<% let fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (fields.length > 0) { %>\\r\\n  <h3 id=\\'reference-fields\\'>Fields</h3>\\r\\n  <ul aria-labelledby=\\'reference-fields\\'>\\r\\n  <% _.each(fields, function(item) { %>\\r\\n    <li>\\r\\n      <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%></a></div>\\r\\n      <div class=\\'paramtype\\'><%= item.description %></div>\\r\\n    </li>\\r\\n  <% }); %>\\r\\n  </ul>\\r\\n<% } %>\\r\\n\\r\\n<% let methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\r\\n<% if (methods.length > 0) { %>\\r\\n  <h3 id=\\'reference-methods\\'>Methods</h3>\\r\\n  <ul aria-labelledby=\\'reference-methods\\'>\\r\\n    <% _.each(methods, function(item) { %>\\r\\n      <li>\\r\\n        <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></div>\\r\\n        <div class=\\'paramtype\\'><%= item.description %></div>\\r\\n      </li>\\r\\n    <% }); %>\\r\\n  </ul>\\r\\n<% } %>\\r\\n';});\n\n",
        -    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\r\\n<br><br>\\r\\n\\r\\n<div>\\r\\n<% if (item.file && item.line) { %>\\r\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\r\\n<% } %>\\r\\n</div>\\r\\n\\r\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\r\\n<br><br>\\r\\n';});\n\n",
        -    "// Copyright (C) 2006 Google Inc.\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n//      http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n\r\n/**\r\n * @fileoverview\r\n * some functions for browser-side pretty printing of code contained in html.\r\n *\r\n * <p>\r\n * For a fairly comprehensive set of languages see the\r\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\r\n * file that came with this source.  At a minimum, the lexer should work on a\r\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\r\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\r\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\r\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\r\n * <p>\r\n * Usage: <ol>\r\n * <li> include this source file in an html page via\r\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\r\n * <li> define style rules.  See the example page for examples.\r\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\r\n *    {@code class=prettyprint.}\r\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\r\n *    printer needs to do more substantial DOM manipulations to support that, so\r\n *    some css styles may not be preserved.\r\n * </ol>\r\n * That's it.  I wanted to keep the API as simple as possible, so there's no\r\n * need to specify which language the code is in, but if you wish, you can add\r\n * another class to the {@code <pre>} or {@code <code>} element to specify the\r\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\r\n * starts with \"lang-\" followed by a file extension, specifies the file type.\r\n * See the \"lang-*.js\" files in this directory for code that implements\r\n * per-language file handlers.\r\n * <p>\r\n * Change log:<br>\r\n * cbeust, 2006/08/22\r\n * <blockquote>\r\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\r\n * </blockquote>\r\n * @requires console\r\n */\r\n\r\n// JSLint declarations\r\n/*global console, document, navigator, setTimeout, window, define */\r\n\r\n/** @define {boolean} */\r\nvar IN_GLOBAL_SCOPE = true;\r\n\r\n/**\r\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\r\n * UI events.\r\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\r\n */\r\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\r\n\r\n/**\r\n * Pretty print a chunk of code.\r\n * @param {string} sourceCodeHtml The HTML to pretty print.\r\n * @param {string} opt_langExtension The language name to use.\r\n *     Typically, a filename extension like 'cpp' or 'java'.\r\n * @param {number|boolean} opt_numberLines True to number lines,\r\n *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n * @return {string} code as html, but prettier\r\n */\r\nvar prettyPrintOne;\r\n/**\r\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n * {@code class=prettyprint} and prettify them.\r\n *\r\n * @param {Function} opt_whenDone called when prettifying is done.\r\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n *   containing all the elements to pretty print.\r\n *   Defaults to {@code document.body}.\r\n */\r\nvar prettyPrint;\r\n\r\n\r\n(function () {\r\n  var win = window;\r\n  // Keyword lists for various languages.\r\n  // We use things that coerce to strings to make them compact when minified\r\n  // and to defeat aggressive optimizers that fold large string constants.\r\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\r\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \r\n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\r\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\r\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\r\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\r\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\r\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\r\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\r\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\r\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\r\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\r\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\r\n      \"throws,transient\"];\r\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\r\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\r\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\r\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\r\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\r\n      \"var,virtual,where\"];\r\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\r\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\r\n      \"throw,true,try,unless,until,when,while,yes\";\r\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\r\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\r\n      \"Infinity,NaN\"];\r\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\r\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\r\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\r\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\r\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\r\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\r\n      \"False,True,None\"];\r\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\r\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\r\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\r\n      \"BEGIN,END\"];\r\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\r\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\r\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\r\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\r\n      \"function,in,local,set,then,until\"];\r\n  var ALL_KEYWORDS = [\r\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\r\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\r\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\r\n\r\n  // token style names.  correspond to css classes\r\n  /**\r\n   * token style for a string literal\r\n   * @const\r\n   */\r\n  var PR_STRING = 'str';\r\n  /**\r\n   * token style for a keyword\r\n   * @const\r\n   */\r\n  var PR_KEYWORD = 'kwd';\r\n  /**\r\n   * token style for a comment\r\n   * @const\r\n   */\r\n  var PR_COMMENT = 'com';\r\n  /**\r\n   * token style for a type\r\n   * @const\r\n   */\r\n  var PR_TYPE = 'typ';\r\n  /**\r\n   * token style for a literal value.  e.g. 1, null, true.\r\n   * @const\r\n   */\r\n  var PR_LITERAL = 'lit';\r\n  /**\r\n   * token style for a punctuation string.\r\n   * @const\r\n   */\r\n  var PR_PUNCTUATION = 'pun';\r\n  /**\r\n   * token style for plain text.\r\n   * @const\r\n   */\r\n  var PR_PLAIN = 'pln';\r\n\r\n  /**\r\n   * token style for an sgml tag.\r\n   * @const\r\n   */\r\n  var PR_TAG = 'tag';\r\n  /**\r\n   * token style for a markup declaration such as a DOCTYPE.\r\n   * @const\r\n   */\r\n  var PR_DECLARATION = 'dec';\r\n  /**\r\n   * token style for embedded source.\r\n   * @const\r\n   */\r\n  var PR_SOURCE = 'src';\r\n  /**\r\n   * token style for an sgml attribute name.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_NAME = 'atn';\r\n  /**\r\n   * token style for an sgml attribute value.\r\n   * @const\r\n   */\r\n  var PR_ATTRIB_VALUE = 'atv';\r\n\r\n  /**\r\n   * A class that indicates a section of markup that is not code, e.g. to allow\r\n   * embedding of line numbers within code listings.\r\n   * @const\r\n   */\r\n  var PR_NOCODE = 'nocode';\r\n\r\n  \r\n  \r\n  /**\r\n   * A set of tokens that can precede a regular expression literal in\r\n   * javascript\r\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\r\n   * has the full list, but I've removed ones that might be problematic when\r\n   * seen in languages that don't support regular expression literals.\r\n   *\r\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\r\n   * literal in a syntactically legal javascript program, and I've removed the\r\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\r\n   * as a count of inches.\r\n   *\r\n   * <p>The link above does not accurately describe EcmaScript rules since\r\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\r\n   * very well in practice.\r\n   *\r\n   * @private\r\n   * @const\r\n   */\r\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\r\n  \r\n  // CAVEAT: this does not properly handle the case where a regular\r\n  // expression immediately follows another since a regular expression may\r\n  // have flags for case-sensitivity and the like.  Having regexp tokens\r\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\r\n  // TODO: maybe style special characters inside a regexp as punctuation.\r\n\r\n  /**\r\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\r\n   * matches the union of the sets of strings matched by the input RegExp.\r\n   * Since it matches globally, if the input strings have a start-of-input\r\n   * anchor (/^.../), it is ignored for the purposes of unioning.\r\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\r\n   * @return {RegExp} a global regex.\r\n   */\r\n  function combinePrefixPatterns(regexs) {\r\n    var capturedGroupIndex = 0;\r\n  \r\n    var needToFoldCase = false;\r\n    var ignoreCase = false;\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.ignoreCase) {\r\n        ignoreCase = true;\r\n      } else if (/[a-z]/i.test(regex.source.replace(\r\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\r\n        needToFoldCase = true;\r\n        ignoreCase = false;\r\n        break;\r\n      }\r\n    }\r\n  \r\n    var escapeCharToCodeUnit = {\r\n      'b': 8,\r\n      't': 9,\r\n      'n': 0xa,\r\n      'v': 0xb,\r\n      'f': 0xc,\r\n      'r': 0xd\r\n    };\r\n  \r\n    function decodeEscape(charsetPart) {\r\n      var cc0 = charsetPart.charCodeAt(0);\r\n      if (cc0 !== 92 /* \\\\ */) {\r\n        return cc0;\r\n      }\r\n      var c1 = charsetPart.charAt(1);\r\n      cc0 = escapeCharToCodeUnit[c1];\r\n      if (cc0) {\r\n        return cc0;\r\n      } else if ('0' <= c1 && c1 <= '7') {\r\n        return parseInt(charsetPart.substring(1), 8);\r\n      } else if (c1 === 'u' || c1 === 'x') {\r\n        return parseInt(charsetPart.substring(2), 16);\r\n      } else {\r\n        return charsetPart.charCodeAt(1);\r\n      }\r\n    }\r\n  \r\n    function encodeEscape(charCode) {\r\n      if (charCode < 0x20) {\r\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\r\n      }\r\n      var ch = String.fromCharCode(charCode);\r\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\r\n          ? \"\\\\\" + ch : ch;\r\n    }\r\n  \r\n    function caseFoldCharset(charSet) {\r\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\r\n          new RegExp(\r\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\r\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\r\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\r\n              + '|\\\\\\\\[0-7]{1,2}'\r\n              + '|\\\\\\\\[\\\\s\\\\S]'\r\n              + '|-'\r\n              + '|[^-\\\\\\\\]',\r\n              'g'));\r\n      var ranges = [];\r\n      var inverse = charsetParts[0] === '^';\r\n  \r\n      var out = ['['];\r\n      if (inverse) { out.push('^'); }\r\n  \r\n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\r\n        var p = charsetParts[i];\r\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\r\n          out.push(p);\r\n        } else {\r\n          var start = decodeEscape(p);\r\n          var end;\r\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\r\n            end = decodeEscape(charsetParts[i + 2]);\r\n            i += 2;\r\n          } else {\r\n            end = start;\r\n          }\r\n          ranges.push([start, end]);\r\n          // If the range might intersect letters, then expand it.\r\n          // This case handling is too simplistic.\r\n          // It does not deal with non-latin case folding.\r\n          // It works for latin source code identifiers though.\r\n          if (!(end < 65 || start > 122)) {\r\n            if (!(end < 65 || start > 90)) {\r\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\r\n            }\r\n            if (!(end < 97 || start > 122)) {\r\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\r\n      // -> [[1, 12], [14, 14], [16, 17]]\r\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\r\n      var consolidatedRanges = [];\r\n      var lastRange = [];\r\n      for (var i = 0; i < ranges.length; ++i) {\r\n        var range = ranges[i];\r\n        if (range[0] <= lastRange[1] + 1) {\r\n          lastRange[1] = Math.max(lastRange[1], range[1]);\r\n        } else {\r\n          consolidatedRanges.push(lastRange = range);\r\n        }\r\n      }\r\n  \r\n      for (var i = 0; i < consolidatedRanges.length; ++i) {\r\n        var range = consolidatedRanges[i];\r\n        out.push(encodeEscape(range[0]));\r\n        if (range[1] > range[0]) {\r\n          if (range[1] + 1 > range[0]) { out.push('-'); }\r\n          out.push(encodeEscape(range[1]));\r\n        }\r\n      }\r\n      out.push(']');\r\n      return out.join('');\r\n    }\r\n  \r\n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\r\n      // Split into character sets, escape sequences, punctuation strings\r\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\r\n      // include any of the above.\r\n      var parts = regex.source.match(\r\n          new RegExp(\r\n              '(?:'\r\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\r\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\r\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\r\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\r\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\r\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\r\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\r\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\r\n              + ')',\r\n              'g'));\r\n      var n = parts.length;\r\n  \r\n      // Maps captured group numbers to the number they will occupy in\r\n      // the output or to -1 if that has not been determined, or to\r\n      // undefined if they need not be capturing in the output.\r\n      var capturedGroups = [];\r\n  \r\n      // Walk over and identify back references to build the capturedGroups\r\n      // mapping.\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          // groups are 1-indexed, so max group index is count of '('\r\n          ++groupIndex;\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue) {\r\n            if (decimalValue <= groupIndex) {\r\n              capturedGroups[decimalValue] = -1;\r\n            } else {\r\n              // Replace with an unambiguous escape sequence so that\r\n              // an octal escape sequence does not turn into a backreference\r\n              // to a capturing group from an earlier regex.\r\n              parts[i] = encodeEscape(decimalValue);\r\n            }\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Renumber groups and reduce capturing groups to non-capturing groups\r\n      // where possible.\r\n      for (var i = 1; i < capturedGroups.length; ++i) {\r\n        if (-1 === capturedGroups[i]) {\r\n          capturedGroups[i] = ++capturedGroupIndex;\r\n        }\r\n      }\r\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\r\n        var p = parts[i];\r\n        if (p === '(') {\r\n          ++groupIndex;\r\n          if (!capturedGroups[groupIndex]) {\r\n            parts[i] = '(?:';\r\n          }\r\n        } else if ('\\\\' === p.charAt(0)) {\r\n          var decimalValue = +p.substring(1);\r\n          if (decimalValue && decimalValue <= groupIndex) {\r\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\r\n          }\r\n        }\r\n      }\r\n  \r\n      // Remove any prefix anchors so that the output will match anywhere.\r\n      // ^^ really does mean an anchored match though.\r\n      for (var i = 0; i < n; ++i) {\r\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\r\n      }\r\n  \r\n      // Expand letters to groups to handle mixing of case-sensitive and\r\n      // case-insensitive patterns if necessary.\r\n      if (regex.ignoreCase && needToFoldCase) {\r\n        for (var i = 0; i < n; ++i) {\r\n          var p = parts[i];\r\n          var ch0 = p.charAt(0);\r\n          if (p.length >= 2 && ch0 === '[') {\r\n            parts[i] = caseFoldCharset(p);\r\n          } else if (ch0 !== '\\\\') {\r\n            // TODO: handle letters in numeric escapes.\r\n            parts[i] = p.replace(\r\n                /[a-zA-Z]/g,\r\n                function (ch) {\r\n                  var cc = ch.charCodeAt(0);\r\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\r\n                });\r\n          }\r\n        }\r\n      }\r\n  \r\n      return parts.join('');\r\n    }\r\n  \r\n    var rewritten = [];\r\n    for (var i = 0, n = regexs.length; i < n; ++i) {\r\n      var regex = regexs[i];\r\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\r\n      rewritten.push(\r\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\r\n    }\r\n  \r\n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\r\n  }\r\n\r\n  /**\r\n   * Split markup into a string of source code and an array mapping ranges in\r\n   * that string to the text nodes in which they appear.\r\n   *\r\n   * <p>\r\n   * The HTML DOM structure:</p>\r\n   * <pre>\r\n   * (Element   \"p\"\r\n   *   (Element \"b\"\r\n   *     (Text  \"print \"))       ; #1\r\n   *   (Text    \"'Hello '\")      ; #2\r\n   *   (Element \"br\")            ; #3\r\n   *   (Text    \"  + 'World';\")) ; #4\r\n   * </pre>\r\n   * <p>\r\n   * corresponds to the HTML\r\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\r\n   *\r\n   * <p>\r\n   * It will produce the output:</p>\r\n   * <pre>\r\n   * {\r\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\r\n   *   //                     1          2\r\n   *   //           012345678901234 5678901234567\r\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\r\n   * }\r\n   * </pre>\r\n   * <p>\r\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\r\n   * on for the other text nodes.\r\n   * </p>\r\n   *\r\n   * <p>\r\n   * The {@code} spans array is an array of pairs.  Even elements are the start\r\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\r\n   * that contain the text for those substrings.\r\n   * Substrings continue until the next index or the end of the source.\r\n   * </p>\r\n   *\r\n   * @param {Node} node an HTML DOM subtree containing source-code.\r\n   * @param {boolean} isPreformatted true if white-space in text nodes should\r\n   *    be considered significant.\r\n   * @return {Object} source code and the text nodes in which they occur.\r\n   */\r\n  function extractSourceSpans(node, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n  \r\n    var chunks = [];\r\n    var length = 0;\r\n    var spans = [];\r\n    var k = 0;\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1) {  // Element\r\n        if (nocode.test(node.className)) { return; }\r\n        for (var child = node.firstChild; child; child = child.nextSibling) {\r\n          walk(child);\r\n        }\r\n        var nodeName = node.nodeName.toLowerCase();\r\n        if ('br' === nodeName || 'li' === nodeName) {\r\n          chunks[k] = '\\n';\r\n          spans[k << 1] = length++;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      } else if (type == 3 || type == 4) {  // Text\r\n        var text = node.nodeValue;\r\n        if (text.length) {\r\n          if (!isPreformatted) {\r\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\r\n          } else {\r\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\r\n          }\r\n          // TODO: handle tabs here?\r\n          chunks[k] = text;\r\n          spans[k << 1] = length;\r\n          length += text.length;\r\n          spans[(k++ << 1) | 1] = node;\r\n        }\r\n      }\r\n    }\r\n  \r\n    walk(node);\r\n  \r\n    return {\r\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\r\n      spans: spans\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Apply the given language handler to sourceCode and add the resulting\r\n   * decorations to out.\r\n   * @param {number} basePos the index of sourceCode within the chunk of source\r\n   *    whose decorations are already present on out.\r\n   */\r\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\r\n    if (!sourceCode) { return; }\r\n    var job = {\r\n      sourceCode: sourceCode,\r\n      basePos: basePos\r\n    };\r\n    langHandler(job);\r\n    out.push.apply(out, job.decorations);\r\n  }\r\n\r\n  var notWs = /\\S/;\r\n\r\n  /**\r\n   * Given an element, if it contains only one child element and any text nodes\r\n   * it contains contain only space characters, return the sole child element.\r\n   * Otherwise returns undefined.\r\n   * <p>\r\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\r\n   * there is a single child element that contains all the non-space textual\r\n   * content, but not to return anything where there are multiple child elements\r\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\r\n   * is textual content.\r\n   */\r\n  function childContentWrapper(element) {\r\n    var wrapper = undefined;\r\n    for (var c = element.firstChild; c; c = c.nextSibling) {\r\n      var type = c.nodeType;\r\n      wrapper = (type === 1)  // Element Node\r\n          ? (wrapper ? element : c)\r\n          : (type === 3)  // Text Node\r\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\r\n          : wrapper;\r\n    }\r\n    return wrapper === element ? undefined : wrapper;\r\n  }\r\n\r\n  /** Given triples of [style, pattern, context] returns a lexing function,\r\n    * The lexing function interprets the patterns to find token boundaries and\r\n    * returns a decoration list of the form\r\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\r\n    * where index_n is an index into the sourceCode, and style_n is a style\r\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\r\n    * all characters in sourceCode[index_n-1:index_n].\r\n    *\r\n    * The stylePatterns is a list whose elements have the form\r\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\r\n    *\r\n    * Style is a style constant like PR_PLAIN, or can be a string of the\r\n    * form 'lang-FOO', where FOO is a language extension describing the\r\n    * language of the portion of the token in $1 after pattern executes.\r\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\r\n    * '(hello (world))', then that portion of the token will be passed to the\r\n    * registered lisp handler for formatting.\r\n    * The text before and after group 1 will be restyled using this decorator\r\n    * so decorators should take care that this doesn't result in infinite\r\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\r\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\r\n    * '<script>foo()<\\/script>', which would cause the current decorator to\r\n    * be called with '<script>' which would not match the same rule since\r\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\r\n    * the generic tag rule.  The handler registered for the 'js' extension would\r\n    * then be called with 'foo()', and finally, the current decorator would\r\n    * be called with '<\\/script>' which would not match the original rule and\r\n    * so the generic tag rule would identify it as a tag.\r\n    *\r\n    * Pattern must only match prefixes, and if it matches a prefix, then that\r\n    * match is considered a token with the same style.\r\n    *\r\n    * Context is applied to the last non-whitespace, non-comment token\r\n    * recognized.\r\n    *\r\n    * Shortcut is an optional string of characters, any of which, if the first\r\n    * character, gurantee that this pattern and only this pattern matches.\r\n    *\r\n    * @param {Array} shortcutStylePatterns patterns that always start with\r\n    *   a known character.  Must have a shortcut string.\r\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\r\n    *   order if the shortcut ones fail.  May have shortcuts.\r\n    *\r\n    * @return {function (Object)} a\r\n    *   function that takes source code and returns a list of decorations.\r\n    */\r\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\r\n    var shortcuts = {};\r\n    var tokenizer;\r\n    (function () {\r\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\r\n      var allRegexs = [];\r\n      var regexKeys = {};\r\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\r\n        var patternParts = allPatterns[i];\r\n        var shortcutChars = patternParts[3];\r\n        if (shortcutChars) {\r\n          for (var c = shortcutChars.length; --c >= 0;) {\r\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\r\n          }\r\n        }\r\n        var regex = patternParts[1];\r\n        var k = '' + regex;\r\n        if (!regexKeys.hasOwnProperty(k)) {\r\n          allRegexs.push(regex);\r\n          regexKeys[k] = null;\r\n        }\r\n      }\r\n      allRegexs.push(/[\\0-\\uffff]/);\r\n      tokenizer = combinePrefixPatterns(allRegexs);\r\n    })();\r\n\r\n    var nPatterns = fallthroughStylePatterns.length;\r\n\r\n    /**\r\n     * Lexes job.sourceCode and produces an output array job.decorations of\r\n     * style classes preceded by the position at which they start in\r\n     * job.sourceCode in order.\r\n     *\r\n     * @param {Object} job an object like <pre>{\r\n     *    sourceCode: {string} sourceText plain text,\r\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\r\n     *        sourceCode.\r\n     * }</pre>\r\n     */\r\n    var decorate = function (job) {\r\n      var sourceCode = job.sourceCode, basePos = job.basePos;\r\n      /** Even entries are positions in source in ascending order.  Odd enties\r\n        * are style markers (e.g., PR_COMMENT) that run from that position until\r\n        * the end.\r\n        * @type {Array.<number|string>}\r\n        */\r\n      var decorations = [basePos, PR_PLAIN];\r\n      var pos = 0;  // index into sourceCode\r\n      var tokens = sourceCode.match(tokenizer) || [];\r\n      var styleCache = {};\r\n\r\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\r\n        var token = tokens[ti];\r\n        var style = styleCache[token];\r\n        var match = void 0;\r\n\r\n        var isEmbedded;\r\n        if (typeof style === 'string') {\r\n          isEmbedded = false;\r\n        } else {\r\n          var patternParts = shortcuts[token.charAt(0)];\r\n          if (patternParts) {\r\n            match = token.match(patternParts[1]);\r\n            style = patternParts[0];\r\n          } else {\r\n            for (var i = 0; i < nPatterns; ++i) {\r\n              patternParts = fallthroughStylePatterns[i];\r\n              match = token.match(patternParts[1]);\r\n              if (match) {\r\n                style = patternParts[0];\r\n                break;\r\n              }\r\n            }\r\n\r\n            if (!match) {  // make sure that we make progress\r\n              style = PR_PLAIN;\r\n            }\r\n          }\r\n\r\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\r\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\r\n            isEmbedded = false;\r\n            style = PR_SOURCE;\r\n          }\r\n\r\n          if (!isEmbedded) { styleCache[token] = style; }\r\n        }\r\n\r\n        var tokenStart = pos;\r\n        pos += token.length;\r\n\r\n        if (!isEmbedded) {\r\n          decorations.push(basePos + tokenStart, style);\r\n        } else {  // Treat group 1 as an embedded block of source code.\r\n          var embeddedSource = match[1];\r\n          var embeddedSourceStart = token.indexOf(embeddedSource);\r\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\r\n          if (match[2]) {\r\n            // If embeddedSource can be blank, then it would match at the\r\n            // beginning which would cause us to infinitely recurse on the\r\n            // entire token, so we catch the right context in match[2].\r\n            embeddedSourceEnd = token.length - match[2].length;\r\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\r\n          }\r\n          var lang = style.substring(5);\r\n          // Decorate the left of the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart,\r\n              token.substring(0, embeddedSourceStart),\r\n              decorate, decorations);\r\n          // Decorate the embedded source\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceStart,\r\n              embeddedSource,\r\n              langHandlerForExtension(lang, embeddedSource),\r\n              decorations);\r\n          // Decorate the right of the embedded section\r\n          appendDecorations(\r\n              basePos + tokenStart + embeddedSourceEnd,\r\n              token.substring(embeddedSourceEnd),\r\n              decorate, decorations);\r\n        }\r\n      }\r\n      job.decorations = decorations;\r\n    };\r\n    return decorate;\r\n  }\r\n\r\n  /** returns a function that produces a list of decorations from source text.\r\n    *\r\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\r\n    * escape.  It does not recognize perl's qq() style strings.\r\n    * It has no special handling for double delimiter escapes as in basic, or\r\n    * the tripled delimiters used in python, but should work on those regardless\r\n    * although in those cases a single string literal may be broken up into\r\n    * multiple adjacent string literals.\r\n    *\r\n    * It recognizes C, C++, and shell style comments.\r\n    *\r\n    * @param {Object} options a set of optional parameters.\r\n    * @return {function (Object)} a function that examines the source code\r\n    *     in the input job and builds the decoration list.\r\n    */\r\n  function sourceDecorator(options) {\r\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\r\n    if (options['tripleQuotedStrings']) {\r\n      // '''multi-line-string''', 'single-line-string', and double-quoted\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\r\n           null, '\\'\"']);\r\n    } else if (options['multiLineStrings']) {\r\n      // 'multi-line-string', \"multi-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\r\n           null, '\\'\"`']);\r\n    } else {\r\n      // 'single-line-string', \"single-line-string\"\r\n      shortcutStylePatterns.push(\r\n          [PR_STRING,\r\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\r\n           null, '\"\\'']);\r\n    }\r\n    if (options['verbatimStrings']) {\r\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\r\n      fallthroughStylePatterns.push(\r\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\r\n    }\r\n    var hc = options['hashComments'];\r\n    if (hc) {\r\n      if (options['cStyleComments']) {\r\n        if (hc > 1) {  // multiline hash comments\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\r\n        } else {\r\n          // Stop C preprocessor declarations at an unclosed open comment\r\n          shortcutStylePatterns.push(\r\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\r\n               null, '#']);\r\n        }\r\n        // #include <stdio.h>\r\n        fallthroughStylePatterns.push(\r\n            [PR_STRING,\r\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\r\n             null]);\r\n      } else {\r\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\r\n      }\r\n    }\r\n    if (options['cStyleComments']) {\r\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\r\n      fallthroughStylePatterns.push(\r\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\r\n    }\r\n    var regexLiterals = options['regexLiterals'];\r\n    if (regexLiterals) {\r\n      /**\r\n       * @const\r\n       */\r\n      var regexExcls = regexLiterals > 1\r\n        ? ''  // Multiline regex literals\r\n        : '\\n\\r';\r\n      /**\r\n       * @const\r\n       */\r\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\r\n      /**\r\n       * @const\r\n       */\r\n      var REGEX_LITERAL = (\r\n          // A regular expression literal starts with a slash that is\r\n          // not followed by * or / so that it is not confused with\r\n          // comments.\r\n          '/(?=[^/*' + regexExcls + '])'\r\n          // and then contains any number of raw characters,\r\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\r\n          // escape sequences (\\x5C),\r\n          +    '|\\\\x5C' + regexAny\r\n          // or non-nesting character sets (\\x5B\\x5D);\r\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\r\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\r\n          // finally closed by a /.\r\n          + '/');\r\n      fallthroughStylePatterns.push(\r\n          ['lang-regex',\r\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\r\n           ]);\r\n    }\r\n\r\n    var types = options['types'];\r\n    if (types) {\r\n      fallthroughStylePatterns.push([PR_TYPE, types]);\r\n    }\r\n\r\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\r\n    if (keywords.length) {\r\n      fallthroughStylePatterns.push(\r\n          [PR_KEYWORD,\r\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\r\n           null]);\r\n    }\r\n\r\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\r\n\r\n    var punctuation =\r\n      // The Bash man page says\r\n\r\n      // A word is a sequence of characters considered as a single\r\n      // unit by GRUB. Words are separated by metacharacters,\r\n      // which are the following plus space, tab, and newline: { }\r\n      // | & $ ; < >\r\n      // ...\r\n      \r\n      // A word beginning with # causes that word and all remaining\r\n      // characters on that line to be ignored.\r\n\r\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\r\n      // comment but empirically\r\n      // $ echo {#}\r\n      // {#}\r\n      // $ echo \\$#\r\n      // $#\r\n      // $ echo }#\r\n      // }#\r\n\r\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\r\n\r\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\r\n      // suggests that this definition is compatible with a\r\n      // default mode that tries to use a single token definition\r\n      // to recognize both bash/python style comments and C\r\n      // preprocessor directives.\r\n\r\n      // This definition of punctuation does not include # in the list of\r\n      // follow-on exclusions, so # will not be broken before if preceeded\r\n      // by a punctuation character.  We could try to exclude # after\r\n      // [|&;<>] but that doesn't seem to cause many major problems.\r\n      // If that does turn out to be a problem, we should change the below\r\n      // when hc is truthy to include # in the run of punctuation characters\r\n      // only when not followint [|&;<>].\r\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\r\n    if (options['regexLiterals']) {\r\n      punctuation += '(?!\\s*\\/)';\r\n    }\r\n\r\n    fallthroughStylePatterns.push(\r\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\r\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\r\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\r\n        [PR_LITERAL,\r\n         new RegExp(\r\n             '^(?:'\r\n             // A hex number\r\n             + '0x[a-f0-9]+'\r\n             // or an octal or decimal number,\r\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\r\n             // possibly in scientific notation\r\n             + '(?:e[+\\\\-]?\\\\d+)?'\r\n             + ')'\r\n             // with an optional modifier like UL for unsigned long\r\n             + '[a-z]*', 'i'),\r\n         null, '0123456789'],\r\n        // Don't treat escaped quotes in bash as starting strings.\r\n        // See issue 144.\r\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\r\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\r\n\r\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\r\n  }\r\n\r\n  var decorateSource = sourceDecorator({\r\n        'keywords': ALL_KEYWORDS,\r\n        'hashComments': true,\r\n        'cStyleComments': true,\r\n        'multiLineStrings': true,\r\n        'regexLiterals': true\r\n      });\r\n\r\n  /**\r\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\r\n   * list item.\r\n   *\r\n   * @param {Node} node modified in place.  Its content is pulled into an\r\n   *     HTMLOListElement, and each line is moved into a separate list item.\r\n   *     This requires cloning elements, so the input might not have unique\r\n   *     IDs after numbering.\r\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\r\n   *     be treated as significant.\r\n   */\r\n  function numberLines(node, opt_startLineNum, isPreformatted) {\r\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\r\n    var lineBreak = /\\r\\n?|\\n/;\r\n  \r\n    var document = node.ownerDocument;\r\n  \r\n    var li = document.createElement('li');\r\n    while (node.firstChild) {\r\n      li.appendChild(node.firstChild);\r\n    }\r\n    // An array of lines.  We split below, so this is initialized to one\r\n    // un-split line.\r\n    var listItems = [li];\r\n  \r\n    function walk(node) {\r\n      var type = node.nodeType;\r\n      if (type == 1 && !nocode.test(node.className)) {  // Element\r\n        if ('br' === node.nodeName) {\r\n          breakAfter(node);\r\n          // Discard the <BR> since it is now flush against a </LI>.\r\n          if (node.parentNode) {\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        } else {\r\n          for (var child = node.firstChild; child; child = child.nextSibling) {\r\n            walk(child);\r\n          }\r\n        }\r\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\r\n        var text = node.nodeValue;\r\n        var match = text.match(lineBreak);\r\n        if (match) {\r\n          var firstLine = text.substring(0, match.index);\r\n          node.nodeValue = firstLine;\r\n          var tail = text.substring(match.index + match[0].length);\r\n          if (tail) {\r\n            var parent = node.parentNode;\r\n            parent.insertBefore(\r\n              document.createTextNode(tail), node.nextSibling);\r\n          }\r\n          breakAfter(node);\r\n          if (!firstLine) {\r\n            // Don't leave blank text nodes in the DOM.\r\n            node.parentNode.removeChild(node);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  \r\n    // Split a line after the given node.\r\n    function breakAfter(lineEndNode) {\r\n      // If there's nothing to the right, then we can skip ending the line\r\n      // here, and move root-wards since splitting just before an end-tag\r\n      // would require us to create a bunch of empty copies.\r\n      while (!lineEndNode.nextSibling) {\r\n        lineEndNode = lineEndNode.parentNode;\r\n        if (!lineEndNode) { return; }\r\n      }\r\n  \r\n      function breakLeftOf(limit, copy) {\r\n        // Clone shallowly if this node needs to be on both sides of the break.\r\n        var rightSide = copy ? limit.cloneNode(false) : limit;\r\n        var parent = limit.parentNode;\r\n        if (parent) {\r\n          // We clone the parent chain.\r\n          // This helps us resurrect important styling elements that cross lines.\r\n          // E.g. in <i>Foo<br>Bar</i>\r\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\r\n          var parentClone = breakLeftOf(parent, 1);\r\n          // Move the clone and everything to the right of the original\r\n          // onto the cloned parent.\r\n          var next = limit.nextSibling;\r\n          parentClone.appendChild(rightSide);\r\n          for (var sibling = next; sibling; sibling = next) {\r\n            next = sibling.nextSibling;\r\n            parentClone.appendChild(sibling);\r\n          }\r\n        }\r\n        return rightSide;\r\n      }\r\n  \r\n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\r\n  \r\n      // Walk the parent chain until we reach an unattached LI.\r\n      for (var parent;\r\n           // Check nodeType since IE invents document fragments.\r\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\r\n        copiedListItem = parent;\r\n      }\r\n      // Put it on the list of lines for later processing.\r\n      listItems.push(copiedListItem);\r\n    }\r\n  \r\n    // Split lines while there are lines left to split.\r\n    for (var i = 0;  // Number of lines that have been split so far.\r\n         i < listItems.length;  // length updated by breakAfter calls.\r\n         ++i) {\r\n      walk(listItems[i]);\r\n    }\r\n  \r\n    // Make sure numeric indices show correctly.\r\n    if (opt_startLineNum === (opt_startLineNum|0)) {\r\n      listItems[0].setAttribute('value', opt_startLineNum);\r\n    }\r\n  \r\n    var ol = document.createElement('ol');\r\n    ol.className = 'linenums';\r\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\r\n    for (var i = 0, n = listItems.length; i < n; ++i) {\r\n      li = listItems[i];\r\n      // Stick a class on the LIs so that stylesheets can\r\n      // color odd/even rows, or any other row pattern that\r\n      // is co-prime with 10.\r\n      li.className = 'L' + ((i + offset) % 10);\r\n      if (!li.firstChild) {\r\n        li.appendChild(document.createTextNode('\\xA0'));\r\n      }\r\n      ol.appendChild(li);\r\n    }\r\n  \r\n    node.appendChild(ol);\r\n  }\r\n  /**\r\n   * Breaks {@code job.sourceCode} around style boundaries in\r\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\r\n   * @param {Object} job like <pre>{\r\n   *    sourceCode: {string} source as plain text,\r\n   *    sourceNode: {HTMLElement} the element containing the source,\r\n   *    spans: {Array.<number|Node>} alternating span start indices into source\r\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\r\n   *       span.\r\n   *    decorations: {Array.<number|string} an array of style classes preceded\r\n   *       by the position at which they start in job.sourceCode in order\r\n   * }</pre>\r\n   * @private\r\n   */\r\n  function recombineTagsAndDecorations(job) {\r\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\r\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\r\n    var newlineRe = /\\n/g;\r\n  \r\n    var source = job.sourceCode;\r\n    var sourceLength = source.length;\r\n    // Index into source after the last code-unit recombined.\r\n    var sourceIndex = 0;\r\n  \r\n    var spans = job.spans;\r\n    var nSpans = spans.length;\r\n    // Index into spans after the last span which ends at or before sourceIndex.\r\n    var spanIndex = 0;\r\n  \r\n    var decorations = job.decorations;\r\n    var nDecorations = decorations.length;\r\n    // Index into decorations after the last decoration which ends at or before\r\n    // sourceIndex.\r\n    var decorationIndex = 0;\r\n  \r\n    // Remove all zero-length decorations.\r\n    decorations[nDecorations] = sourceLength;\r\n    var decPos, i;\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      if (decorations[i] !== decorations[i + 2]) {\r\n        decorations[decPos++] = decorations[i++];\r\n        decorations[decPos++] = decorations[i++];\r\n      } else {\r\n        i += 2;\r\n      }\r\n    }\r\n    nDecorations = decPos;\r\n  \r\n    // Simplify decorations.\r\n    for (i = decPos = 0; i < nDecorations;) {\r\n      var startPos = decorations[i];\r\n      // Conflate all adjacent decorations that use the same style.\r\n      var startDec = decorations[i + 1];\r\n      var end = i + 2;\r\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\r\n        end += 2;\r\n      }\r\n      decorations[decPos++] = startPos;\r\n      decorations[decPos++] = startDec;\r\n      i = end;\r\n    }\r\n  \r\n    nDecorations = decorations.length = decPos;\r\n  \r\n    var sourceNode = job.sourceNode;\r\n    var oldDisplay;\r\n    if (sourceNode) {\r\n      oldDisplay = sourceNode.style.display;\r\n      sourceNode.style.display = 'none';\r\n    }\r\n    try {\r\n      var decoration = null;\r\n      while (spanIndex < nSpans) {\r\n        var spanStart = spans[spanIndex];\r\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\r\n  \r\n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\r\n  \r\n        var end = Math.min(spanEnd, decEnd);\r\n  \r\n        var textNode = spans[spanIndex + 1];\r\n        var styledText;\r\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\r\n            // Don't introduce spans around empty text nodes.\r\n            && (styledText = source.substring(sourceIndex, end))) {\r\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\r\n          // code to display with spaces instead of line breaks.\r\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\r\n          // space to appear at the beginning of every line but the first.\r\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\r\n          if (isIE8OrEarlier) {\r\n            styledText = styledText.replace(newlineRe, '\\r');\r\n          }\r\n          textNode.nodeValue = styledText;\r\n          var document = textNode.ownerDocument;\r\n          var span = document.createElement('span');\r\n          span.className = decorations[decorationIndex + 1];\r\n          var parentNode = textNode.parentNode;\r\n          parentNode.replaceChild(span, textNode);\r\n          span.appendChild(textNode);\r\n          if (sourceIndex < spanEnd) {  // Split off a text node.\r\n            spans[spanIndex + 1] = textNode\r\n                // TODO: Possibly optimize by using '' if there's no flicker.\r\n                = document.createTextNode(source.substring(end, spanEnd));\r\n            parentNode.insertBefore(textNode, span.nextSibling);\r\n          }\r\n        }\r\n  \r\n        sourceIndex = end;\r\n  \r\n        if (sourceIndex >= spanEnd) {\r\n          spanIndex += 2;\r\n        }\r\n        if (sourceIndex >= decEnd) {\r\n          decorationIndex += 2;\r\n        }\r\n      }\r\n    } finally {\r\n      if (sourceNode) {\r\n        sourceNode.style.display = oldDisplay;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Maps language-specific file extensions to handlers. */\r\n  var langHandlerRegistry = {};\r\n  /** Register a language handler for the given file extensions.\r\n    * @param {function (Object)} handler a function from source code to a list\r\n    *      of decorations.  Takes a single argument job which describes the\r\n    *      state of the computation.   The single parameter has the form\r\n    *      {@code {\r\n    *        sourceCode: {string} as plain text.\r\n    *        decorations: {Array.<number|string>} an array of style classes\r\n    *                     preceded by the position at which they start in\r\n    *                     job.sourceCode in order.\r\n    *                     The language handler should assigned this field.\r\n    *        basePos: {int} the position of source in the larger source chunk.\r\n    *                 All positions in the output decorations array are relative\r\n    *                 to the larger source chunk.\r\n    *      } }\r\n    * @param {Array.<string>} fileExtensions\r\n    */\r\n  function registerLangHandler(handler, fileExtensions) {\r\n    for (var i = fileExtensions.length; --i >= 0;) {\r\n      var ext = fileExtensions[i];\r\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\r\n        langHandlerRegistry[ext] = handler;\r\n      } else if (win['console']) {\r\n        console['warn']('cannot override language handler %s', ext);\r\n      }\r\n    }\r\n  }\r\n  function langHandlerForExtension(extension, source) {\r\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\r\n      // Treat it as markup if the first non whitespace character is a < and\r\n      // the last non-whitespace character is a >.\r\n      extension = /^\\s*</.test(source)\r\n          ? 'default-markup'\r\n          : 'default-code';\r\n    }\r\n    return langHandlerRegistry[extension];\r\n  }\r\n  registerLangHandler(decorateSource, ['default-code']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [],\r\n          [\r\n           [PR_PLAIN,       /^[^<?]+/],\r\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\r\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\r\n           // Unescaped content in an unknown language\r\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\r\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\r\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\r\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\r\n           // Unescaped content in javascript.  (Or possibly vbscript).\r\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\r\n           // Contains unescaped stylesheet content\r\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\r\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\r\n          ]),\r\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\r\n  registerLangHandler(\r\n      createSimpleLexer(\r\n          [\r\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\r\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\r\n           ],\r\n          [\r\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\r\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\r\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\r\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\r\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\r\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\r\n           ]),\r\n      ['in.tag']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CPP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'types': C_TYPES\r\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': 'null,true,false'\r\n        }), ['json']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': CSHARP_KEYWORDS,\r\n          'hashComments': true,\r\n          'cStyleComments': true,\r\n          'verbatimStrings': true,\r\n          'types': C_TYPES\r\n        }), ['cs']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JAVA_KEYWORDS,\r\n          'cStyleComments': true\r\n        }), ['java']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': SH_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true\r\n        }), ['bash', 'bsh', 'csh', 'sh']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PYTHON_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'tripleQuotedStrings': true\r\n        }), ['cv', 'py', 'python']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': PERL_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': 2  // multiline regex literals\r\n        }), ['perl', 'pl', 'pm']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUBY_KEYWORDS,\r\n          'hashComments': true,\r\n          'multiLineStrings': true,\r\n          'regexLiterals': true\r\n        }), ['rb', 'ruby']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': JSCRIPT_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'regexLiterals': true\r\n        }), ['javascript', 'js']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': COFFEE_KEYWORDS,\r\n          'hashComments': 3,  // ### style block comments\r\n          'cStyleComments': true,\r\n          'multilineStrings': true,\r\n          'tripleQuotedStrings': true,\r\n          'regexLiterals': true\r\n        }), ['coffee']);\r\n  registerLangHandler(sourceDecorator({\r\n          'keywords': RUST_KEYWORDS,\r\n          'cStyleComments': true,\r\n          'multilineStrings': true\r\n        }), ['rc', 'rs', 'rust']);\r\n  registerLangHandler(\r\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\r\n\r\n  function applyDecorator(job) {\r\n    var opt_langExtension = job.langExtension;\r\n\r\n    try {\r\n      // Extract tags, and convert the source code to plain text.\r\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\r\n      /** Plain text. @type {string} */\r\n      var source = sourceAndSpans.sourceCode;\r\n      job.sourceCode = source;\r\n      job.spans = sourceAndSpans.spans;\r\n      job.basePos = 0;\r\n\r\n      // Apply the appropriate language handler\r\n      langHandlerForExtension(opt_langExtension, source)(job);\r\n\r\n      // Integrate the decorations and tags back into the source code,\r\n      // modifying the sourceNode in place.\r\n      recombineTagsAndDecorations(job);\r\n    } catch (e) {\r\n      if (win['console']) {\r\n        console['log'](e && e['stack'] || e);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Pretty print a chunk of code.\r\n   * @param sourceCodeHtml {string} The HTML to pretty print.\r\n   * @param opt_langExtension {string} The language name to use.\r\n   *     Typically, a filename extension like 'cpp' or 'java'.\r\n   * @param opt_numberLines {number|boolean} True to number lines,\r\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\r\n   */\r\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\r\n    var container = document.createElement('div');\r\n    // This could cause images to load and onload listeners to fire.\r\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\r\n    // We assume that the inner HTML is from a trusted source.\r\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\r\n    // when it is injected into a <pre> tag.\r\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\r\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\r\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\r\n    container = container.firstChild;\r\n    if (opt_numberLines) {\r\n      numberLines(container, opt_numberLines, true);\r\n    }\r\n\r\n    var job = {\r\n      langExtension: opt_langExtension,\r\n      numberLines: opt_numberLines,\r\n      sourceNode: container,\r\n      pre: 1\r\n    };\r\n    applyDecorator(job);\r\n    return container.innerHTML;\r\n  }\r\n\r\n   /**\r\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\r\n    * {@code class=prettyprint} and prettify them.\r\n    *\r\n    * @param {Function} opt_whenDone called when prettifying is done.\r\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\r\n    *   containing all the elements to pretty print.\r\n    *   Defaults to {@code document.body}.\r\n    */\r\n  function $prettyPrint(opt_whenDone, opt_root) {\r\n    var root = opt_root || document.body;\r\n    var doc = root.ownerDocument || document;\r\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\r\n    // fetch a list of nodes to rewrite\r\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\r\n    var elements = [];\r\n    for (var i = 0; i < codeSegments.length; ++i) {\r\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\r\n        elements.push(codeSegments[i][j]);\r\n      }\r\n    }\r\n    codeSegments = null;\r\n\r\n    var clock = Date;\r\n    if (!clock['now']) {\r\n      clock = { 'now': function () { return +(new Date); } };\r\n    }\r\n\r\n    // The loop is broken into a series of continuations to make sure that we\r\n    // don't make the browser unresponsive when rewriting a large page.\r\n    var k = 0;\r\n    var prettyPrintingJob;\r\n\r\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\r\n    var prettyPrintRe = /\\bprettyprint\\b/;\r\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\r\n    var preformattedTagNameRe = /pre|xmp/i;\r\n    var codeRe = /^code$/i;\r\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\r\n    var EMPTY = {};\r\n\r\n    function doWork() {\r\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\r\n                     clock['now']() + 250 /* ms */ :\r\n                     Infinity);\r\n      for (; k < elements.length && clock['now']() < endTime; k++) {\r\n        var cs = elements[k];\r\n\r\n        // Look for a preceding comment like\r\n        // <?prettify lang=\"...\" linenums=\"...\"?>\r\n        var attrs = EMPTY;\r\n        {\r\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\r\n            var nt = preceder.nodeType;\r\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\r\n            // like <!--?foo?-->, but in XML is a processing instruction\r\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\r\n            if (value\r\n                ? !/^\\??prettify\\b/.test(value)\r\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\r\n              // Skip over white-space text nodes but not others.\r\n              break;\r\n            }\r\n            if (value) {\r\n              attrs = {};\r\n              value.replace(\r\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\r\n                function (_, name, value) { attrs[name] = value; });\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        var className = cs.className;\r\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\r\n            // Don't redo this if we've already done it.\r\n            // This allows recalling pretty print to just prettyprint elements\r\n            // that have been added to the page since last call.\r\n            && !prettyPrintedRe.test(className)) {\r\n\r\n          // make sure this is not nested in an already prettified element\r\n          var nested = false;\r\n          for (var p = cs.parentNode; p; p = p.parentNode) {\r\n            var tn = p.tagName;\r\n            if (preCodeXmpRe.test(tn)\r\n                && p.className && prettyPrintRe.test(p.className)) {\r\n              nested = true;\r\n              break;\r\n            }\r\n          }\r\n          if (!nested) {\r\n            // Mark done.  If we fail to prettyprint for whatever reason,\r\n            // we shouldn't try again.\r\n            cs.className += ' prettyprinted';\r\n\r\n            // If the classes includes a language extensions, use it.\r\n            // Language extensions can be specified like\r\n            //     <pre class=\"prettyprint lang-cpp\">\r\n            // the language extension \"cpp\" is used to find a language handler\r\n            // as passed to PR.registerLangHandler.\r\n            // HTML5 recommends that a language be specified using \"language-\"\r\n            // as the prefix instead.  Google Code Prettify supports both.\r\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\r\n            var langExtension = attrs['lang'];\r\n            if (!langExtension) {\r\n              langExtension = className.match(langExtensionRe);\r\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\r\n              var wrapper;\r\n              if (!langExtension && (wrapper = childContentWrapper(cs))\r\n                  && codeRe.test(wrapper.tagName)) {\r\n                langExtension = wrapper.className.match(langExtensionRe);\r\n              }\r\n\r\n              if (langExtension) { langExtension = langExtension[1]; }\r\n            }\r\n\r\n            var preformatted;\r\n            if (preformattedTagNameRe.test(cs.tagName)) {\r\n              preformatted = 1;\r\n            } else {\r\n              var currentStyle = cs['currentStyle'];\r\n              var defaultView = doc.defaultView;\r\n              var whitespace = (\r\n                  currentStyle\r\n                  ? currentStyle['whiteSpace']\r\n                  : (defaultView\r\n                     && defaultView.getComputedStyle)\r\n                  ? defaultView.getComputedStyle(cs, null)\r\n                  .getPropertyValue('white-space')\r\n                  : 0);\r\n              preformatted = whitespace\r\n                  && 'pre' === whitespace.substring(0, 3);\r\n            }\r\n\r\n            // Look for a class like linenums or linenums:<n> where <n> is the\r\n            // 1-indexed number of the first line.\r\n            var lineNums = attrs['linenums'];\r\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\r\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\r\n              lineNums =\r\n                lineNums\r\n                ? lineNums[1] && lineNums[1].length\r\n                  ? +lineNums[1] : true\r\n                : false;\r\n            }\r\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\r\n\r\n            // do the pretty printing\r\n            prettyPrintingJob = {\r\n              langExtension: langExtension,\r\n              sourceNode: cs,\r\n              numberLines: lineNums,\r\n              pre: preformatted\r\n            };\r\n            applyDecorator(prettyPrintingJob);\r\n          }\r\n        }\r\n      }\r\n      if (k < elements.length) {\r\n        // finish up in a continuation\r\n        setTimeout(doWork, 250);\r\n      } else if ('function' === typeof opt_whenDone) {\r\n        opt_whenDone();\r\n      }\r\n    }\r\n\r\n    doWork();\r\n  }\r\n\r\n  /**\r\n   * Contains functions for creating and registering new language handlers.\r\n   * @type {Object}\r\n   */\r\n  var PR = win['PR'] = {\r\n        'createSimpleLexer': createSimpleLexer,\r\n        'registerLangHandler': registerLangHandler,\r\n        'sourceDecorator': sourceDecorator,\r\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\r\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\r\n        'PR_COMMENT': PR_COMMENT,\r\n        'PR_DECLARATION': PR_DECLARATION,\r\n        'PR_KEYWORD': PR_KEYWORD,\r\n        'PR_LITERAL': PR_LITERAL,\r\n        'PR_NOCODE': PR_NOCODE,\r\n        'PR_PLAIN': PR_PLAIN,\r\n        'PR_PUNCTUATION': PR_PUNCTUATION,\r\n        'PR_SOURCE': PR_SOURCE,\r\n        'PR_STRING': PR_STRING,\r\n        'PR_TAG': PR_TAG,\r\n        'PR_TYPE': PR_TYPE,\r\n        'prettyPrintOne':\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\r\n             : (prettyPrintOne = $prettyPrintOne),\r\n        'prettyPrint': prettyPrint =\r\n           IN_GLOBAL_SCOPE\r\n             ? (win['prettyPrint'] = $prettyPrint)\r\n             : (prettyPrint = $prettyPrint)\r\n      };\r\n\r\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\r\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\r\n  // The Asynchronous Module Definition (AMD) API specifies a\r\n  // mechanism for defining modules such that the module and its\r\n  // dependencies can be asynchronously loaded.\r\n  // ...\r\n  // To allow a clear indicator that a global define function (as\r\n  // needed for script src browser loading) conforms to the AMD API,\r\n  // any global define function SHOULD have a property called \"amd\"\r\n  // whose value is an object. This helps avoid conflict with any\r\n  // other existing JavaScript code that could have defined a define()\r\n  // function that does not conform to the AMD API.\r\n  if (typeof define === \"function\" && define['amd']) {\r\n    define(\"google-code-prettify\", [], function () {\r\n      return PR; \r\n    });\r\n  }\r\n})();\r\n\ndefine(\"prettify\", function(){});\n\n",
        -    "define('itemView',[\r\n  'App',\r\n  // Templates\r\n  'text!tpl/item.html',\r\n  'text!tpl/class.html',\r\n  'text!tpl/itemEnd.html',\r\n  // Tools\r\n  'prettify'\r\n], function(App, itemTpl, classTpl, endTpl) {\r\n  'use strict';\r\n\r\n  var appVersion = App.project.version || 'master';\r\n\r\n  var itemView = Backbone.View.extend({\r\n    el: '#item',\r\n    init: function() {\r\n      this.$html = $('html');\r\n      this.$body = $('body');\r\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\r\n\r\n      this.tpl = _.template(itemTpl);\r\n      this.classTpl = _.template(classTpl);\r\n      this.endTpl = _.template(endTpl);\r\n\r\n      return this;\r\n    },\r\n    getSyntax: function(isMethod, cleanItem) {\r\n      var isConstructor = cleanItem.is_constructor;\r\n      var syntax = '';\r\n      if (isConstructor) {\r\n        syntax += 'new ';\r\n      } else if (cleanItem.static && cleanItem.class) {\r\n        syntax += cleanItem.class + '.';\r\n      }\r\n      syntax += cleanItem.name;\r\n\r\n      if (isMethod || isConstructor) {\r\n        syntax += '(';\r\n        if (cleanItem.params) {\r\n          for (var i = 0; i < cleanItem.params.length; i++) {\r\n            var p = cleanItem.params[i];\r\n            if (p.optional) {\r\n              syntax += '[';\r\n            }\r\n            syntax += p.name;\r\n            if (p.optdefault) {\r\n              syntax += '=' + p.optdefault;\r\n            }\r\n            if (p.optional) {\r\n              syntax += ']';\r\n            }\r\n            if (i !== cleanItem.params.length - 1) {\r\n              syntax += ', ';\r\n            }\r\n          }\r\n        }\r\n        syntax += ')';\r\n      }\r\n\r\n      return syntax;\r\n    },\r\n    // Return a list of valid syntaxes across all overloaded versions of\r\n    // this item.\r\n    //\r\n    // For reference, we ultimately want to replicate something like this:\r\n    //\r\n    // https://processing.org/reference/color_.html\r\n    getSyntaxes: function(isMethod, cleanItem) {\r\n      var overloads = cleanItem.overloads || [cleanItem];\r\n      return overloads.map(this.getSyntax.bind(this, isMethod));\r\n    },\r\n    render: function(item) {\r\n      if (item) {\r\n        var itemHtml = '';\r\n        var cleanItem = this.clean(item);\r\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\r\n        var collectionName = isClass\r\n            ? 'Constructor'\r\n            : this.capitalizeFirst(cleanItem.itemtype),\r\n          isConstructor = cleanItem.is_constructor;\r\n        cleanItem.isMethod = collectionName === 'Method';\r\n\r\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\r\n\r\n        // Set the item header (title)\r\n\r\n        // Set item contents\r\n        if (isClass) {\r\n          var constructor = this.tpl({\r\n            item: cleanItem,\r\n            isClass: true,\r\n            isConstructor: isConstructor,\r\n            syntaxes: syntaxes\r\n          });\r\n          cleanItem.constructor = constructor;\r\n\r\n          var contents = _.find(App.classes, function(c) {\r\n            return c.name === cleanItem.name;\r\n          });\r\n          cleanItem.things = contents.items;\r\n\r\n          itemHtml = this.classTpl(cleanItem);\r\n        } else {\r\n          cleanItem.constRefs =\r\n            item.module === 'Constants' && App.data.consts[item.name];\r\n\r\n          itemHtml = this.tpl({\r\n            item: cleanItem,\r\n            isClass: false,\r\n            isConstructor: false,\r\n            syntaxes: syntaxes\r\n          });\r\n        }\r\n\r\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\r\n\r\n        // Insert the view in the dom\r\n        this.$el.html(itemHtml);\r\n\r\n        renderCode(cleanItem.name);\r\n\r\n        // Set the document title based on the item name.\r\n        // If it is a method, add parentheses to the name\r\n        if (item.itemtype === 'method') {\r\n          App.pageView.appendToDocumentTitle(item.name + '()');\r\n        } else {\r\n          App.pageView.appendToDocumentTitle(item.name);\r\n        }\r\n\r\n        // Hook up alt-text for examples\r\n        setTimeout(function() {\r\n          var alts = $('.example-content')[0];\r\n          if (alts) {\r\n            alts = $(alts)\r\n              .data('alt')\r\n              .split('\\n');\r\n\r\n            var canvases = $('.cnv_div');\r\n            for (var j = 0; j < alts.length; j++) {\r\n              if (j < canvases.length) {\r\n                $(canvases[j]).append(\r\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\r\n                );\r\n              }\r\n            }\r\n          }\r\n        }, 1000);\r\n        Prism.highlightAll();\r\n      }\r\n\r\n      var renderEvent = new Event('reference-rendered');\r\n      window.dispatchEvent(renderEvent);\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Clean item properties: url encode properties containing paths.\r\n     * @param {object} item The item object.\r\n     * @returns {object} Returns the same item object with urlencoded paths.\r\n     */\r\n    clean: function(item) {\r\n      var cleanItem = item;\r\n\r\n      if (cleanItem.hasOwnProperty('file')) {\r\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\r\n      }\r\n      return cleanItem;\r\n    },\r\n    /**\r\n     * Show a single item.\r\n     * @param {object} item Item object.\r\n     * @returns {object} This view.\r\n     */\r\n    show: function(item) {\r\n      if (item) {\r\n        this.render(item);\r\n      }\r\n\r\n      App.pageView.hideContentViews();\r\n\r\n      this.$el.show();\r\n\r\n      this.scrollTop();\r\n      $('#item').focus();\r\n      return this;\r\n    },\r\n    /**\r\n     * Show a message if no item is found.\r\n     * @returns {object} This view.\r\n     */\r\n    nothingFound: function() {\r\n      this.$el.html(\r\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\r\n      );\r\n      App.pageView.hideContentViews();\r\n      this.$el.show();\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Scroll to the top of the window with an animation.\r\n     */\r\n    scrollTop: function() {\r\n      // Hack for Chrome/Firefox scroll animation\r\n      // Chrome scrolls 'body', Firefox scrolls 'html'\r\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\r\n      if (scroll) {\r\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\r\n      }\r\n    },\r\n    /**\r\n     * Helper method to capitalize the first letter of a string\r\n     * @param {string} str\r\n     * @returns {string} Returns the string.\r\n     */\r\n    capitalizeFirst: function(str) {\r\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n    }\r\n  });\r\n\r\n  return itemView;\r\n});\r\n\n",
        -    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\r\\n  <br>\\r\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\r\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\r\\n</div>\\r\\n\\r\\n<div id=\\'collection-list-categories\\'>\\r\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\r\\n<% var i=0; %>\\r\\n<% var max=Math.floor(groups.length/4); %>\\r\\n<% var rem=groups.length%4; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% var m = rem > 0 ? 1 : 0 %>\\r\\n  <% if (i === 0) { %>\\r\\n    <ul aria-labelledby=\"categories\">\\r\\n    <% } %>\\r\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\r\\n    <% if (i === (max+m-1)) { %>\\r\\n    </ul>\\r\\n  \\t<% rem-- %>\\r\\n  \\t<% i=0 %>\\r\\n  <% } else { %>\\r\\n  \\t<% i++ %>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        -    "define('menuView',[\r\n  'App',\r\n  'text!tpl/menu.html'\r\n], function(App, menuTpl) {\r\n\r\n  var menuView = Backbone.View.extend({\r\n    el: '#collection-list-nav',\r\n    /**\r\n     * Init.\r\n     * @returns {object} This view.\r\n     */\r\n    init: function() {\r\n      this.menuTpl = _.template(menuTpl);\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     * @returns {object} This view.\r\n     */\r\n    render: function() {\r\n\r\n      var groups = [];\r\n      _.each(App.modules, function (item, i) {\r\n        if (!item.is_submodule) {\r\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\r\n            groups.push(item.name);\r\n          }\r\n        }\r\n        //}\r\n      });\r\n\r\n      // Sort groups by name A-Z\r\n      groups.sort();\r\n\r\n      var menuHtml = this.menuTpl({\r\n        'groups': groups\r\n      });\r\n\r\n      // Render the view\r\n      this.$el.html(menuHtml);\r\n    },\r\n\r\n    hide: function() {\r\n      this.$el.hide();\r\n    },\r\n\r\n    show: function() {\r\n      this.$el.show();\r\n    },\r\n\r\n    /**\r\n     * Update the menu.\r\n     * @param {string} el The name of the current route.\r\n     */\r\n    update: function(menuItem) {\r\n      //console.log(menuItem);\r\n      // this.$menuItems.removeClass('active');\r\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\r\n\r\n    }\r\n  });\r\n\r\n  return menuView;\r\n\r\n});\r\n\n",
        -    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\r\\n\\r\\n<p><%= module.description %></p>\\r\\n\\r\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\r\\n\\r\\n<% var t = 0; col = 0; %>\\r\\n\\r\\n<% _.each(groups, function(group){ %>\\r\\n  <% if (t == 0) { %> \\r\\n    <div class=\"column_<%=col%>\">\\r\\n  <% } %>\\r\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\r\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\r\\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\r\\n    <% if (group.hash) { %> </a><br> <% } %>\\r\\n  <% } %>\\r\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\r\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\r\\n    <% t++; %>\\r\\n  <% }); %>\\r\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\r\\n    </div>\\r\\n  <% } %>\\r\\n<% }); %>\\r\\n</div>\\r\\n';});\n\n",
        -    "define(\r\n  'libraryView',[\r\n    'App',\r\n    // Templates\r\n    'text!tpl/library.html'\r\n  ],\r\n  function(App, libraryTpl) {\r\n    var libraryView = Backbone.View.extend({\r\n      el: '#list',\r\n      events: {},\r\n      /**\r\n       * Init.\r\n       */\r\n      init: function() {\r\n        this.libraryTpl = _.template(libraryTpl);\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Render the list.\r\n       */\r\n      render: function(m, listCollection) {\r\n        if (m && listCollection) {\r\n          var self = this;\r\n\r\n          // Render items and group them by module\r\n          // module === group\r\n          this.groups = {};\r\n          _.each(m.items, function(item, i) {\r\n            var module = item.module || '_';\r\n            var group;\r\n            // Override default group with a selected category\r\n            // TODO: Overwriting with the first category might not be the best choice\r\n            // We might also want to have links for categories\r\n            if (item.category && item.category[0]) {\r\n              group = item.category[0];\r\n              // Populate item.hash\r\n              App.router.getHash(item);\r\n\r\n              // Create a group list without link hash\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: undefined,\r\n                  items: []\r\n                };\r\n              }\r\n            } else {\r\n              group = item.class || '_';\r\n              var hash = App.router.getHash(item);\r\n\r\n              var ind = hash.lastIndexOf('/');\r\n              hash = hash.substring(0, ind);\r\n\r\n              // Create a group list\r\n              if (!self.groups[group]) {\r\n                self.groups[group] = {\r\n                  name: group.replace('_', '&nbsp;'),\r\n                  module: module,\r\n                  hash: hash,\r\n                  items: []\r\n                };\r\n              }\r\n            }\r\n\r\n            self.groups[group].items.push(item);\r\n          });\r\n\r\n          // Sort groups by name A-Z\r\n          self.groups = _.sortBy(self.groups, this.sortByName);\r\n\r\n          // Put the <li> items html into the list <ul>\r\n          var libraryHtml = self.libraryTpl({\r\n            title: self.capitalizeFirst(listCollection),\r\n            module: m.module,\r\n            totalItems: m.items.length,\r\n            groups: self.groups\r\n          });\r\n\r\n          // Render the view\r\n          this.$el.html(libraryHtml);\r\n        }\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Show a list of items.\r\n       * @param {array} items Array of item objects.\r\n       * @returns {object} This view.\r\n       */\r\n      show: function(listGroup) {\r\n        if (App[listGroup]) {\r\n          this.render(App[listGroup], listGroup);\r\n        }\r\n        App.pageView.hideContentViews();\r\n\r\n        this.$el.show();\r\n\r\n        return this;\r\n      },\r\n      /**\r\n       * Helper method to capitalize the first letter of a string\r\n       * @param {string} str\r\n       * @returns {string} Returns the string.\r\n       */\r\n      capitalizeFirst: function(str) {\r\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\r\n      },\r\n      /**\r\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\r\n       * @param {string} a\r\n       * @param {string} b\r\n       * @returns {Array} Returns an array with elements sorted from A to Z.\r\n       */\r\n      sortAZ: function(a, b) {\r\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\r\n      },\r\n\r\n      sortByName: function(a, b) {\r\n        if (a.name === 'p5') return -1;\r\n        else return 0;\r\n      }\r\n    });\r\n\r\n    return libraryView;\r\n  }\r\n);\r\n\n",
        -    "define('pageView',[\r\n  'App',\r\n\r\n  // Views\r\n  'searchView',\r\n  'listView',\r\n  'itemView',\r\n  'menuView',\r\n  'libraryView'\r\n], function(App, searchView, listView, itemView, menuView, libraryView) {\r\n\r\n  // Store the original title parts so we can substitue different endings.\r\n  var _originalDocumentTitle = window.document.title;\r\n\r\n  var pageView = Backbone.View.extend({\r\n    el: 'body',\r\n    /**\r\n     * Init.\r\n     */\r\n    init: function() {\r\n      App.$container = $('#container');\r\n      App.contentViews = [];\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Render.\r\n     */\r\n    render: function() {\r\n\r\n      // Menu view\r\n      if (!App.menuView) {\r\n        App.menuView = new menuView();\r\n        App.menuView.init().render();\r\n      }\r\n\r\n      // Item view\r\n      if (!App.itemView) {\r\n        App.itemView = new itemView();\r\n        App.itemView.init().render();\r\n        // Add the item view to the views array\r\n        App.contentViews.push(App.itemView);\r\n      }\r\n\r\n      // List view\r\n      if (!App.listView) {\r\n        App.listView = new listView();\r\n        App.listView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.listView);\r\n      }\r\n\r\n      // Library view\r\n      if (!App.libraryView) {\r\n        App.libraryView = new libraryView();\r\n        App.libraryView.init().render();\r\n        // Add the list view to the views array\r\n        App.contentViews.push(App.libraryView);\r\n      }\r\n\r\n      // Search\r\n      if (!App.searchView) {\r\n        App.searchView = new searchView();\r\n        App.searchView.init().render();\r\n      }\r\n      return this;\r\n    },\r\n    /**\r\n     * Hide item and list views.\r\n     * @returns {object} This view.\r\n     */\r\n    hideContentViews: function() {\r\n      _.each(App.contentViews, function(view, i) {\r\n        view.$el.hide();\r\n      });\r\n\r\n      return this;\r\n    },\r\n    /**\r\n     * Append the supplied name to the first part of original document title.\r\n     * If no name is supplied, the title will reset to the original one.\r\n     */\r\n    appendToDocumentTitle: function(name){\r\n      if(name){\r\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\r\n        window.document.title = [firstTitlePart, name].join(\" | \");\r\n      } else {\r\n        window.document.title = _originalDocumentTitle;\r\n      }\r\n    }    \r\n  });\r\n\r\n  return pageView;\r\n\r\n});\r\n\n",
        -    "define('router',[\r\n  'App'\r\n], function(App) {\r\n\r\n  'use strict'; //\r\n\r\n  var Router = Backbone.Router.extend({\r\n\r\n    routes: {\r\n      '': 'list',\r\n      'p5': 'list',\r\n      'p5/': 'list',\r\n      'classes': 'list',\r\n      'search': 'search',\r\n      'libraries/:lib': 'library',\r\n      ':searchClass(/:searchItem)': 'get'\r\n    },\r\n    /**\r\n     * Whether the json API data was loaded.\r\n     */\r\n    _initialized: false,\r\n    /**\r\n     * Initialize the app: load json API data and create searchable arrays.\r\n     */\r\n    init: function(callback) {\r\n      var self = this;\r\n      require(['pageView'], function(pageView) {\r\n\r\n        // If already initialized, move away from here!\r\n        if (self._initialized) {\r\n          if (callback)\r\n            callback();\r\n          return;\r\n        }\r\n\r\n        // Update initialization state: must be done now to avoid recursive mess\r\n        self._initialized = true;\r\n\r\n        // Render views\r\n        if (!App.pageView) {\r\n          App.pageView = new pageView();\r\n          App.pageView.init().render();\r\n        }\r\n\r\n        // If a callback is set (a route has already been called), run it\r\n        // otherwise, show the default list\r\n        if (callback)\r\n          callback();\r\n        else\r\n          self.list();\r\n      });\r\n    },\r\n    /**\r\n     * Start route. Simply check if initialized.\r\n     */\r\n    start: function() {\r\n      this.init();\r\n    },\r\n    /**\r\n     * Show item details by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     */\r\n    get: function(searchClass, searchItem) {\r\n\r\n      // if looking for a library page, redirect\r\n      if (searchClass === 'p5.sound' && !searchItem) {\r\n        window.location.hash = '/libraries/'+searchClass;\r\n        return;\r\n      }\r\n\r\n      var self = this;\r\n      this.init(function() {\r\n        var item = self.getItem(searchClass, searchItem);\r\n\r\n        App.menuView.hide();\r\n\r\n        if (item) {\r\n          App.itemView.show(item);\r\n        } else {\r\n          //App.itemView.nothingFound();\r\n\r\n          self.list();\r\n        }\r\n\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Returns one item object by searching a class or a class item (method, property or event).\r\n     * @param {string} searchClass The class name (mandatory).\r\n     * @param {string} searchItem The class item name: can be a method, property or event name.\r\n     * @returns {object} The item found or undefined if nothing was found.\r\n     */\r\n    getItem: function(searchClass, searchItem) {\r\n      var classes = App.classes,\r\n              items = App.allItems,\r\n              classesCount = classes.length,\r\n              itemsCount = items.length,\r\n              className = searchClass ? searchClass.toLowerCase() : undefined,\r\n              itemName = searchItem ? searchItem : undefined,\r\n              found;\r\n\r\n      // Only search for a class, if itemName is undefined\r\n      if (className && !itemName) {\r\n        for (var i = 0; i < classesCount; i++) {\r\n          if (classes[i].name.toLowerCase() === className) {\r\n            found = classes[i];\r\n            _.each(found.items, function(i, idx) {\r\n              i.hash = App.router.getHash(i);\r\n            });\r\n            break;\r\n          }\r\n        }\r\n        // Search for a class item\r\n      } else if (className && itemName) {\r\n        // Search case sensitively\r\n        for (var i = 0; i < itemsCount; i++) {\r\n          if (items[i].class.toLowerCase() === className &&\r\n            items[i].name === itemName) {\r\n            found = items[i];\r\n            break;\r\n          }\r\n        }\r\n\r\n        // If no match was found, fallback to search case insensitively\r\n        if(!found){\r\n          for (var i = 0; i < itemsCount; i++) {\r\n            if(items[i].class.toLowerCase() === className &&\r\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\r\n              found = items[i];\r\n              break;\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      return found;\r\n    },\r\n    /**\r\n     * List items.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    list: function(collection) {\r\n\r\n      collection = 'allItems';\r\n\r\n      // Make sure collection is valid\r\n      if (App.collections.indexOf(collection) < 0) {\r\n        return;\r\n      }\r\n\r\n      this.init(function() {\r\n        App.menuView.show(collection);\r\n        App.menuView.update(collection);\r\n        App.listView.show(collection);\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Display information for a library.\r\n     * @param {string} collection The name of the collection to list.\r\n     */\r\n    library: function(collection) {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.libraryView.show(collection.substring(3)); //remove p5.\r\n        styleCodeLinks();\r\n      });\r\n    },\r\n    /**\r\n     * Close all content views.\r\n     */\r\n    search: function() {\r\n      this.init(function() {\r\n        App.menuView.hide();\r\n        App.pageView.hideContentViews();\r\n      });\r\n    },\r\n\r\n    /**\r\n     * Create an hash/url for the item.\r\n     * @param {Object} item A class, method, property or event object.\r\n     * @returns {String} The hash string, including the '#'.\r\n     */\r\n     getHash: function(item) {\r\n\r\n       if (!item.hash) {\r\n\r\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\r\n\r\n         if (item.class) {\r\n           var clsFunc = '#/' + item.class + '.' + item.name;\r\n           var idx = clsFunc.lastIndexOf('.');\r\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\r\n         } else {\r\n          item.hash = '#/' + item.name;\r\n         }\r\n       }\r\n\r\n       return item.hash;\r\n    }\r\n  });\r\n\r\n  \r\n  function styleCodeLinks() {\r\n    var links = document.getElementsByTagName(\"a\");\r\n    for (var iLink = 0; iLink < links.length; iLink++) {\r\n      var link = links[iLink];\r\n      if (link.hash.startsWith('#/p5')) {\r\n        link.classList.add('code');\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n  // Get the router\r\n  App.router = new Router();\r\n\r\n  // Start history\r\n  Backbone.history.start();\r\n\r\n  return App.router;\r\n\r\n});\r\n\n",
        -    "/**\r\n * Define global App.\r\n */\r\nvar App = window.App || {};\r\ndefine('App', [],function() {\r\n  return App;\r\n});\r\n\r\n/**\r\n * Load json API data and start the router.\r\n * @param {module} App\r\n * @param {module} router\r\n */\r\nrequire([\r\n  'App',\r\n  './documented-method'], function(App, DocumentedMethod) {\r\n\r\n  // Set collections\r\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];\r\n\r\n  // Get json API data\r\n  $.getJSON('data.min.json', function(data) {\r\n    App.data = data;\r\n    App.classes = [];\r\n    App.methods = [];\r\n    App.properties = [];\r\n    App.events = [];\r\n    App.allItems = [];\r\n    App.sound = { items: [] };\r\n    App.dom = { items: [] };\r\n    App.modules = [];\r\n    App.project = data.project;\r\n\r\n\r\n    var modules = data.modules;\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(modules, function(m, idx, array) {\r\n      App.modules.push(m);\r\n      if (m.name == \"p5.sound\") {\r\n        App.sound.module = m;\r\n      }\r\n    });\r\n\r\n\r\n    var items = data.classitems;\r\n    var classes = data.classes;\r\n\r\n    // Get classes\r\n    _.each(classes, function(c, idx, array) {\r\n      if (!c.private) {\r\n        App.classes.push(c);\r\n      }\r\n    });\r\n\r\n\r\n    // Get class items (methods, properties, events)\r\n    _.each(items, function(el, idx, array) {\r\n      if (el.itemtype) {\r\n        if (el.itemtype === \"method\") {\r\n          el = new DocumentedMethod(el);\r\n          App.methods.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"property\") {\r\n          App.properties.push(el);\r\n          App.allItems.push(el);\r\n        } else if (el.itemtype === \"event\") {\r\n          App.events.push(el);\r\n          App.allItems.push(el);\r\n        }\r\n\r\n        // libraries\r\n        if (el.module === \"p5.sound\") {\r\n          App.sound.items.push(el);\r\n        }\r\n      }\r\n    });\r\n\r\n    _.each(App.classes, function(c, idx) {\r\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\r\n    });\r\n\r\n    require(['router']);\r\n  });\r\n});\r\n\ndefine(\"main\", function(){});\n\n",
        +    "// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define('documented-method',[], factory);\n  } else if (typeof module === 'object' && module.exports) {\n    module.exports = factory();\n  } else {\n    root.DocumentedMethod = factory();\n  }\n}(this, function () {\n  function extend(target, src) {\n    Object.keys(src).forEach(function(prop) {\n      target[prop] = src[prop];\n    });\n    return target;\n  }\n\n  function DocumentedMethod(classitem) {\n    extend(this, classitem);\n\n    if (this.overloads) {\n      // Make each overload inherit properties from their parent\n      // classitem.\n      this.overloads = this.overloads.map(function(overload) {\n        return extend(Object.create(this), overload);\n      }, this);\n\n      if (this.params) {\n        throw new Error('params for overloaded methods should be undefined');\n      }\n\n      this.params = this._getMergedParams();\n    }\n  }\n\n  DocumentedMethod.prototype = {\n    // Merge parameters across all overloaded versions of this item.\n    _getMergedParams: function() {\n      var paramNames = {};\n      var params = [];\n\n      this.overloads.forEach(function(overload) {\n        if (!overload.params) {\n          return;\n        }\n        overload.params.forEach(function(param) {\n          if (param.name in paramNames) {\n            return;\n          }\n          paramNames[param.name] = param;\n          params.push(param);\n        });\n      });\n\n      return params;\n    }\n  };\n\n  return DocumentedMethod;\n}));\n\n",
        +    "/**\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/requirejs/text for details\n */\n/*jslint regexp: true */\n/*global require, XMLHttpRequest, ActiveXObject,\n  define, window, process, Packages,\n  java, location, Components, FileUtils */\n\ndefine('text',['module'], function (module) {\n    'use strict';\n\n    var text, fs, Cc, Ci, xpcIsWindows,\n        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],\n        xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        hasLocation = typeof location !== 'undefined' && location.href,\n        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\\:/, ''),\n        defaultHostName = hasLocation && location.hostname,\n        defaultPort = hasLocation && (location.port || undefined),\n        buildMap = {},\n        masterConfig = (module.config && module.config()) || {};\n\n    text = {\n        version: '2.0.10',\n\n        strip: function (content) {\n            //Strips <?xml ...?> declarations so that external SVG and XML\n            //documents can be added to a document without worry. Also, if the string\n            //is an HTML document, only the part inside the body tag is returned.\n            if (content) {\n                content = content.replace(xmlRegExp, \"\");\n                var matches = content.match(bodyRegExp);\n                if (matches) {\n                    content = matches[1];\n                }\n            } else {\n                content = \"\";\n            }\n            return content;\n        },\n\n        jsEscape: function (content) {\n            return content.replace(/(['\\\\])/g, '\\\\$1')\n                .replace(/[\\f]/g, \"\\\\f\")\n                .replace(/[\\b]/g, \"\\\\b\")\n                .replace(/[\\n]/g, \"\\\\n\")\n                .replace(/[\\t]/g, \"\\\\t\")\n                .replace(/[\\r]/g, \"\\\\r\")\n                .replace(/[\\u2028]/g, \"\\\\u2028\")\n                .replace(/[\\u2029]/g, \"\\\\u2029\");\n        },\n\n        createXhr: masterConfig.createXhr || function () {\n            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n            var xhr, i, progId;\n            if (typeof XMLHttpRequest !== \"undefined\") {\n                return new XMLHttpRequest();\n            } else if (typeof ActiveXObject !== \"undefined\") {\n                for (i = 0; i < 3; i += 1) {\n                    progId = progIds[i];\n                    try {\n                        xhr = new ActiveXObject(progId);\n                    } catch (e) {}\n\n                    if (xhr) {\n                        progIds = [progId];  // so faster next time\n                        break;\n                    }\n                }\n            }\n\n            return xhr;\n        },\n\n        /**\n         * Parses a resource name into its component parts. Resource names\n         * look like: module/name.ext!strip, where the !strip part is\n         * optional.\n         * @param {String} name the resource name\n         * @returns {Object} with properties \"moduleName\", \"ext\" and \"strip\"\n         * where strip is a boolean.\n         */\n        parseName: function (name) {\n            var modName, ext, temp,\n                strip = false,\n                index = name.indexOf(\".\"),\n                isRelative = name.indexOf('./') === 0 ||\n                             name.indexOf('../') === 0;\n\n            if (index !== -1 && (!isRelative || index > 1)) {\n                modName = name.substring(0, index);\n                ext = name.substring(index + 1, name.length);\n            } else {\n                modName = name;\n            }\n\n            temp = ext || modName;\n            index = temp.indexOf(\"!\");\n            if (index !== -1) {\n                //Pull off the strip arg.\n                strip = temp.substring(index + 1) === \"strip\";\n                temp = temp.substring(0, index);\n                if (ext) {\n                    ext = temp;\n                } else {\n                    modName = temp;\n                }\n            }\n\n            return {\n                moduleName: modName,\n                ext: ext,\n                strip: strip\n            };\n        },\n\n        xdRegExp: /^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,\n\n        /**\n         * Is an URL on another domain. Only works for browser use, returns\n         * false in non-browser environments. Only used to know if an\n         * optimized .js version of a text resource should be loaded\n         * instead.\n         * @param {String} url\n         * @returns Boolean\n         */\n        useXhr: function (url, protocol, hostname, port) {\n            var uProtocol, uHostName, uPort,\n                match = text.xdRegExp.exec(url);\n            if (!match) {\n                return true;\n            }\n            uProtocol = match[2];\n            uHostName = match[3];\n\n            uHostName = uHostName.split(':');\n            uPort = uHostName[1];\n            uHostName = uHostName[0];\n\n            return (!uProtocol || uProtocol === protocol) &&\n                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&\n                   ((!uPort && !uHostName) || uPort === port);\n        },\n\n        finishLoad: function (name, strip, content, onLoad) {\n            content = strip ? text.strip(content) : content;\n            if (masterConfig.isBuild) {\n                buildMap[name] = content;\n            }\n            onLoad(content);\n        },\n\n        load: function (name, req, onLoad, config) {\n            //Name has format: some.module.filext!strip\n            //The strip part is optional.\n            //if strip is present, then that means only get the string contents\n            //inside a body tag in an HTML string. For XML/SVG content it means\n            //removing the <?xml ...?> declarations so the content can be inserted\n            //into the current doc without problems.\n\n            // Do not bother with the work if a build and text will\n            // not be inlined.\n            if (config.isBuild && !config.inlineText) {\n                onLoad();\n                return;\n            }\n\n            masterConfig.isBuild = config.isBuild;\n\n            var parsed = text.parseName(name),\n                nonStripName = parsed.moduleName +\n                    (parsed.ext ? '.' + parsed.ext : ''),\n                url = req.toUrl(nonStripName),\n                useXhr = (masterConfig.useXhr) ||\n                         text.useXhr;\n\n            // Do not load if it is an empty: url\n            if (url.indexOf('empty:') === 0) {\n                onLoad();\n                return;\n            }\n\n            //Load the text. Use XHR if possible and in a browser.\n            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {\n                text.get(url, function (content) {\n                    text.finishLoad(name, parsed.strip, content, onLoad);\n                }, function (err) {\n                    if (onLoad.error) {\n                        onLoad.error(err);\n                    }\n                });\n            } else {\n                //Need to fetch the resource across domains. Assume\n                //the resource has been optimized into a JS module. Fetch\n                //by the module name + extension, but do not include the\n                //!strip part to avoid file system issues.\n                req([nonStripName], function (content) {\n                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,\n                                    parsed.strip, content, onLoad);\n                });\n            }\n        },\n\n        write: function (pluginName, moduleName, write, config) {\n            if (buildMap.hasOwnProperty(moduleName)) {\n                var content = text.jsEscape(buildMap[moduleName]);\n                write.asModule(pluginName + \"!\" + moduleName,\n                               \"define(function () { return '\" +\n                                   content +\n                               \"';});\\n\");\n            }\n        },\n\n        writeFile: function (pluginName, moduleName, req, write, config) {\n            var parsed = text.parseName(moduleName),\n                extPart = parsed.ext ? '.' + parsed.ext : '',\n                nonStripName = parsed.moduleName + extPart,\n                //Use a '.js' file name so that it indicates it is a\n                //script that can be loaded across domains.\n                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';\n\n            //Leverage own load() method to load plugin value, but only\n            //write out values that do not have the strip argument,\n            //to avoid any potential issues with ! in file names.\n            text.load(nonStripName, req, function (value) {\n                //Use own write() method to construct full module value.\n                //But need to create shell that translates writeFile's\n                //write() to the right interface.\n                var textWrite = function (contents) {\n                    return write(fileName, contents);\n                };\n                textWrite.asModule = function (moduleName, contents) {\n                    return write.asModule(moduleName, fileName, contents);\n                };\n\n                text.write(pluginName, nonStripName, textWrite, config);\n            }, config);\n        }\n    };\n\n    if (masterConfig.env === 'node' || (!masterConfig.env &&\n            typeof process !== \"undefined\" &&\n            process.versions &&\n            !!process.versions.node &&\n            !process.versions['node-webkit'])) {\n        //Using special require.nodeRequire, something added by r.js.\n        fs = require.nodeRequire('fs');\n\n        text.get = function (url, callback, errback) {\n            try {\n                var file = fs.readFileSync(url, 'utf8');\n                //Remove BOM (Byte Mark Order) from utf8 files if it is there.\n                if (file.indexOf('\\uFEFF') === 0) {\n                    file = file.substring(1);\n                }\n                callback(file);\n            } catch (e) {\n                errback(e);\n            }\n        };\n    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&\n            text.createXhr())) {\n        text.get = function (url, callback, errback, headers) {\n            var xhr = text.createXhr(), header;\n            xhr.open('GET', url, true);\n\n            //Allow plugins direct access to xhr headers\n            if (headers) {\n                for (header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                    }\n                }\n            }\n\n            //Allow overrides specified in config\n            if (masterConfig.onXhr) {\n                masterConfig.onXhr(xhr, url);\n            }\n\n            xhr.onreadystatechange = function (evt) {\n                var status, err;\n                //Do not explicitly handle errors, those should be\n                //visible via console output in the browser.\n                if (xhr.readyState === 4) {\n                    status = xhr.status;\n                    if (status > 399 && status < 600) {\n                        //An http 4xx or 5xx error. Signal an error.\n                        err = new Error(url + ' HTTP status: ' + status);\n                        err.xhr = xhr;\n                        errback(err);\n                    } else {\n                        callback(xhr.responseText);\n                    }\n\n                    if (masterConfig.onXhrComplete) {\n                        masterConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            };\n            xhr.send(null);\n        };\n    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&\n            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {\n        //Why Java, why is this so awkward?\n        text.get = function (url, callback) {\n            var stringBuffer, line,\n                encoding = \"utf-8\",\n                file = new java.io.File(url),\n                lineSeparator = java.lang.System.getProperty(\"line.separator\"),\n                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),\n                content = '';\n            try {\n                stringBuffer = new java.lang.StringBuffer();\n                line = input.readLine();\n\n                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324\n                // http://www.unicode.org/faq/utf_bom.html\n\n                // Note that when we use utf-8, the BOM should appear as \"EF BB BF\", but it doesn't due to this bug in the JDK:\n                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058\n                if (line && line.length() && line.charAt(0) === 0xfeff) {\n                    // Eat the BOM, since we've already found the encoding on this file,\n                    // and we plan to concatenating this buffer with others; the BOM should\n                    // only appear at the top of a file.\n                    line = line.substring(1);\n                }\n\n                if (line !== null) {\n                    stringBuffer.append(line);\n                }\n\n                while ((line = input.readLine()) !== null) {\n                    stringBuffer.append(lineSeparator);\n                    stringBuffer.append(line);\n                }\n                //Make sure we return a JavaScript string and not a Java string.\n                content = String(stringBuffer.toString()); //String\n            } finally {\n                input.close();\n            }\n            callback(content);\n        };\n    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&\n            typeof Components !== 'undefined' && Components.classes &&\n            Components.interfaces)) {\n        //Avert your gaze!\n        Cc = Components.classes,\n        Ci = Components.interfaces;\n        Components.utils['import']('resource://gre/modules/FileUtils.jsm');\n        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);\n\n        text.get = function (url, callback) {\n            var inStream, convertStream, fileObj,\n                readData = {};\n\n            if (xpcIsWindows) {\n                url = url.replace(/\\//g, '\\\\');\n            }\n\n            fileObj = new FileUtils.File(url);\n\n            //XPCOM, you so crazy\n            try {\n                inStream = Cc['@mozilla.org/network/file-input-stream;1']\n                           .createInstance(Ci.nsIFileInputStream);\n                inStream.init(fileObj, 1, 0, false);\n\n                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']\n                                .createInstance(Ci.nsIConverterInputStream);\n                convertStream.init(inStream, \"utf-8\", inStream.available(),\n                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);\n\n                convertStream.readString(inStream.available(), readData);\n                convertStream.close();\n                inStream.close();\n                callback(readData.value);\n            } catch (e) {\n                throw new Error((fileObj && fileObj.path || '') + ': ' + e);\n            }\n        };\n    }\n    return text;\n});\n\n",
        +    "\ndefine('text!tpl/search.html',[],function () { return '<h2 class=\"sr-only\">search</h2>\\n<form>\\n  <input id=\"search_reference_field\" type=\"text\" class=\"<%=className%>\" value=\"\" placeholder=\"<%=placeholder%>\" aria-label=\"search reference\">\\n  <label class=\"sr-only\" for=\"search_reference_field\">Search reference</label>\\n</form>\\n\\n';});\n\n",
        +    "\ndefine('text!tpl/search_suggestion.html',[],function () { return '<p id=\"index-<%=idx%>\" class=\"search-suggestion\">\\n\\n  <strong><%=name%></strong>\\n\\n  <span class=\"small\">\\n    <% if (final) { %>\\n    constant\\n    <% } else if (itemtype) { %>\\n    <%=itemtype%> \\n    <% } %>\\n\\n    <% if (className) { %>\\n    in <strong><%=className%></strong>\\n    <% } %>\\n\\n    <% if (typeof is_constructor !== \\'undefined\\' && is_constructor) { %>\\n    <strong><span class=\"glyphicon glyphicon-star\"></span> constructor</strong>\\n    <% } %>\\n  </span>\\n\\n</p>';});\n\n",
        +    "/*!\n * typeahead.js 0.10.2\n * https://github.com/twitter/typeahead.js\n * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT\n */\ndefine('typeahead',[], function() {\n\n//(function($) {\n\n\n    var _ = {\n        isMsie: function() {\n            return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\\d+(.\\d+)?)/i)[2] : false;\n        },\n        isBlankString: function(str) {\n            return !str || /^\\s*$/.test(str);\n        },\n        escapeRegExChars: function(str) {\n            return str.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, \"\\\\$&\");\n        },\n        isString: function(obj) {\n            return typeof obj === \"string\";\n        },\n        isNumber: function(obj) {\n            return typeof obj === \"number\";\n        },\n        isArray: $.isArray,\n        isFunction: $.isFunction,\n        isObject: $.isPlainObject,\n        isUndefined: function(obj) {\n            return typeof obj === \"undefined\";\n        },\n        bind: $.proxy,\n        each: function(collection, cb) {\n            $.each(collection, reverseArgs);\n            function reverseArgs(index, value) {\n                return cb(value, index);\n            }\n        },\n        map: $.map,\n        filter: $.grep,\n        every: function(obj, test) {\n            var result = true;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (!(result = test.call(null, val, key, obj))) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        some: function(obj, test) {\n            var result = false;\n            if (!obj) {\n                return result;\n            }\n            $.each(obj, function(key, val) {\n                if (result = test.call(null, val, key, obj)) {\n                    return false;\n                }\n            });\n            return !!result;\n        },\n        mixin: $.extend,\n        getUniqueId: function() {\n            var counter = 0;\n            return function() {\n                return counter++;\n            };\n        }(),\n        templatify: function templatify(obj) {\n            return $.isFunction(obj) ? obj : template;\n            function template() {\n                return String(obj);\n            }\n        },\n        defer: function(fn) {\n            setTimeout(fn, 0);\n        },\n        debounce: function(func, wait, immediate) {\n            var timeout, result;\n            return function() {\n                var context = this, args = arguments, later, callNow;\n                later = function() {\n                    timeout = null;\n                    if (!immediate) {\n                        result = func.apply(context, args);\n                    }\n                };\n                callNow = immediate && !timeout;\n                clearTimeout(timeout);\n                timeout = setTimeout(later, wait);\n                if (callNow) {\n                    result = func.apply(context, args);\n                }\n                return result;\n            };\n        },\n        throttle: function(func, wait) {\n            var context, args, timeout, result, previous, later;\n            previous = 0;\n            later = function() {\n                previous = new Date();\n                timeout = null;\n                result = func.apply(context, args);\n            };\n            return function() {\n                var now = new Date(), remaining = wait - (now - previous);\n                context = this;\n                args = arguments;\n                if (remaining <= 0) {\n                    clearTimeout(timeout);\n                    timeout = null;\n                    previous = now;\n                    result = func.apply(context, args);\n                } else if (!timeout) {\n                    timeout = setTimeout(later, remaining);\n                }\n                return result;\n            };\n        },\n        noop: function() {}\n    };\n    var VERSION = \"0.10.2\";\n    var tokenizers = function(root) {\n        return {\n            nonword: nonword,\n            whitespace: whitespace,\n            obj: {\n                nonword: getObjTokenizer(nonword),\n                whitespace: getObjTokenizer(whitespace)\n            }\n        };\n        function whitespace(s) {\n            return s.split(/\\s+/);\n        }\n        function nonword(s) {\n            return s.split(/\\W+/);\n        }\n        function getObjTokenizer(tokenizer) {\n            return function setKey(key) {\n                return function tokenize(o) {\n                    return tokenizer(o[key]);\n                };\n            };\n        }\n    }();\n    var LruCache = function() {\n        function LruCache(maxSize) {\n            this.maxSize = maxSize || 100;\n            this.size = 0;\n            this.hash = {};\n            this.list = new List();\n        }\n        _.mixin(LruCache.prototype, {\n            set: function set(key, val) {\n                var tailItem = this.list.tail, node;\n                if (this.size >= this.maxSize) {\n                    this.list.remove(tailItem);\n                    delete this.hash[tailItem.key];\n                }\n                if (node = this.hash[key]) {\n                    node.val = val;\n                    this.list.moveToFront(node);\n                } else {\n                    node = new Node(key, val);\n                    this.list.add(node);\n                    this.hash[key] = node;\n                    this.size++;\n                }\n            },\n            get: function get(key) {\n                var node = this.hash[key];\n                if (node) {\n                    this.list.moveToFront(node);\n                    return node.val;\n                }\n            }\n        });\n        function List() {\n            this.head = this.tail = null;\n        }\n        _.mixin(List.prototype, {\n            add: function add(node) {\n                if (this.head) {\n                    node.next = this.head;\n                    this.head.prev = node;\n                }\n                this.head = node;\n                this.tail = this.tail || node;\n            },\n            remove: function remove(node) {\n                node.prev ? node.prev.next = node.next : this.head = node.next;\n                node.next ? node.next.prev = node.prev : this.tail = node.prev;\n            },\n            moveToFront: function(node) {\n                this.remove(node);\n                this.add(node);\n            }\n        });\n        function Node(key, val) {\n            this.key = key;\n            this.val = val;\n            this.prev = this.next = null;\n        }\n        return LruCache;\n    }();\n    var PersistentStorage = function() {\n        var ls, methods;\n        try {\n            ls = window.localStorage;\n            ls.setItem(\"~~~\", \"!\");\n            ls.removeItem(\"~~~\");\n        } catch (err) {\n            ls = null;\n        }\n        function PersistentStorage(namespace) {\n            this.prefix = [ \"__\", namespace, \"__\" ].join(\"\");\n            this.ttlKey = \"__ttl__\";\n            this.keyMatcher = new RegExp(\"^\" + this.prefix);\n        }\n        if (ls && window.JSON) {\n            methods = {\n                _prefix: function(key) {\n                    return this.prefix + key;\n                },\n                _ttlKey: function(key) {\n                    return this._prefix(key) + this.ttlKey;\n                },\n                get: function(key) {\n                    if (this.isExpired(key)) {\n                        this.remove(key);\n                    }\n                    return decode(ls.getItem(this._prefix(key)));\n                },\n                set: function(key, val, ttl) {\n                    if (_.isNumber(ttl)) {\n                        ls.setItem(this._ttlKey(key), encode(now() + ttl));\n                    } else {\n                        ls.removeItem(this._ttlKey(key));\n                    }\n                    return ls.setItem(this._prefix(key), encode(val));\n                },\n                remove: function(key) {\n                    ls.removeItem(this._ttlKey(key));\n                    ls.removeItem(this._prefix(key));\n                    return this;\n                },\n                clear: function() {\n                    var i, key, keys = [], len = ls.length;\n                    for (i = 0; i < len; i++) {\n                        if ((key = ls.key(i)).match(this.keyMatcher)) {\n                            keys.push(key.replace(this.keyMatcher, \"\"));\n                        }\n                    }\n                    for (i = keys.length; i--; ) {\n                        this.remove(keys[i]);\n                    }\n                    return this;\n                },\n                isExpired: function(key) {\n                    var ttl = decode(ls.getItem(this._ttlKey(key)));\n                    return _.isNumber(ttl) && now() > ttl ? true : false;\n                }\n            };\n        } else {\n            methods = {\n                get: _.noop,\n                set: _.noop,\n                remove: _.noop,\n                clear: _.noop,\n                isExpired: _.noop\n            };\n        }\n        _.mixin(PersistentStorage.prototype, methods);\n        return PersistentStorage;\n        function now() {\n            return new Date().getTime();\n        }\n        function encode(val) {\n            return JSON.stringify(_.isUndefined(val) ? null : val);\n        }\n        function decode(val) {\n            return JSON.parse(val);\n        }\n    }();\n    var Transport = function() {\n        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, requestCache = new LruCache(10);\n        function Transport(o) {\n            o = o || {};\n            this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;\n            this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;\n        }\n        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {\n            maxPendingRequests = num;\n        };\n        Transport.resetCache = function clearCache() {\n            requestCache = new LruCache(10);\n        };\n        _.mixin(Transport.prototype, {\n            _get: function(url, o, cb) {\n                var that = this, jqXhr;\n                if (jqXhr = pendingRequests[url]) {\n                    jqXhr.done(done).fail(fail);\n                } else if (pendingRequestsCount < maxPendingRequests) {\n                    pendingRequestsCount++;\n                    pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);\n                } else {\n                    this.onDeckRequestArgs = [].slice.call(arguments, 0);\n                }\n                function done(resp) {\n                    cb && cb(null, resp);\n                    requestCache.set(url, resp);\n                }\n                function fail() {\n                    cb && cb(true);\n                }\n                function always() {\n                    pendingRequestsCount--;\n                    delete pendingRequests[url];\n                    if (that.onDeckRequestArgs) {\n                        that._get.apply(that, that.onDeckRequestArgs);\n                        that.onDeckRequestArgs = null;\n                    }\n                }\n            },\n            get: function(url, o, cb) {\n                var resp;\n                if (_.isFunction(o)) {\n                    cb = o;\n                    o = {};\n                }\n                if (resp = requestCache.get(url)) {\n                    _.defer(function() {\n                        cb && cb(null, resp);\n                    });\n                } else {\n                    this._get(url, o, cb);\n                }\n                return !!resp;\n            }\n        });\n        return Transport;\n        function callbackToDeferred(fn) {\n            return function customSendWrapper(url, o) {\n                var deferred = $.Deferred();\n                fn(url, o, onSuccess, onError);\n                return deferred;\n                function onSuccess(resp) {\n                    _.defer(function() {\n                        deferred.resolve(resp);\n                    });\n                }\n                function onError(err) {\n                    _.defer(function() {\n                        deferred.reject(err);\n                    });\n                }\n            };\n        }\n    }();\n    var SearchIndex = function() {\n        function SearchIndex(o) {\n            o = o || {};\n            if (!o.datumTokenizer || !o.queryTokenizer) {\n                $.error(\"datumTokenizer and queryTokenizer are both required\");\n            }\n            this.datumTokenizer = o.datumTokenizer;\n            this.queryTokenizer = o.queryTokenizer;\n            this.reset();\n        }\n        _.mixin(SearchIndex.prototype, {\n            bootstrap: function bootstrap(o) {\n                this.datums = o.datums;\n                this.trie = o.trie;\n            },\n            add: function(data) {\n                var that = this;\n                data = _.isArray(data) ? data : [ data ];\n                _.each(data, function(datum) {\n                    var id, tokens;\n                    id = that.datums.push(datum) - 1;\n                    tokens = normalizeTokens(that.datumTokenizer(datum));\n                    _.each(tokens, function(token) {\n                        var node, chars, ch;\n                        node = that.trie;\n                        chars = token.split(\"\");\n                        while (ch = chars.shift()) {\n                            node = node.children[ch] || (node.children[ch] = newNode());\n                            node.ids.push(id);\n                        }\n                    });\n                });\n            },\n            get: function get(query) {\n                var that = this, tokens, matches;\n                tokens = normalizeTokens(this.queryTokenizer(query));\n                _.each(tokens, function(token) {\n                    var node, chars, ch, ids;\n                    if (matches && matches.length === 0) {\n                        return false;\n                    }\n                    node = that.trie;\n                    chars = token.split(\"\");\n                    while (node && (ch = chars.shift())) {\n                        node = node.children[ch];\n                    }\n                    if (node && chars.length === 0) {\n                        ids = node.ids.slice(0);\n                        matches = matches ? getIntersection(matches, ids) : ids;\n                    } else {\n                        matches = [];\n                        return false;\n                    }\n                });\n                return matches ? _.map(unique(matches), function(id) {\n                    return that.datums[id];\n                }) : [];\n            },\n            reset: function reset() {\n                this.datums = [];\n                this.trie = newNode();\n            },\n            serialize: function serialize() {\n                return {\n                    datums: this.datums,\n                    trie: this.trie\n                };\n            }\n        });\n        return SearchIndex;\n        function normalizeTokens(tokens) {\n            tokens = _.filter(tokens, function(token) {\n                return !!token;\n            });\n            tokens = _.map(tokens, function(token) {\n                return token.toLowerCase();\n            });\n            return tokens;\n        }\n        function newNode() {\n            return {\n                ids: [],\n                children: {}\n            };\n        }\n        function unique(array) {\n            var seen = {}, uniques = [];\n            for (var i = 0; i < array.length; i++) {\n                if (!seen[array[i]]) {\n                    seen[array[i]] = true;\n                    uniques.push(array[i]);\n                }\n            }\n            return uniques;\n        }\n        function getIntersection(arrayA, arrayB) {\n            var ai = 0, bi = 0, intersection = [];\n            arrayA = arrayA.sort(compare);\n            arrayB = arrayB.sort(compare);\n            while (ai < arrayA.length && bi < arrayB.length) {\n                if (arrayA[ai] < arrayB[bi]) {\n                    ai++;\n                } else if (arrayA[ai] > arrayB[bi]) {\n                    bi++;\n                } else {\n                    intersection.push(arrayA[ai]);\n                    ai++;\n                    bi++;\n                }\n            }\n            return intersection;\n            function compare(a, b) {\n                return a - b;\n            }\n        }\n    }();\n    var oParser = function() {\n        return {\n            local: getLocal,\n            prefetch: getPrefetch,\n            remote: getRemote\n        };\n        function getLocal(o) {\n            return o.local || null;\n        }\n        function getPrefetch(o) {\n            var prefetch, defaults;\n            defaults = {\n                url: null,\n                thumbprint: \"\",\n                ttl: 24 * 60 * 60 * 1e3,\n                filter: null,\n                ajax: {}\n            };\n            if (prefetch = o.prefetch || null) {\n                prefetch = _.isString(prefetch) ? {\n                    url: prefetch\n                } : prefetch;\n                prefetch = _.mixin(defaults, prefetch);\n                prefetch.thumbprint = VERSION + prefetch.thumbprint;\n                prefetch.ajax.type = prefetch.ajax.type || \"GET\";\n                prefetch.ajax.dataType = prefetch.ajax.dataType || \"json\";\n                !prefetch.url && $.error(\"prefetch requires url to be set\");\n            }\n            return prefetch;\n        }\n        function getRemote(o) {\n            var remote, defaults;\n            defaults = {\n                url: null,\n                wildcard: \"%QUERY\",\n                replace: null,\n                rateLimitBy: \"debounce\",\n                rateLimitWait: 300,\n                send: null,\n                filter: null,\n                ajax: {}\n            };\n            if (remote = o.remote || null) {\n                remote = _.isString(remote) ? {\n                    url: remote\n                } : remote;\n                remote = _.mixin(defaults, remote);\n                remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);\n                remote.ajax.type = remote.ajax.type || \"GET\";\n                remote.ajax.dataType = remote.ajax.dataType || \"json\";\n                delete remote.rateLimitBy;\n                delete remote.rateLimitWait;\n                !remote.url && $.error(\"remote requires url to be set\");\n            }\n            return remote;\n            function byDebounce(wait) {\n                return function(fn) {\n                    return _.debounce(fn, wait);\n                };\n            }\n            function byThrottle(wait) {\n                return function(fn) {\n                    return _.throttle(fn, wait);\n                };\n            }\n        }\n    }();\n    (function(root) {\n        var old, keys;\n        old = root.Bloodhound;\n        keys = {\n            data: \"data\",\n            protocol: \"protocol\",\n            thumbprint: \"thumbprint\"\n        };\n        root.Bloodhound = Bloodhound;\n        function Bloodhound(o) {\n            if (!o || !o.local && !o.prefetch && !o.remote) {\n                $.error(\"one of local, prefetch, or remote is required\");\n            }\n            this.limit = o.limit || 5;\n            this.sorter = getSorter(o.sorter);\n            this.dupDetector = o.dupDetector || ignoreDuplicates;\n            this.local = oParser.local(o);\n            this.prefetch = oParser.prefetch(o);\n            this.remote = oParser.remote(o);\n            this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;\n            this.index = new SearchIndex({\n                datumTokenizer: o.datumTokenizer,\n                queryTokenizer: o.queryTokenizer\n            });\n            this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;\n        }\n        Bloodhound.noConflict = function noConflict() {\n            root.Bloodhound = old;\n            return Bloodhound;\n        };\n        Bloodhound.tokenizers = tokenizers;\n        _.mixin(Bloodhound.prototype, {\n            _loadPrefetch: function loadPrefetch(o) {\n                var that = this, serialized, deferred;\n                if (serialized = this._readFromStorage(o.thumbprint)) {\n                    this.index.bootstrap(serialized);\n                    deferred = $.Deferred().resolve();\n                } else {\n                    deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);\n                }\n                return deferred;\n                function handlePrefetchResponse(resp) {\n                    that.clear();\n                    that.add(o.filter ? o.filter(resp) : resp);\n                    that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);\n                }\n            },\n            _getFromRemote: function getFromRemote(query, cb) {\n                var that = this, url, uriEncodedQuery;\n                query = query || \"\";\n                uriEncodedQuery = encodeURIComponent(query);\n                url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);\n                return this.transport.get(url, this.remote.ajax, handleRemoteResponse);\n                function handleRemoteResponse(err, resp) {\n                    err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);\n                }\n            },\n            _saveToStorage: function saveToStorage(data, thumbprint, ttl) {\n                if (this.storage) {\n                    this.storage.set(keys.data, data, ttl);\n                    this.storage.set(keys.protocol, location.protocol, ttl);\n                    this.storage.set(keys.thumbprint, thumbprint, ttl);\n                }\n            },\n            _readFromStorage: function readFromStorage(thumbprint) {\n                var stored = {}, isExpired;\n                if (this.storage) {\n                    stored.data = this.storage.get(keys.data);\n                    stored.protocol = this.storage.get(keys.protocol);\n                    stored.thumbprint = this.storage.get(keys.thumbprint);\n                }\n                isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;\n                return stored.data && !isExpired ? stored.data : null;\n            },\n            _initialize: function initialize() {\n                var that = this, local = this.local, deferred;\n                deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();\n                local && deferred.done(addLocalToIndex);\n                this.transport = this.remote ? new Transport(this.remote) : null;\n                return this.initPromise = deferred.promise();\n                function addLocalToIndex() {\n                    that.add(_.isFunction(local) ? local() : local);\n                }\n            },\n            initialize: function initialize(force) {\n                return !this.initPromise || force ? this._initialize() : this.initPromise;\n            },\n            add: function add(data) {\n                this.index.add(data);\n            },\n            get: function get(query, cb) {\n                var that = this, matches = [], cacheHit = false;\n                matches = this.index.get(query);\n                matches = this.sorter(matches).slice(0, this.limit);\n                if (matches.length < this.limit && this.transport) {\n                    cacheHit = this._getFromRemote(query, returnRemoteMatches);\n                }\n                if (!cacheHit) {\n                    (matches.length > 0 || !this.transport) && cb && cb(matches);\n                }\n                function returnRemoteMatches(remoteMatches) {\n                    var matchesWithBackfill = matches.slice(0);\n                    _.each(remoteMatches, function(remoteMatch) {\n                        var isDuplicate;\n                        isDuplicate = _.some(matchesWithBackfill, function(match) {\n                            return that.dupDetector(remoteMatch, match);\n                        });\n                        !isDuplicate && matchesWithBackfill.push(remoteMatch);\n                        return matchesWithBackfill.length < that.limit;\n                    });\n                    cb && cb(that.sorter(matchesWithBackfill));\n                }\n            },\n            clear: function clear() {\n                this.index.reset();\n            },\n            clearPrefetchCache: function clearPrefetchCache() {\n                this.storage && this.storage.clear();\n            },\n            clearRemoteCache: function clearRemoteCache() {\n                this.transport && Transport.resetCache();\n            },\n            ttAdapter: function ttAdapter() {\n                return _.bind(this.get, this);\n            }\n        });\n        return Bloodhound;\n        function getSorter(sortFn) {\n            return _.isFunction(sortFn) ? sort : noSort;\n            function sort(array) {\n                return array.sort(sortFn);\n            }\n            function noSort(array) {\n                return array;\n            }\n        }\n        function ignoreDuplicates() {\n            return false;\n        }\n    })(this);\n    var html = {\n        wrapper: '<span class=\"twitter-typeahead\"></span>',\n        dropdown: '<span class=\"tt-dropdown-menu\"></span>',\n        dataset: '<div class=\"tt-dataset-%CLASS%\"></div>',\n        suggestions: '<span class=\"tt-suggestions\"></span>',\n        suggestion: '<div class=\"tt-suggestion\"></div>'\n    };\n    var css = {\n        wrapper: {\n            position: \"relative\",\n            display: \"inline-block\"\n        },\n        hint: {\n            position: \"absolute\",\n            top: \"0\",\n            left: \"0\",\n            borderColor: \"transparent\",\n            boxShadow: \"none\"\n        },\n        input: {\n            position: \"relative\",\n            verticalAlign: \"top\",\n            backgroundColor: \"transparent\"\n        },\n        inputWithNoHint: {\n            position: \"relative\",\n            verticalAlign: \"top\"\n        },\n        dropdown: {\n            position: \"absolute\",\n            top: \"100%\",\n            left: \"0\",\n            zIndex: \"100\",\n            display: \"none\"\n        },\n        suggestions: {\n            display: \"block\"\n        },\n        suggestion: {\n            whiteSpace: \"nowrap\",\n            cursor: \"pointer\"\n        },\n        suggestionChild: {\n            whiteSpace: \"normal\"\n        },\n        ltr: {\n            left: \"0\",\n            right: \"auto\"\n        },\n        rtl: {\n            left: \"auto\",\n            right: \" 0\"\n        }\n    };\n    if (_.isMsie()) {\n        _.mixin(css.input, {\n            backgroundImage: \"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)\"\n        });\n    }\n    if (_.isMsie() && _.isMsie() <= 7) {\n        _.mixin(css.input, {\n            marginTop: \"-1px\"\n        });\n    }\n    var EventBus = function() {\n        var namespace = \"typeahead:\";\n        function EventBus(o) {\n            if (!o || !o.el) {\n                $.error(\"EventBus initialized without el\");\n            }\n            this.$el = $(o.el);\n        }\n        _.mixin(EventBus.prototype, {\n            trigger: function(type) {\n                var args = [].slice.call(arguments, 1);\n                this.$el.trigger(namespace + type, args);\n            }\n        });\n        return EventBus;\n    }();\n    var EventEmitter = function() {\n        var splitter = /\\s+/, nextTick = getNextTick();\n        return {\n            onSync: onSync,\n            onAsync: onAsync,\n            off: off,\n            trigger: trigger\n        };\n        function on(method, types, cb, context) {\n            var type;\n            if (!cb) {\n                return this;\n            }\n            types = types.split(splitter);\n            cb = context ? bindContext(cb, context) : cb;\n            this._callbacks = this._callbacks || {};\n            while (type = types.shift()) {\n                this._callbacks[type] = this._callbacks[type] || {\n                    sync: [],\n                    async: []\n                };\n                this._callbacks[type][method].push(cb);\n            }\n            return this;\n        }\n        function onAsync(types, cb, context) {\n            return on.call(this, \"async\", types, cb, context);\n        }\n        function onSync(types, cb, context) {\n            return on.call(this, \"sync\", types, cb, context);\n        }\n        function off(types) {\n            var type;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            while (type = types.shift()) {\n                delete this._callbacks[type];\n            }\n            return this;\n        }\n        function trigger(types) {\n            var type, callbacks, args, syncFlush, asyncFlush;\n            if (!this._callbacks) {\n                return this;\n            }\n            types = types.split(splitter);\n            args = [].slice.call(arguments, 1);\n            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {\n                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));\n                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));\n                syncFlush() && nextTick(asyncFlush);\n            }\n            return this;\n        }\n        function getFlush(callbacks, context, args) {\n            return flush;\n            function flush() {\n                var cancelled;\n                for (var i = 0; !cancelled && i < callbacks.length; i += 1) {\n                    cancelled = callbacks[i].apply(context, args) === false;\n                }\n                return !cancelled;\n            }\n        }\n        function getNextTick() {\n            var nextTickFn;\n            if (window.setImmediate) {\n                nextTickFn = function nextTickSetImmediate(fn) {\n                    setImmediate(function() {\n                        fn();\n                    });\n                };\n            } else {\n                nextTickFn = function nextTickSetTimeout(fn) {\n                    setTimeout(function() {\n                        fn();\n                    }, 0);\n                };\n            }\n            return nextTickFn;\n        }\n        function bindContext(fn, context) {\n            return fn.bind ? fn.bind(context) : function() {\n                fn.apply(context, [].slice.call(arguments, 0));\n            };\n        }\n    }();\n    var highlight = function(doc) {\n        var defaults = {\n            node: null,\n            pattern: null,\n            tagName: \"strong\",\n            className: null,\n            wordsOnly: false,\n            caseSensitive: false\n        };\n        return function hightlight(o) {\n            var regex;\n            o = _.mixin({}, defaults, o);\n            if (!o.node || !o.pattern) {\n                return;\n            }\n            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];\n            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);\n            traverse(o.node, hightlightTextNode);\n            function hightlightTextNode(textNode) {\n                var match, patternNode;\n                if (match = regex.exec(textNode.data)) {\n                    wrapperNode = doc.createElement(o.tagName);\n                    o.className && (wrapperNode.className = o.className);\n                    patternNode = textNode.splitText(match.index);\n                    patternNode.splitText(match[0].length);\n                    wrapperNode.appendChild(patternNode.cloneNode(true));\n                    textNode.parentNode.replaceChild(wrapperNode, patternNode);\n                }\n                return !!match;\n            }\n            function traverse(el, hightlightTextNode) {\n                var childNode, TEXT_NODE_TYPE = 3;\n                for (var i = 0; i < el.childNodes.length; i++) {\n                    childNode = el.childNodes[i];\n                    if (childNode.nodeType === TEXT_NODE_TYPE) {\n                        i += hightlightTextNode(childNode) ? 1 : 0;\n                    } else {\n                        traverse(childNode, hightlightTextNode);\n                    }\n                }\n            }\n        };\n        function getRegex(patterns, caseSensitive, wordsOnly) {\n            var escapedPatterns = [], regexStr;\n            for (var i = 0; i < patterns.length; i++) {\n                escapedPatterns.push(_.escapeRegExChars(patterns[i]));\n            }\n            regexStr = wordsOnly ? \"\\\\b(\" + escapedPatterns.join(\"|\") + \")\\\\b\" : \"(\" + escapedPatterns.join(\"|\") + \")\";\n            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, \"i\");\n        }\n    }(window.document);\n    var Input = function() {\n        var specialKeyCodeMap;\n        specialKeyCodeMap = {\n            9: \"tab\",\n            27: \"esc\",\n            37: \"left\",\n            39: \"right\",\n            13: \"enter\",\n            38: \"up\",\n            40: \"down\"\n        };\n        function Input(o) {\n            var that = this, onBlur, onFocus, onKeydown, onInput;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"input is missing\");\n            }\n            onBlur = _.bind(this._onBlur, this);\n            onFocus = _.bind(this._onFocus, this);\n            onKeydown = _.bind(this._onKeydown, this);\n            onInput = _.bind(this._onInput, this);\n            this.$hint = $(o.hint);\n            this.$input = $(o.input).on(\"blur.tt\", onBlur).on(\"focus.tt\", onFocus).on(\"keydown.tt\", onKeydown);\n            if (this.$hint.length === 0) {\n                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;\n            }\n            if (!_.isMsie()) {\n                this.$input.on(\"input.tt\", onInput);\n            } else {\n                this.$input.on(\"keydown.tt keypress.tt cut.tt paste.tt\", function($e) {\n                    if (specialKeyCodeMap[$e.which || $e.keyCode]) {\n                        return;\n                    }\n                    _.defer(_.bind(that._onInput, that, $e));\n                });\n            }\n            this.query = this.$input.val();\n            this.$overflowHelper = buildOverflowHelper(this.$input);\n        }\n        Input.normalizeQuery = function(str) {\n            return (str || \"\").replace(/^\\s*/g, \"\").replace(/\\s{2,}/g, \" \");\n        };\n        _.mixin(Input.prototype, EventEmitter, {\n            _onBlur: function onBlur() {\n                this.resetInputValue();\n                this.trigger(\"blurred\");\n            },\n            _onFocus: function onFocus() {\n                this.trigger(\"focused\");\n            },\n            _onKeydown: function onKeydown($e) {\n                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];\n                this._managePreventDefault(keyName, $e);\n                if (keyName && this._shouldTrigger(keyName, $e)) {\n                    this.trigger(keyName + \"Keyed\", $e);\n                }\n            },\n            _onInput: function onInput() {\n                this._checkInputValue();\n            },\n            _managePreventDefault: function managePreventDefault(keyName, $e) {\n                var preventDefault, hintValue, inputValue;\n                switch (keyName) {\n                  case \"tab\":\n                    hintValue = this.getHint();\n                    inputValue = this.getInputValue();\n                    preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);\n                    break;\n\n                  case \"up\":\n                  case \"down\":\n                    preventDefault = !withModifier($e);\n                    break;\n\n                  default:\n                    preventDefault = false;\n                }\n                preventDefault && $e.preventDefault();\n            },\n            _shouldTrigger: function shouldTrigger(keyName, $e) {\n                var trigger;\n                switch (keyName) {\n                  case \"tab\":\n                    trigger = !withModifier($e);\n                    break;\n\n                  default:\n                    trigger = true;\n                }\n                return trigger;\n            },\n            _checkInputValue: function checkInputValue() {\n                var inputValue, areEquivalent, hasDifferentWhitespace;\n                inputValue = this.getInputValue();\n                areEquivalent = areQueriesEquivalent(inputValue, this.query);\n                hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;\n                if (!areEquivalent) {\n                    this.trigger(\"queryChanged\", this.query = inputValue);\n                } else if (hasDifferentWhitespace) {\n                    this.trigger(\"whitespaceChanged\", this.query);\n                }\n            },\n            focus: function focus() {\n                this.$input.focus();\n            },\n            blur: function blur() {\n                this.$input.blur();\n            },\n            getQuery: function getQuery() {\n                return this.query;\n            },\n            setQuery: function setQuery(query) {\n                this.query = query;\n            },\n            getInputValue: function getInputValue() {\n                return this.$input.val();\n            },\n            setInputValue: function setInputValue(value, silent) {\n                this.$input.val(value);\n                silent ? this.clearHint() : this._checkInputValue();\n            },\n            resetInputValue: function resetInputValue() {\n                this.setInputValue(this.query, true);\n            },\n            getHint: function getHint() {\n                return this.$hint.val();\n            },\n            setHint: function setHint(value) {\n                this.$hint.val(value);\n            },\n            clearHint: function clearHint() {\n                this.setHint(\"\");\n            },\n            clearHintIfInvalid: function clearHintIfInvalid() {\n                var val, hint, valIsPrefixOfHint, isValid;\n                val = this.getInputValue();\n                hint = this.getHint();\n                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;\n                isValid = val !== \"\" && valIsPrefixOfHint && !this.hasOverflow();\n                !isValid && this.clearHint();\n            },\n            getLanguageDirection: function getLanguageDirection() {\n                return (this.$input.css(\"direction\") || \"ltr\").toLowerCase();\n            },\n            hasOverflow: function hasOverflow() {\n                var constraint = this.$input.width() - 2;\n                this.$overflowHelper.text(this.getInputValue());\n                return this.$overflowHelper.width() >= constraint;\n            },\n            isCursorAtEnd: function() {\n                var valueLength, selectionStart, range;\n                valueLength = this.$input.val().length;\n                selectionStart = this.$input[0].selectionStart;\n                if (_.isNumber(selectionStart)) {\n                    return selectionStart === valueLength;\n                } else if (document.selection) {\n                    range = document.selection.createRange();\n                    range.moveStart(\"character\", -valueLength);\n                    return valueLength === range.text.length;\n                }\n                return true;\n            },\n            destroy: function destroy() {\n                this.$hint.off(\".tt\");\n                this.$input.off(\".tt\");\n                this.$hint = this.$input = this.$overflowHelper = null;\n            }\n        });\n        return Input;\n        function buildOverflowHelper($input) {\n            return $('<pre aria-hidden=\"true\"></pre>').css({\n                position: \"absolute\",\n                visibility: \"hidden\",\n                whiteSpace: \"pre\",\n                fontFamily: $input.css(\"font-family\"),\n                fontSize: $input.css(\"font-size\"),\n                fontStyle: $input.css(\"font-style\"),\n                fontVariant: $input.css(\"font-variant\"),\n                fontWeight: $input.css(\"font-weight\"),\n                wordSpacing: $input.css(\"word-spacing\"),\n                letterSpacing: $input.css(\"letter-spacing\"),\n                textIndent: $input.css(\"text-indent\"),\n                textRendering: $input.css(\"text-rendering\"),\n                textTransform: $input.css(\"text-transform\")\n            }).insertAfter($input);\n        }\n        function areQueriesEquivalent(a, b) {\n            return Input.normalizeQuery(a) === Input.normalizeQuery(b);\n        }\n        function withModifier($e) {\n            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;\n        }\n    }();\n    var Dataset = function() {\n        var datasetKey = \"ttDataset\", valueKey = \"ttValue\", datumKey = \"ttDatum\";\n        function Dataset(o) {\n            o = o || {};\n            o.templates = o.templates || {};\n            if (!o.source) {\n                $.error(\"missing source\");\n            }\n            if (o.name && !isValidName(o.name)) {\n                $.error(\"invalid dataset name: \" + o.name);\n            }\n            this.query = null;\n            this.highlight = !!o.highlight;\n            this.name = o.name || _.getUniqueId();\n            this.source = o.source;\n            this.displayFn = getDisplayFn(o.display || o.displayKey);\n            this.templates = getTemplates(o.templates, this.displayFn);\n            this.$el = $(html.dataset.replace(\"%CLASS%\", this.name));\n        }\n        Dataset.extractDatasetName = function extractDatasetName(el) {\n            return $(el).data(datasetKey);\n        };\n        Dataset.extractValue = function extractDatum(el) {\n            return $(el).data(valueKey);\n        };\n        Dataset.extractDatum = function extractDatum(el) {\n            return $(el).data(datumKey);\n        };\n        _.mixin(Dataset.prototype, EventEmitter, {\n            _render: function render(query, suggestions) {\n                if (!this.$el) {\n                    return;\n                }\n                var that = this, hasSuggestions;\n                this.$el.empty();\n                hasSuggestions = suggestions && suggestions.length;\n                if (!hasSuggestions && this.templates.empty) {\n                    this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                } else if (hasSuggestions) {\n                    this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);\n                }\n                this.trigger(\"rendered\");\n                function getEmptyHtml() {\n                    return that.templates.empty({\n                        query: query,\n                        isEmpty: true\n                    });\n                }\n                function getSuggestionsHtml() {\n                    var $suggestions, nodes;\n                    $suggestions = $(html.suggestions).css(css.suggestions);\n                    nodes = _.map(suggestions, getSuggestionNode);\n                    $suggestions.append.apply($suggestions, nodes);\n                    that.highlight && highlight({\n                        node: $suggestions[0],\n                        pattern: query\n                    });\n                    return $suggestions;\n                    function getSuggestionNode(suggestion) {\n                        var $el;\n                        $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);\n                        $el.children().each(function() {\n                            $(this).css(css.suggestionChild);\n                        });\n                        return $el;\n                    }\n                }\n                function getHeaderHtml() {\n                    return that.templates.header({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n                function getFooterHtml() {\n                    return that.templates.footer({\n                        query: query,\n                        isEmpty: !hasSuggestions\n                    });\n                }\n            },\n            getRoot: function getRoot() {\n                return this.$el;\n            },\n            update: function update(query) {\n                var that = this;\n                this.query = query;\n                this.canceled = false;\n                this.source(query, render);\n                function render(suggestions) {\n                    if (!that.canceled && query === that.query) {\n                        that._render(query, suggestions);\n                    }\n                }\n            },\n            cancel: function cancel() {\n                this.canceled = true;\n            },\n            clear: function clear() {\n                this.cancel();\n                this.$el.empty();\n                this.trigger(\"rendered\");\n            },\n            isEmpty: function isEmpty() {\n                return this.$el.is(\":empty\");\n            },\n            destroy: function destroy() {\n                this.$el = null;\n            }\n        });\n        return Dataset;\n        function getDisplayFn(display) {\n            display = display || \"value\";\n            return _.isFunction(display) ? display : displayFn;\n            function displayFn(obj) {\n                return obj[display];\n            }\n        }\n        function getTemplates(templates, displayFn) {\n            return {\n                empty: templates.empty && _.templatify(templates.empty),\n                header: templates.header && _.templatify(templates.header),\n                footer: templates.footer && _.templatify(templates.footer),\n                suggestion: templates.suggestion || suggestionTemplate\n            };\n            function suggestionTemplate(context) {\n                return \"<p>\" + displayFn(context) + \"</p>\";\n            }\n        }\n        function isValidName(str) {\n            return /^[_a-zA-Z0-9-]+$/.test(str);\n        }\n    }();\n    var Dropdown = function() {\n        function Dropdown(o) {\n            var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;\n            o = o || {};\n            if (!o.menu) {\n                $.error(\"menu is required\");\n            }\n            this.isOpen = false;\n            this.isEmpty = true;\n            this.datasets = _.map(o.datasets, initializeDataset);\n            onSuggestionClick = _.bind(this._onSuggestionClick, this);\n            onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);\n            onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);\n            this.$menu = $(o.menu).on(\"click.tt\", \".tt-suggestion\", onSuggestionClick).on(\"mouseenter.tt\", \".tt-suggestion\", onSuggestionMouseEnter).on(\"mouseleave.tt\", \".tt-suggestion\", onSuggestionMouseLeave);\n            _.each(this.datasets, function(dataset) {\n                that.$menu.append(dataset.getRoot());\n                dataset.onSync(\"rendered\", that._onRendered, that);\n            });\n        }\n        _.mixin(Dropdown.prototype, EventEmitter, {\n            _onSuggestionClick: function onSuggestionClick($e) {\n                this.trigger(\"suggestionClicked\", $($e.currentTarget));\n            },\n            _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {\n                this._removeCursor();\n                this._setCursor($($e.currentTarget), true);\n            },\n            _onSuggestionMouseLeave: function onSuggestionMouseLeave() {\n                this._removeCursor();\n            },\n            _onRendered: function onRendered() {\n                this.isEmpty = _.every(this.datasets, isDatasetEmpty);\n                this.isEmpty ? this._hide() : this.isOpen && this._show();\n                this.trigger(\"datasetRendered\");\n                function isDatasetEmpty(dataset) {\n                    return dataset.isEmpty();\n                }\n            },\n            _hide: function() {\n                this.$menu.hide();\n            },\n            _show: function() {\n                this.$menu.css(\"display\", \"block\");\n            },\n            _getSuggestions: function getSuggestions() {\n                return this.$menu.find(\".tt-suggestion\");\n            },\n            _getCursor: function getCursor() {\n                return this.$menu.find(\".tt-cursor\").first();\n            },\n            _setCursor: function setCursor($el, silent) {\n                $el.first().addClass(\"tt-cursor\");\n                !silent && this.trigger(\"cursorMoved\");\n            },\n            _removeCursor: function removeCursor() {\n                this._getCursor().removeClass(\"tt-cursor\");\n            },\n            _moveCursor: function moveCursor(increment) {\n                var $suggestions, $oldCursor, newCursorIndex, $newCursor;\n                if (!this.isOpen) {\n                    return;\n                }\n                $oldCursor = this._getCursor();\n                $suggestions = this._getSuggestions();\n                this._removeCursor();\n                newCursorIndex = $suggestions.index($oldCursor) + increment;\n                newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;\n                if (newCursorIndex === -1) {\n                    this.trigger(\"cursorRemoved\");\n                    return;\n                } else if (newCursorIndex < -1) {\n                    newCursorIndex = $suggestions.length - 1;\n                }\n                this._setCursor($newCursor = $suggestions.eq(newCursorIndex));\n                this._ensureVisible($newCursor);\n            },\n            _ensureVisible: function ensureVisible($el) {\n                var elTop, elBottom, menuScrollTop, menuHeight;\n                elTop = $el.position().top;\n                elBottom = elTop + $el.outerHeight(true);\n                menuScrollTop = this.$menu.scrollTop();\n                menuHeight = this.$menu.height() + parseInt(this.$menu.css(\"paddingTop\"), 10) + parseInt(this.$menu.css(\"paddingBottom\"), 10);\n                if (elTop < 0) {\n                    this.$menu.scrollTop(menuScrollTop + elTop);\n                } else if (menuHeight < elBottom) {\n                    this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));\n                }\n            },\n            close: function close() {\n                if (this.isOpen) {\n                    this.isOpen = false;\n                    this._removeCursor();\n                    this._hide();\n                    this.trigger(\"closed\");\n                }\n            },\n            open: function open() {\n                if (!this.isOpen) {\n                    this.isOpen = true;\n                    !this.isEmpty && this._show();\n                    this.trigger(\"opened\");\n                }\n            },\n            setLanguageDirection: function setLanguageDirection(dir) {\n                this.$menu.css(dir === \"ltr\" ? css.ltr : css.rtl);\n            },\n            moveCursorUp: function moveCursorUp() {\n                this._moveCursor(-1);\n            },\n            moveCursorDown: function moveCursorDown() {\n                this._moveCursor(+1);\n            },\n            getDatumForSuggestion: function getDatumForSuggestion($el) {\n                var datum = null;\n                if ($el.length) {\n                    datum = {\n                        raw: Dataset.extractDatum($el),\n                        value: Dataset.extractValue($el),\n                        datasetName: Dataset.extractDatasetName($el)\n                    };\n                }\n                return datum;\n            },\n            getDatumForCursor: function getDatumForCursor() {\n                return this.getDatumForSuggestion(this._getCursor().first());\n            },\n            getDatumForTopSuggestion: function getDatumForTopSuggestion() {\n                return this.getDatumForSuggestion(this._getSuggestions().first());\n            },\n            update: function update(query) {\n                _.each(this.datasets, updateDataset);\n                function updateDataset(dataset) {\n                    dataset.update(query);\n                }\n            },\n            empty: function empty() {\n                _.each(this.datasets, clearDataset);\n                this.isEmpty = true;\n                function clearDataset(dataset) {\n                    dataset.clear();\n                }\n            },\n            isVisible: function isVisible() {\n                return this.isOpen && !this.isEmpty;\n            },\n            destroy: function destroy() {\n                this.$menu.off(\".tt\");\n                this.$menu = null;\n                _.each(this.datasets, destroyDataset);\n                function destroyDataset(dataset) {\n                    dataset.destroy();\n                }\n            }\n        });\n        return Dropdown;\n        function initializeDataset(oDataset) {\n            return new Dataset(oDataset);\n        }\n    }();\n    var Typeahead = function() {\n        var attrsKey = \"ttAttrs\";\n        function Typeahead(o) {\n            var $menu, $input, $hint;\n            o = o || {};\n            if (!o.input) {\n                $.error(\"missing input\");\n            }\n            this.isActivated = false;\n            this.autoselect = !!o.autoselect;\n            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;\n            this.$node = buildDomStructure(o.input, o.withHint);\n            $menu = this.$node.find(\".tt-dropdown-menu\");\n            $input = this.$node.find(\".tt-input\");\n            $hint = this.$node.find(\".tt-hint\");\n            $input.on(\"blur.tt\", function($e) {\n                var active, isActive, hasActive;\n                active = document.activeElement;\n                isActive = $menu.is(active);\n                hasActive = $menu.has(active).length > 0;\n                if (_.isMsie() && (isActive || hasActive)) {\n                    $e.preventDefault();\n                    $e.stopImmediatePropagation();\n                    _.defer(function() {\n                        $input.focus();\n                    });\n                }\n            });\n            $menu.on(\"mousedown.tt\", function($e) {\n                $e.preventDefault();\n            });\n            this.eventBus = o.eventBus || new EventBus({\n                el: $input\n            });\n            this.dropdown = new Dropdown({\n                menu: $menu,\n                datasets: o.datasets\n            }).onSync(\"suggestionClicked\", this._onSuggestionClicked, this).onSync(\"cursorMoved\", this._onCursorMoved, this).onSync(\"cursorRemoved\", this._onCursorRemoved, this).onSync(\"opened\", this._onOpened, this).onSync(\"closed\", this._onClosed, this).onAsync(\"datasetRendered\", this._onDatasetRendered, this);\n            this.input = new Input({\n                input: $input,\n                hint: $hint\n            }).onSync(\"focused\", this._onFocused, this).onSync(\"blurred\", this._onBlurred, this).onSync(\"enterKeyed\", this._onEnterKeyed, this).onSync(\"tabKeyed\", this._onTabKeyed, this).onSync(\"escKeyed\", this._onEscKeyed, this).onSync(\"upKeyed\", this._onUpKeyed, this).onSync(\"downKeyed\", this._onDownKeyed, this).onSync(\"leftKeyed\", this._onLeftKeyed, this).onSync(\"rightKeyed\", this._onRightKeyed, this).onSync(\"queryChanged\", this._onQueryChanged, this).onSync(\"whitespaceChanged\", this._onWhitespaceChanged, this);\n            this._setLanguageDirection();\n        }\n        _.mixin(Typeahead.prototype, {\n            _onSuggestionClicked: function onSuggestionClicked(type, $el) {\n                var datum;\n                if (datum = this.dropdown.getDatumForSuggestion($el)) {\n                    this._select(datum);\n                }\n            },\n            _onCursorMoved: function onCursorMoved() {\n                var datum = this.dropdown.getDatumForCursor();\n                this.input.setInputValue(datum.value, true);\n                this.eventBus.trigger(\"cursorchanged\", datum.raw, datum.datasetName);\n            },\n            _onCursorRemoved: function onCursorRemoved() {\n                this.input.resetInputValue();\n                this._updateHint();\n            },\n            _onDatasetRendered: function onDatasetRendered() {\n                this._updateHint();\n            },\n            _onOpened: function onOpened() {\n                this._updateHint();\n                this.eventBus.trigger(\"opened\");\n            },\n            _onClosed: function onClosed() {\n                this.input.clearHint();\n                this.eventBus.trigger(\"closed\");\n            },\n            _onFocused: function onFocused() {\n                this.isActivated = true;\n                this.dropdown.open();\n            },\n            _onBlurred: function onBlurred() {\n                this.isActivated = false;\n                this.dropdown.empty();\n                this.dropdown.close();\n                this.setVal(\"\", true); //LM\n            },\n            _onEnterKeyed: function onEnterKeyed(type, $e) {\n                var cursorDatum, topSuggestionDatum;\n                cursorDatum = this.dropdown.getDatumForCursor();\n                topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();\n                if (cursorDatum) {\n                    this._select(cursorDatum);\n                    $e.preventDefault();\n                } else if (this.autoselect && topSuggestionDatum) {\n                    this._select(topSuggestionDatum);\n                    $e.preventDefault();\n                }\n            },\n            _onTabKeyed: function onTabKeyed(type, $e) {\n                var datum;\n                if (datum = this.dropdown.getDatumForCursor()) {\n                    this._select(datum);\n                    $e.preventDefault();\n                } else {\n                    this._autocomplete(true);\n                }\n            },\n            _onEscKeyed: function onEscKeyed() {\n                this.dropdown.close();\n                this.input.resetInputValue();\n            },\n            _onUpKeyed: function onUpKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();\n                this.dropdown.open();\n            },\n            _onDownKeyed: function onDownKeyed() {\n                var query = this.input.getQuery();\n                this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();\n                this.dropdown.open();\n            },\n            _onLeftKeyed: function onLeftKeyed() {\n                this.dir === \"rtl\" && this._autocomplete();\n            },\n            _onRightKeyed: function onRightKeyed() {\n                this.dir === \"ltr\" && this._autocomplete();\n            },\n            _onQueryChanged: function onQueryChanged(e, query) {\n                this.input.clearHintIfInvalid();\n                query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();\n                this.dropdown.open();\n                this._setLanguageDirection();\n            },\n            _onWhitespaceChanged: function onWhitespaceChanged() {\n                this._updateHint();\n                this.dropdown.open();\n            },\n            _setLanguageDirection: function setLanguageDirection() {\n                var dir;\n                if (this.dir !== (dir = this.input.getLanguageDirection())) {\n                    this.dir = dir;\n                    this.$node.css(\"direction\", dir);\n                    this.dropdown.setLanguageDirection(dir);\n                }\n            },\n            _updateHint: function updateHint() {\n                var datum, val, query, escapedQuery, frontMatchRegEx, match;\n                datum = this.dropdown.getDatumForTopSuggestion();\n                if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {\n                    val = this.input.getInputValue();\n                    query = Input.normalizeQuery(val);\n                    escapedQuery = _.escapeRegExChars(query);\n                    frontMatchRegEx = new RegExp(\"^(?:\" + escapedQuery + \")(.+$)\", \"i\");\n                    match = frontMatchRegEx.exec(datum.value);\n                    match ? this.input.setHint(val + match[1]) : this.input.clearHint();\n                } else {\n                    this.input.clearHint();\n                }\n            },\n            _autocomplete: function autocomplete(laxCursor) {\n                var hint, query, isCursorAtEnd, datum;\n                hint = this.input.getHint();\n                query = this.input.getQuery();\n                isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();\n                if (hint && query !== hint && isCursorAtEnd) {\n                    datum = this.dropdown.getDatumForTopSuggestion();\n                    datum && this.input.setInputValue(datum.value);\n                    this.eventBus.trigger(\"autocompleted\", datum.raw, datum.datasetName);\n                }\n            },\n            _select: function select(datum) {\n                this.input.setQuery(datum.value);\n                this.input.setInputValue(datum.value, true);\n                this._setLanguageDirection();\n                this.eventBus.trigger(\"selected\", datum.raw, datum.datasetName);\n                this.dropdown.close();\n                _.defer(_.bind(this.dropdown.empty, this.dropdown));\n            },\n            open: function open() {\n                this.dropdown.open();\n            },\n            close: function close() {\n                this.dropdown.close();\n            },\n            setVal: function setVal(val) {\n                if (this.isActivated) {\n                    this.input.setInputValue(val);\n                } else {\n                    this.input.setQuery(val);\n                    this.input.setInputValue(val, true);\n                }\n                this._setLanguageDirection();\n            },\n            getVal: function getVal() {\n                return this.input.getQuery();\n            },\n            destroy: function destroy() {\n                this.input.destroy();\n                this.dropdown.destroy();\n                destroyDomStructure(this.$node);\n                this.$node = null;\n            }\n        });\n        return Typeahead;\n        function buildDomStructure(input, withHint) {\n            var $input, $wrapper, $dropdown, $hint;\n            $input = $(input);\n            $wrapper = $(html.wrapper).css(css.wrapper);\n            $dropdown = $(html.dropdown).css(css.dropdown);\n            $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));\n            $hint.val(\"\").removeData().addClass(\"tt-hint\").removeAttr(\"id name placeholder\").prop(\"disabled\", true).attr({\n                autocomplete: \"off\",\n                spellcheck: \"false\"\n            });\n            $input.data(attrsKey, {\n                dir: $input.attr(\"dir\"),\n                autocomplete: $input.attr(\"autocomplete\"),\n                spellcheck: $input.attr(\"spellcheck\"),\n                style: $input.attr(\"style\")\n            });\n            $input.addClass(\"tt-input\").attr({\n                autocomplete: \"off\",\n                spellcheck: false\n            }).css(withHint ? css.input : css.inputWithNoHint);\n            try {\n                !$input.attr(\"dir\") && $input.attr(\"dir\", \"auto\");\n            } catch (e) {}\n            return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);\n        }\n        function getBackgroundStyles($el) {\n            return {\n                backgroundAttachment: $el.css(\"background-attachment\"),\n                backgroundClip: $el.css(\"background-clip\"),\n                backgroundColor: $el.css(\"background-color\"),\n                backgroundImage: $el.css(\"background-image\"),\n                backgroundOrigin: $el.css(\"background-origin\"),\n                backgroundPosition: $el.css(\"background-position\"),\n                backgroundRepeat: $el.css(\"background-repeat\"),\n                backgroundSize: $el.css(\"background-size\")\n            };\n        }\n        function destroyDomStructure($node) {\n            var $input = $node.find(\".tt-input\");\n            _.each($input.data(attrsKey), function(val, key) {\n                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);\n            });\n            $input.detach().removeData(attrsKey).removeClass(\"tt-input\").insertAfter($node);\n            $node.remove();\n        }\n    }();\n    (function() {\n        var old, typeaheadKey, methods;\n        old = $.fn.typeahead;\n        typeaheadKey = \"ttTypeahead\";\n        methods = {\n            initialize: function initialize(o, datasets) {\n                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);\n                o = o || {};\n                return this.each(attach);\n                function attach() {\n                    var $input = $(this), eventBus, typeahead;\n                    _.each(datasets, function(d) {\n                        d.highlight = !!o.highlight;\n                    });\n                    typeahead = new Typeahead({\n                        input: $input,\n                        eventBus: eventBus = new EventBus({\n                            el: $input\n                        }),\n                        withHint: _.isUndefined(o.hint) ? true : !!o.hint,\n                        minLength: o.minLength,\n                        autoselect: o.autoselect,\n                        datasets: datasets\n                    });\n                    $input.data(typeaheadKey, typeahead);\n                }\n            },\n            open: function open() {\n                return this.each(openTypeahead);\n                function openTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.open();\n                    }\n                }\n            },\n            close: function close() {\n                return this.each(closeTypeahead);\n                function closeTypeahead() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.close();\n                    }\n                }\n            },\n            val: function val(newVal) {\n                return !arguments.length ? getVal(this.first()) : this.each(setVal);\n                function setVal() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.setVal(newVal);\n                    }\n                }\n                function getVal($input) {\n                    var typeahead, query;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        query = typeahead.getVal();\n                    }\n                    return query;\n                }\n            },\n            destroy: function destroy() {\n                return this.each(unattach);\n                function unattach() {\n                    var $input = $(this), typeahead;\n                    if (typeahead = $input.data(typeaheadKey)) {\n                        typeahead.destroy();\n                        $input.removeData(typeaheadKey);\n                    }\n                }\n            }\n        };\n        $.fn.typeahead = function(method) {\n            if (methods[method]) {\n                return methods[method].apply(this, [].slice.call(arguments, 1));\n            } else {\n                return methods.initialize.apply(this, arguments);\n            }\n        };\n        $.fn.typeahead.noConflict = function noConflict() {\n            $.fn.typeahead = old;\n            return this;\n        };\n    })();\n    \n    \n    \n//})(window.jQuery);\n\n\n});\n",
        +    "define('searchView',[\n  'App',\n  // Templates\n  'text!tpl/search.html',\n  'text!tpl/search_suggestion.html',\n  // Tools\n  'typeahead'\n], function(App, searchTpl, suggestionTpl) {\n\n  var searchView = Backbone.View.extend({\n    el: '#search',\n    /**\n     * Init.\n     */\n    init: function() {\n      var tpl = _.template(searchTpl);\n      var className = 'form-control input-lg';\n      var placeholder = 'Search reference';\n      this.searchHtml = tpl({\n        'placeholder': placeholder,\n        'className': className\n      });\n      this.items = App.classes.concat(App.allItems);\n\n      return this;\n    },\n    /**\n     * Render input field with Typehead activated.\n     */\n    render: function() {\n      // Append the view to the dom\n      this.$el.append(this.searchHtml);\n\n      // Render Typeahead\n      var $searchInput = this.$el.find('input[type=text]');\n      this.typeaheadRender($searchInput);\n      this.typeaheadEvents($searchInput);\n\n      return this;\n    },\n    /**\n     * Apply Twitter Typeahead to the search input field.\n     * @param {jquery} $input\n     */\n    typeaheadRender: function($input) {\n      var self = this;\n      $input.typeahead(null, {\n        'displayKey': 'name',\n        'minLength': 2,\n        //'highlight': true,\n        'source': self.substringMatcher(this.items),\n        'templates': {\n          'empty': '<p class=\"empty-message\">Unable to find any item that match the current query</p>',\n          'suggestion': _.template(suggestionTpl)\n        }\n      });\n    },\n    /**\n     * Setup typeahead custom events (item selected).\n     */\n    typeaheadEvents: function($input) {\n      var self = this;\n      $input.on('typeahead:selected', function(e, item, datasetName) {\n        var selectedItem = self.items[item.idx];\n        select(selectedItem);\n      });\n      $input.on('keydown', function(e) {\n        if (e.which === 13) { // enter\n          var txt = $input.val();\n          var f = _.find(self.items, function(it) { return it.name == txt; });\n          if (f) {\n            select(f);\n          }\n        } else if (e.which === 27) {\n          $input.blur();\n        }\n      });\n\n      function select(selectedItem) {\n        var hash = App.router.getHash(selectedItem);//\n        App.router.navigate(hash, {'trigger': true});\n        $('#item').focus();\n      }\n    },\n    /**\n     * substringMatcher function for Typehead (search for strings in an array).\n     * @param {array} array\n     * @returns {Function}\n     */\n    substringMatcher: function(array) {\n      return function findMatches(query, callback) {\n        var matches = [], substrRegex, arrayLength = array.length;\n\n        // regex used to determine if a string contains the substring `query`\n        substrRegex = new RegExp(query, 'i');\n\n        // iterate through the pool of strings and for any string that\n        // contains the substring `query`, add it to the `matches` array\n        for (var i=0; i < arrayLength; i++) {\n          var item = array[i];\n          if (substrRegex.test(item.name)) {\n            // typeahead expects suggestions to be a js object\n            matches.push({\n              'itemtype': item.itemtype,\n              'name': item.name,\n              'className': item.class,\n              'is_constructor': !!item.is_constructor,\n              'final': item.final,\n              'idx': i\n            });\n          }\n        }\n\n        callback(matches);\n      };\n    }\n\n  });\n\n  return searchView;\n\n});\n\n",
        +    "\ndefine('text!tpl/list.html',[],function () { return '<% _.each(groups, function(group){ %>\\n  <div class=\"reference-group clearfix main-ref-page\">  \\n    <h2 class=\"group-name\" id=\"group-<%=group.name%>\" tab-index=\"-1\"><%=group.name%></h2>\\n    <div class=\"reference-subgroups clearfix main-ref-page\">  \\n    <% _.each(group.subgroups, function(subgroup, ind) { %>\\n      <div class=\"reference-subgroup\">\\n        <% if (subgroup.name !== \\'0\\') { %>\\n          <h3 id=\"<%=group.name%><%=ind%>\" class=\"subgroup-name subgroup-<%=subgroup.name%>\"><%=subgroup.name%></h3>\\n        <% } %>\\n        <ul aria-labelledby=\"<%=group.name%> <%=ind%>\">\\n        <% _.each(subgroup.items, function(item) { %>\\n        <li><a href=\"<%=item.hash%>\"><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></li>\\n        <% }); %>\\n        </ul>\\n      </div>\\n    <% }); %>\\n    </div>\\n  </div>\\n<% }); %>\\n';});\n\n",
        +    "define('listView',[\n  'App',\n  // Templates\n  'text!tpl/list.html'\n], function (App, listTpl) {\n  var striptags = function(html) {\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.textContent;\n  };\n\n  var listView = Backbone.View.extend({\n    el: '#list',\n    events: {},\n    /**\n     * Init.\n     */\n    init: function () {\n      this.listTpl = _.template(listTpl);\n\n      return this;\n    },\n    /**\n     * Render the list.\n     */\n    render: function (items, listCollection) {\n      if (items && listCollection) {\n        var self = this;\n\n        // Render items and group them by module\n        // module === group\n        this.groups = {};\n        _.each(items, function (item, i) {\n\n          if (!item.private && item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n\n            var group = item.module || '_';\n            var subgroup = item.submodule || '_';\n            if (group === subgroup) {\n              subgroup = '0';\n            }\n            var hash = App.router.getHash(item);\n\n            // fixes broken links for #/p5/> and #/p5/>=\n            item.hash = item.hash.replace('>', '&gt;');\n\n            // Create a group list\n            if (!self.groups[group]) {\n              self.groups[group] = {\n                name: group.replace('_', '&nbsp;'),\n                subgroups: {}\n              };\n            }\n\n            // Create a subgroup list\n            if (!self.groups[group].subgroups[subgroup]) {\n              self.groups[group].subgroups[subgroup] = {\n                name: subgroup.replace('_', '&nbsp;'),\n                items: []\n              };\n            }\n\n            // hide the un-interesting constants\n            if (group === 'Constants' && !item.example)\n              return;\n\n            if (item.class === 'p5') {\n\n              self.groups[group].subgroups[subgroup].items.push(item);\n\n            } else {\n\n              var found = _.find(self.groups[group].subgroups[subgroup].items,\n                function(i){ return i.name == item.class; });\n\n              if (!found) {\n\n                // FIX TO INVISIBLE OBJECTS: DH (see also router.js)\n                var ind = hash.lastIndexOf('/');\n                hash = item.hash.substring(0, ind).replace('p5/','p5.');\n                self.groups[group].subgroups[subgroup].items.push({\n                  name: item.class,\n                  hash: hash\n                });\n              }\n\n            }\n          }\n        });\n\n        // Put the <li> items html into the list <ul>\n        var listHtml = self.listTpl({\n          'striptags': striptags,\n          'title': self.capitalizeFirst(listCollection),\n          'groups': self.groups,\n          'listCollection': listCollection\n        });\n\n        // Render the view\n        this.$el.html(listHtml);\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Show a list of items.\n     * @param {array} items Array of item objects.\n     * @returns {object} This view.\n     */\n    show: function (listGroup) {\n      if (App[listGroup]) {\n        this.render(App[listGroup], listGroup);\n      }\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function (str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n\n\n\n  });\n\n  return listView;\n\n});\n\n",
        +    "\ndefine('text!tpl/item.html',[],function () { return '<h2><%=item.name%><% if (item.isMethod) { %>()<% } %></h2>\\n\\n<% if (item.example) { %>\\n<div class=\"example\">\\n  <h3 id=\"reference-example\">Examples</h3>\\n\\n  <div class=\"example-content\" data-alt=\"<%= item.alt %>\">\\n    <% _.each(item.example, function(example, i){ %>\\n      <%= example %>\\n    <% }); %>\\n  </div>\\n</div>\\n<% } %>\\n\\n<div class=\"description\">\\n    \\n  <h3 id=\"reference-description\">Description</h3>\\n\\n  <% if (item.deprecated) { %>\\n    <p>\\n      Deprecated: <%=item.name%><% if (item.isMethod) { %>()<% } %> is deprecated and will be removed in a future version of p5. <% if (item.deprecationMessage) { %><%=item.deprecationMessage%><% } %>\\n    </p>\\n  <% } %>\\n      \\n\\n  <span class=\\'description-text\\'><%= item.description %></span>\\n\\n  <% if (item.extends) { %>\\n    <p><span id=\"reference-extends\">Extends</span> <a href=\"/reference/#/<%=item.extends%>\" title=\"<%=item.extends%> reference\"><%=item.extends%></a></p>\\n  <% } %>\\n\\n  <% if (item.module === \\'p5.sound\\') { %>\\n    <p>This function requires you include the p5.sound library.  Add the following into the head of your index.html file:\\n      <pre><code class=\"language-javascript\">&lt;script src=\"path/to/p5.sound.js\"&gt;&lt;/script&gt;</code></pre>\\n    </p>\\n  <% } %>\\n\\n  <% if (item.constRefs) { %>\\n    <p>Used by:\\n  <%\\n      var refs = item.constRefs;\\n      for (var i = 0; i < refs.length; i ++) {\\n        var ref = refs[i];\\n        var name = ref;\\n        if (name.substr(0, 3) === \\'p5.\\') {\\n          name = name.substr(3);\\n        }\\n  if (i !== 0) {\\n          if (i == refs.length - 1) {\\n            %> and <%\\n          } else {\\n            %>, <%\\n          }\\n        }\\n        %><a href=\"./#/<%= ref.replace(\\'.\\', \\'/\\') %>\"><%= name %>()</a><%\\n      }\\n  %>\\n    </p>\\n  <% } %>\\n</div>\\n\\n<% if (isConstructor || !isClass) { %>\\n\\n<div>\\n  <h3 id=\"reference-syntax\">Syntax</h3>\\n  <p>\\n    <% syntaxes.forEach(function(syntax) { %>\\n    <pre><code class=\"language-javascript\"><%= syntax %></code></pre>\\n    <% }) %>\\n  </p>\\n</div>\\n\\n\\n<% if (item.params) { %>\\n  <div class=\"params\">\\n    <h3 id=\"reference-parameters\">Parameters</h3>\\n    <ul aria-labelledby=\\'reference-parameters\\'>\\n    <% for (var i=0; i<item.params.length; i++) { %>\\n      <% var p = item.params[i] %>\\n      <li>\\n        <div class=\\'paramname\\'><%=p.name%></div>\\n        <% if (p.type) { %>\\n          <div class=\\'paramtype\\'>\\n          <% var type = p.type.replace(/(p5\\\\.[A-Z][A-Za-z]*)/, \\'<a href=\"#/$1\">$1</a>\\'); %>\\n          <span class=\"param-type label label-info\"><%=type%></span>: <%=p.description%>\\n          <% if (p.optional) { %> (Optional)<% } %>\\n          </div>\\n        <% } %>\\n      </li>\\n    <% } %>\\n    </ul>\\n  </div>\\n<% } %>\\n\\n<% if (item.return && item.return.type) { %>\\n  <div>\\n    <h3 id=\"reference-returns\">Returns</h3>\\n    <p class=\\'returns\\'><span class=\"param-type label label-info\"><%=item.return.type%></span>: <%= item.return.description %></p>\\n  </div>\\n<% } %>\\n\\n<% } %>\\n';});\n\n",
        +    "\ndefine('text!tpl/class.html',[],function () { return '\\n<% if (typeof constructor !== \\'undefined\\') { %>\\n<div class=\"constructor\">\\n  <%=constructor%>\\n</div>\\n<% } %>\\n\\n<% let fields = _.filter(things, function(item) { return item.itemtype === \\'property\\' && item.access !== \\'private\\' }); %>\\n<% if (fields.length > 0) { %>\\n  <h3 id=\\'reference-fields\\'>Fields</h3>\\n  <ul aria-labelledby=\\'reference-fields\\'>\\n  <% _.each(fields, function(item) { %>\\n    <li>\\n      <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%></a></div>\\n      <div class=\\'paramtype\\'><%= item.description %></div>\\n    </li>\\n  <% }); %>\\n  </ul>\\n<% } %>\\n\\n<% let methods = _.filter(things, function(item) { return item.itemtype === \\'method\\' && item.access !== \\'private\\' }); %>\\n<% if (methods.length > 0) { %>\\n  <h3 id=\\'reference-methods\\'>Methods</h3>\\n  <ul aria-labelledby=\\'reference-methods\\'>\\n    <% _.each(methods, function(item) { %>\\n      <li>\\n        <div class=\\'paramname\\'><a href=\"<%=item.hash%>\" <% if (item.module !== module) { %>class=\"addon\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a></div>\\n        <div class=\\'paramtype\\'><%= item.description %></div>\\n      </li>\\n    <% }); %>\\n  </ul>\\n<% } %>\\n';});\n\n",
        +    "\ndefine('text!tpl/itemEnd.html',[],function () { return '\\n<br><br>\\n\\n<div>\\n<% if (item.file && item.line) { %>\\n<span id=\"reference-error1\">Notice any errors or typos?</span> <a href=\"https://github.com/processing/p5.js/issues\"><span id=\"reference-contribute2\">Please let us know.</span></a> <span id=\"reference-error3\">Please feel free to edit</span> <a href=\"https://github.com/processing/p5.js/blob/<%= appVersion %>/<%= item.file %>#L<%= item.line %>\" target=\"_blank\" ><%= item.file %></a> <span id=\"reference-error5\">and issue a pull request!</span>\\n<% } %>\\n</div>\\n\\n<a style=\"border-bottom:none !important;\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\" target=_blank><img src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" style=\"width:88px\" alt=\"creative commons logo\"/></a>\\n<br><br>\\n';});\n\n",
        +    "// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n\n/**\n * @fileoverview\n * some functions for browser-side pretty printing of code contained in html.\n *\n * <p>\n * For a fairly comprehensive set of languages see the\n * <a href=\"http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs\">README</a>\n * file that came with this source.  At a minimum, the lexer should work on a\n * number of languages including C and friends, Java, Python, Bash, SQL, HTML,\n * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk\n * and a subset of Perl, but, because of commenting conventions, doesn't work on\n * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.\n * <p>\n * Usage: <ol>\n * <li> include this source file in an html page via\n *   {@code <script src=\"/path/to/prettify.js\"></script>}\n * <li> define style rules.  See the example page for examples.\n * <li> mark the {@code <pre>} and {@code <code>} tags in your source with\n *    {@code class=prettyprint.}\n *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty\n *    printer needs to do more substantial DOM manipulations to support that, so\n *    some css styles may not be preserved.\n * </ol>\n * That's it.  I wanted to keep the API as simple as possible, so there's no\n * need to specify which language the code is in, but if you wish, you can add\n * another class to the {@code <pre>} or {@code <code>} element to specify the\n * language, as in {@code <pre class=\"prettyprint lang-java\">}.  Any class that\n * starts with \"lang-\" followed by a file extension, specifies the file type.\n * See the \"lang-*.js\" files in this directory for code that implements\n * per-language file handlers.\n * <p>\n * Change log:<br>\n * cbeust, 2006/08/22\n * <blockquote>\n *   Java annotations (start with \"@\") are now captured as literals (\"lit\")\n * </blockquote>\n * @requires console\n */\n\n// JSLint declarations\n/*global console, document, navigator, setTimeout, window, define */\n\n/** @define {boolean} */\nvar IN_GLOBAL_SCOPE = true;\n\n/**\n * Split {@code prettyPrint} into multiple timeouts so as not to interfere with\n * UI events.\n * If set to {@code false}, {@code prettyPrint()} is synchronous.\n */\nwindow['PR_SHOULD_USE_CONTINUATION'] = true;\n\n/**\n * Pretty print a chunk of code.\n * @param {string} sourceCodeHtml The HTML to pretty print.\n * @param {string} opt_langExtension The language name to use.\n *     Typically, a filename extension like 'cpp' or 'java'.\n * @param {number|boolean} opt_numberLines True to number lines,\n *     or the 1-indexed number of the first line in sourceCodeHtml.\n * @return {string} code as html, but prettier\n */\nvar prettyPrintOne;\n/**\n * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n * {@code class=prettyprint} and prettify them.\n *\n * @param {Function} opt_whenDone called when prettifying is done.\n * @param {HTMLElement|HTMLDocument} opt_root an element or document\n *   containing all the elements to pretty print.\n *   Defaults to {@code document.body}.\n */\nvar prettyPrint;\n\n\n(function () {\n  var win = window;\n  // Keyword lists for various languages.\n  // We use things that coerce to strings to make them compact when minified\n  // and to defeat aggressive optimizers that fold large string constants.\n  var FLOW_CONTROL_KEYWORDS = [\"break,continue,do,else,for,if,return,while\"];\n  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,\"auto,case,char,const,default,\" + \n      \"double,enum,extern,float,goto,inline,int,long,register,short,signed,\" +\n      \"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"];\n  var COMMON_KEYWORDS = [C_KEYWORDS,\"catch,class,delete,false,import,\" +\n      \"new,operator,private,protected,public,this,throw,true,try,typeof\"];\n  var CPP_KEYWORDS = [COMMON_KEYWORDS,\"alignof,align_union,asm,axiom,bool,\" +\n      \"concept,concept_map,const_cast,constexpr,decltype,delegate,\" +\n      \"dynamic_cast,explicit,export,friend,generic,late_check,\" +\n      \"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,\" +\n      \"static_cast,template,typeid,typename,using,virtual,where\"];\n  var JAVA_KEYWORDS = [COMMON_KEYWORDS,\n      \"abstract,assert,boolean,byte,extends,final,finally,implements,import,\" +\n      \"instanceof,interface,null,native,package,strictfp,super,synchronized,\" +\n      \"throws,transient\"];\n  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,\n      \"as,base,by,checked,decimal,delegate,descending,dynamic,event,\" +\n      \"fixed,foreach,from,group,implicit,in,internal,into,is,let,\" +\n      \"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,\" +\n      \"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,\" +\n      \"var,virtual,where\"];\n  var COFFEE_KEYWORDS = \"all,and,by,catch,class,else,extends,false,finally,\" +\n      \"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,\" +\n      \"throw,true,try,unless,until,when,while,yes\";\n  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,\n      \"debugger,eval,export,function,get,null,set,undefined,var,with,\" +\n      \"Infinity,NaN\"];\n  var PERL_KEYWORDS = \"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,\" +\n      \"goto,if,import,last,local,my,next,no,our,print,package,redo,require,\" +\n      \"sub,undef,unless,until,use,wantarray,while,BEGIN,END\";\n  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"and,as,assert,class,def,del,\" +\n      \"elif,except,exec,finally,from,global,import,in,is,lambda,\" +\n      \"nonlocal,not,or,pass,print,raise,try,with,yield,\" +\n      \"False,True,None\"];\n  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"alias,and,begin,case,class,\" +\n      \"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,\" +\n      \"rescue,retry,self,super,then,true,undef,unless,until,when,yield,\" +\n      \"BEGIN,END\"];\n   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"as,assert,const,copy,drop,\" +\n      \"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,\" +\n      \"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"];\n  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, \"case,done,elif,esac,eval,fi,\" +\n      \"function,in,local,set,then,until\"];\n  var ALL_KEYWORDS = [\n      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,\n      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];\n  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/;\n\n  // token style names.  correspond to css classes\n  /**\n   * token style for a string literal\n   * @const\n   */\n  var PR_STRING = 'str';\n  /**\n   * token style for a keyword\n   * @const\n   */\n  var PR_KEYWORD = 'kwd';\n  /**\n   * token style for a comment\n   * @const\n   */\n  var PR_COMMENT = 'com';\n  /**\n   * token style for a type\n   * @const\n   */\n  var PR_TYPE = 'typ';\n  /**\n   * token style for a literal value.  e.g. 1, null, true.\n   * @const\n   */\n  var PR_LITERAL = 'lit';\n  /**\n   * token style for a punctuation string.\n   * @const\n   */\n  var PR_PUNCTUATION = 'pun';\n  /**\n   * token style for plain text.\n   * @const\n   */\n  var PR_PLAIN = 'pln';\n\n  /**\n   * token style for an sgml tag.\n   * @const\n   */\n  var PR_TAG = 'tag';\n  /**\n   * token style for a markup declaration such as a DOCTYPE.\n   * @const\n   */\n  var PR_DECLARATION = 'dec';\n  /**\n   * token style for embedded source.\n   * @const\n   */\n  var PR_SOURCE = 'src';\n  /**\n   * token style for an sgml attribute name.\n   * @const\n   */\n  var PR_ATTRIB_NAME = 'atn';\n  /**\n   * token style for an sgml attribute value.\n   * @const\n   */\n  var PR_ATTRIB_VALUE = 'atv';\n\n  /**\n   * A class that indicates a section of markup that is not code, e.g. to allow\n   * embedding of line numbers within code listings.\n   * @const\n   */\n  var PR_NOCODE = 'nocode';\n\n  \n  \n  /**\n   * A set of tokens that can precede a regular expression literal in\n   * javascript\n   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html\n   * has the full list, but I've removed ones that might be problematic when\n   * seen in languages that don't support regular expression literals.\n   *\n   * <p>Specifically, I've removed any keywords that can't precede a regexp\n   * literal in a syntactically legal javascript program, and I've removed the\n   * \"in\" keyword since it's not a keyword in many languages, and might be used\n   * as a count of inches.\n   *\n   * <p>The link above does not accurately describe EcmaScript rules since\n   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works\n   * very well in practice.\n   *\n   * @private\n   * @const\n   */\n  var REGEXP_PRECEDER_PATTERN = '(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*';\n  \n  // CAVEAT: this does not properly handle the case where a regular\n  // expression immediately follows another since a regular expression may\n  // have flags for case-sensitivity and the like.  Having regexp tokens\n  // adjacent is not valid in any language I'm aware of, so I'm punting.\n  // TODO: maybe style special characters inside a regexp as punctuation.\n\n  /**\n   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally\n   * matches the union of the sets of strings matched by the input RegExp.\n   * Since it matches globally, if the input strings have a start-of-input\n   * anchor (/^.../), it is ignored for the purposes of unioning.\n   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.\n   * @return {RegExp} a global regex.\n   */\n  function combinePrefixPatterns(regexs) {\n    var capturedGroupIndex = 0;\n  \n    var needToFoldCase = false;\n    var ignoreCase = false;\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.ignoreCase) {\n        ignoreCase = true;\n      } else if (/[a-z]/i.test(regex.source.replace(\n                     /\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi, ''))) {\n        needToFoldCase = true;\n        ignoreCase = false;\n        break;\n      }\n    }\n  \n    var escapeCharToCodeUnit = {\n      'b': 8,\n      't': 9,\n      'n': 0xa,\n      'v': 0xb,\n      'f': 0xc,\n      'r': 0xd\n    };\n  \n    function decodeEscape(charsetPart) {\n      var cc0 = charsetPart.charCodeAt(0);\n      if (cc0 !== 92 /* \\\\ */) {\n        return cc0;\n      }\n      var c1 = charsetPart.charAt(1);\n      cc0 = escapeCharToCodeUnit[c1];\n      if (cc0) {\n        return cc0;\n      } else if ('0' <= c1 && c1 <= '7') {\n        return parseInt(charsetPart.substring(1), 8);\n      } else if (c1 === 'u' || c1 === 'x') {\n        return parseInt(charsetPart.substring(2), 16);\n      } else {\n        return charsetPart.charCodeAt(1);\n      }\n    }\n  \n    function encodeEscape(charCode) {\n      if (charCode < 0x20) {\n        return (charCode < 0x10 ? '\\\\x0' : '\\\\x') + charCode.toString(16);\n      }\n      var ch = String.fromCharCode(charCode);\n      return (ch === '\\\\' || ch === '-' || ch === ']' || ch === '^')\n          ? \"\\\\\" + ch : ch;\n    }\n  \n    function caseFoldCharset(charSet) {\n      var charsetParts = charSet.substring(1, charSet.length - 1).match(\n          new RegExp(\n              '\\\\\\\\u[0-9A-Fa-f]{4}'\n              + '|\\\\\\\\x[0-9A-Fa-f]{2}'\n              + '|\\\\\\\\[0-3][0-7]{0,2}'\n              + '|\\\\\\\\[0-7]{1,2}'\n              + '|\\\\\\\\[\\\\s\\\\S]'\n              + '|-'\n              + '|[^-\\\\\\\\]',\n              'g'));\n      var ranges = [];\n      var inverse = charsetParts[0] === '^';\n  \n      var out = ['['];\n      if (inverse) { out.push('^'); }\n  \n      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {\n        var p = charsetParts[i];\n        if (/\\\\[bdsw]/i.test(p)) {  // Don't muck with named groups.\n          out.push(p);\n        } else {\n          var start = decodeEscape(p);\n          var end;\n          if (i + 2 < n && '-' === charsetParts[i + 1]) {\n            end = decodeEscape(charsetParts[i + 2]);\n            i += 2;\n          } else {\n            end = start;\n          }\n          ranges.push([start, end]);\n          // If the range might intersect letters, then expand it.\n          // This case handling is too simplistic.\n          // It does not deal with non-latin case folding.\n          // It works for latin source code identifiers though.\n          if (!(end < 65 || start > 122)) {\n            if (!(end < 65 || start > 90)) {\n              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);\n            }\n            if (!(end < 97 || start > 122)) {\n              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);\n            }\n          }\n        }\n      }\n  \n      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]\n      // -> [[1, 12], [14, 14], [16, 17]]\n      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });\n      var consolidatedRanges = [];\n      var lastRange = [];\n      for (var i = 0; i < ranges.length; ++i) {\n        var range = ranges[i];\n        if (range[0] <= lastRange[1] + 1) {\n          lastRange[1] = Math.max(lastRange[1], range[1]);\n        } else {\n          consolidatedRanges.push(lastRange = range);\n        }\n      }\n  \n      for (var i = 0; i < consolidatedRanges.length; ++i) {\n        var range = consolidatedRanges[i];\n        out.push(encodeEscape(range[0]));\n        if (range[1] > range[0]) {\n          if (range[1] + 1 > range[0]) { out.push('-'); }\n          out.push(encodeEscape(range[1]));\n        }\n      }\n      out.push(']');\n      return out.join('');\n    }\n  \n    function allowAnywhereFoldCaseAndRenumberGroups(regex) {\n      // Split into character sets, escape sequences, punctuation strings\n      // like ('(', '(?:', ')', '^'), and runs of characters that do not\n      // include any of the above.\n      var parts = regex.source.match(\n          new RegExp(\n              '(?:'\n              + '\\\\[(?:[^\\\\x5C\\\\x5D]|\\\\\\\\[\\\\s\\\\S])*\\\\]'  // a character set\n              + '|\\\\\\\\u[A-Fa-f0-9]{4}'  // a unicode escape\n              + '|\\\\\\\\x[A-Fa-f0-9]{2}'  // a hex escape\n              + '|\\\\\\\\[0-9]+'  // a back-reference or octal escape\n              + '|\\\\\\\\[^ux0-9]'  // other escape sequence\n              + '|\\\\(\\\\?[:!=]'  // start of a non-capturing group\n              + '|[\\\\(\\\\)\\\\^]'  // start/end of a group, or line start\n              + '|[^\\\\x5B\\\\x5C\\\\(\\\\)\\\\^]+'  // run of other characters\n              + ')',\n              'g'));\n      var n = parts.length;\n  \n      // Maps captured group numbers to the number they will occupy in\n      // the output or to -1 if that has not been determined, or to\n      // undefined if they need not be capturing in the output.\n      var capturedGroups = [];\n  \n      // Walk over and identify back references to build the capturedGroups\n      // mapping.\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          // groups are 1-indexed, so max group index is count of '('\n          ++groupIndex;\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue) {\n            if (decimalValue <= groupIndex) {\n              capturedGroups[decimalValue] = -1;\n            } else {\n              // Replace with an unambiguous escape sequence so that\n              // an octal escape sequence does not turn into a backreference\n              // to a capturing group from an earlier regex.\n              parts[i] = encodeEscape(decimalValue);\n            }\n          }\n        }\n      }\n  \n      // Renumber groups and reduce capturing groups to non-capturing groups\n      // where possible.\n      for (var i = 1; i < capturedGroups.length; ++i) {\n        if (-1 === capturedGroups[i]) {\n          capturedGroups[i] = ++capturedGroupIndex;\n        }\n      }\n      for (var i = 0, groupIndex = 0; i < n; ++i) {\n        var p = parts[i];\n        if (p === '(') {\n          ++groupIndex;\n          if (!capturedGroups[groupIndex]) {\n            parts[i] = '(?:';\n          }\n        } else if ('\\\\' === p.charAt(0)) {\n          var decimalValue = +p.substring(1);\n          if (decimalValue && decimalValue <= groupIndex) {\n            parts[i] = '\\\\' + capturedGroups[decimalValue];\n          }\n        }\n      }\n  \n      // Remove any prefix anchors so that the output will match anywhere.\n      // ^^ really does mean an anchored match though.\n      for (var i = 0; i < n; ++i) {\n        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }\n      }\n  \n      // Expand letters to groups to handle mixing of case-sensitive and\n      // case-insensitive patterns if necessary.\n      if (regex.ignoreCase && needToFoldCase) {\n        for (var i = 0; i < n; ++i) {\n          var p = parts[i];\n          var ch0 = p.charAt(0);\n          if (p.length >= 2 && ch0 === '[') {\n            parts[i] = caseFoldCharset(p);\n          } else if (ch0 !== '\\\\') {\n            // TODO: handle letters in numeric escapes.\n            parts[i] = p.replace(\n                /[a-zA-Z]/g,\n                function (ch) {\n                  var cc = ch.charCodeAt(0);\n                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';\n                });\n          }\n        }\n      }\n  \n      return parts.join('');\n    }\n  \n    var rewritten = [];\n    for (var i = 0, n = regexs.length; i < n; ++i) {\n      var regex = regexs[i];\n      if (regex.global || regex.multiline) { throw new Error('' + regex); }\n      rewritten.push(\n          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');\n    }\n  \n    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');\n  }\n\n  /**\n   * Split markup into a string of source code and an array mapping ranges in\n   * that string to the text nodes in which they appear.\n   *\n   * <p>\n   * The HTML DOM structure:</p>\n   * <pre>\n   * (Element   \"p\"\n   *   (Element \"b\"\n   *     (Text  \"print \"))       ; #1\n   *   (Text    \"'Hello '\")      ; #2\n   *   (Element \"br\")            ; #3\n   *   (Text    \"  + 'World';\")) ; #4\n   * </pre>\n   * <p>\n   * corresponds to the HTML\n   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>\n   *\n   * <p>\n   * It will produce the output:</p>\n   * <pre>\n   * {\n   *   sourceCode: \"print 'Hello '\\n  + 'World';\",\n   *   //                     1          2\n   *   //           012345678901234 5678901234567\n   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]\n   * }\n   * </pre>\n   * <p>\n   * where #1 is a reference to the {@code \"print \"} text node above, and so\n   * on for the other text nodes.\n   * </p>\n   *\n   * <p>\n   * The {@code} spans array is an array of pairs.  Even elements are the start\n   * indices of substrings, and odd elements are the text nodes (or BR elements)\n   * that contain the text for those substrings.\n   * Substrings continue until the next index or the end of the source.\n   * </p>\n   *\n   * @param {Node} node an HTML DOM subtree containing source-code.\n   * @param {boolean} isPreformatted true if white-space in text nodes should\n   *    be considered significant.\n   * @return {Object} source code and the text nodes in which they occur.\n   */\n  function extractSourceSpans(node, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n  \n    var chunks = [];\n    var length = 0;\n    var spans = [];\n    var k = 0;\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1) {  // Element\n        if (nocode.test(node.className)) { return; }\n        for (var child = node.firstChild; child; child = child.nextSibling) {\n          walk(child);\n        }\n        var nodeName = node.nodeName.toLowerCase();\n        if ('br' === nodeName || 'li' === nodeName) {\n          chunks[k] = '\\n';\n          spans[k << 1] = length++;\n          spans[(k++ << 1) | 1] = node;\n        }\n      } else if (type == 3 || type == 4) {  // Text\n        var text = node.nodeValue;\n        if (text.length) {\n          if (!isPreformatted) {\n            text = text.replace(/[ \\t\\r\\n]+/g, ' ');\n          } else {\n            text = text.replace(/\\r\\n?/g, '\\n');  // Normalize newlines.\n          }\n          // TODO: handle tabs here?\n          chunks[k] = text;\n          spans[k << 1] = length;\n          length += text.length;\n          spans[(k++ << 1) | 1] = node;\n        }\n      }\n    }\n  \n    walk(node);\n  \n    return {\n      sourceCode: chunks.join('').replace(/\\n$/, ''),\n      spans: spans\n    };\n  }\n\n  /**\n   * Apply the given language handler to sourceCode and add the resulting\n   * decorations to out.\n   * @param {number} basePos the index of sourceCode within the chunk of source\n   *    whose decorations are already present on out.\n   */\n  function appendDecorations(basePos, sourceCode, langHandler, out) {\n    if (!sourceCode) { return; }\n    var job = {\n      sourceCode: sourceCode,\n      basePos: basePos\n    };\n    langHandler(job);\n    out.push.apply(out, job.decorations);\n  }\n\n  var notWs = /\\S/;\n\n  /**\n   * Given an element, if it contains only one child element and any text nodes\n   * it contains contain only space characters, return the sole child element.\n   * Otherwise returns undefined.\n   * <p>\n   * This is meant to return the CODE element in {@code <pre><code ...>} when\n   * there is a single child element that contains all the non-space textual\n   * content, but not to return anything where there are multiple child elements\n   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there\n   * is textual content.\n   */\n  function childContentWrapper(element) {\n    var wrapper = undefined;\n    for (var c = element.firstChild; c; c = c.nextSibling) {\n      var type = c.nodeType;\n      wrapper = (type === 1)  // Element Node\n          ? (wrapper ? element : c)\n          : (type === 3)  // Text Node\n          ? (notWs.test(c.nodeValue) ? element : wrapper)\n          : wrapper;\n    }\n    return wrapper === element ? undefined : wrapper;\n  }\n\n  /** Given triples of [style, pattern, context] returns a lexing function,\n    * The lexing function interprets the patterns to find token boundaries and\n    * returns a decoration list of the form\n    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]\n    * where index_n is an index into the sourceCode, and style_n is a style\n    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to\n    * all characters in sourceCode[index_n-1:index_n].\n    *\n    * The stylePatterns is a list whose elements have the form\n    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].\n    *\n    * Style is a style constant like PR_PLAIN, or can be a string of the\n    * form 'lang-FOO', where FOO is a language extension describing the\n    * language of the portion of the token in $1 after pattern executes.\n    * E.g., if style is 'lang-lisp', and group 1 contains the text\n    * '(hello (world))', then that portion of the token will be passed to the\n    * registered lisp handler for formatting.\n    * The text before and after group 1 will be restyled using this decorator\n    * so decorators should take care that this doesn't result in infinite\n    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks\n    * something like ['lang-js', /<[s]cript>(.+?)<\\/script>/].  This may match\n    * '<script>foo()<\\/script>', which would cause the current decorator to\n    * be called with '<script>' which would not match the same rule since\n    * group 1 must not be empty, so it would be instead styled as PR_TAG by\n    * the generic tag rule.  The handler registered for the 'js' extension would\n    * then be called with 'foo()', and finally, the current decorator would\n    * be called with '<\\/script>' which would not match the original rule and\n    * so the generic tag rule would identify it as a tag.\n    *\n    * Pattern must only match prefixes, and if it matches a prefix, then that\n    * match is considered a token with the same style.\n    *\n    * Context is applied to the last non-whitespace, non-comment token\n    * recognized.\n    *\n    * Shortcut is an optional string of characters, any of which, if the first\n    * character, gurantee that this pattern and only this pattern matches.\n    *\n    * @param {Array} shortcutStylePatterns patterns that always start with\n    *   a known character.  Must have a shortcut string.\n    * @param {Array} fallthroughStylePatterns patterns that will be tried in\n    *   order if the shortcut ones fail.  May have shortcuts.\n    *\n    * @return {function (Object)} a\n    *   function that takes source code and returns a list of decorations.\n    */\n  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {\n    var shortcuts = {};\n    var tokenizer;\n    (function () {\n      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);\n      var allRegexs = [];\n      var regexKeys = {};\n      for (var i = 0, n = allPatterns.length; i < n; ++i) {\n        var patternParts = allPatterns[i];\n        var shortcutChars = patternParts[3];\n        if (shortcutChars) {\n          for (var c = shortcutChars.length; --c >= 0;) {\n            shortcuts[shortcutChars.charAt(c)] = patternParts;\n          }\n        }\n        var regex = patternParts[1];\n        var k = '' + regex;\n        if (!regexKeys.hasOwnProperty(k)) {\n          allRegexs.push(regex);\n          regexKeys[k] = null;\n        }\n      }\n      allRegexs.push(/[\\0-\\uffff]/);\n      tokenizer = combinePrefixPatterns(allRegexs);\n    })();\n\n    var nPatterns = fallthroughStylePatterns.length;\n\n    /**\n     * Lexes job.sourceCode and produces an output array job.decorations of\n     * style classes preceded by the position at which they start in\n     * job.sourceCode in order.\n     *\n     * @param {Object} job an object like <pre>{\n     *    sourceCode: {string} sourceText plain text,\n     *    basePos: {int} position of job.sourceCode in the larger chunk of\n     *        sourceCode.\n     * }</pre>\n     */\n    var decorate = function (job) {\n      var sourceCode = job.sourceCode, basePos = job.basePos;\n      /** Even entries are positions in source in ascending order.  Odd enties\n        * are style markers (e.g., PR_COMMENT) that run from that position until\n        * the end.\n        * @type {Array.<number|string>}\n        */\n      var decorations = [basePos, PR_PLAIN];\n      var pos = 0;  // index into sourceCode\n      var tokens = sourceCode.match(tokenizer) || [];\n      var styleCache = {};\n\n      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {\n        var token = tokens[ti];\n        var style = styleCache[token];\n        var match = void 0;\n\n        var isEmbedded;\n        if (typeof style === 'string') {\n          isEmbedded = false;\n        } else {\n          var patternParts = shortcuts[token.charAt(0)];\n          if (patternParts) {\n            match = token.match(patternParts[1]);\n            style = patternParts[0];\n          } else {\n            for (var i = 0; i < nPatterns; ++i) {\n              patternParts = fallthroughStylePatterns[i];\n              match = token.match(patternParts[1]);\n              if (match) {\n                style = patternParts[0];\n                break;\n              }\n            }\n\n            if (!match) {  // make sure that we make progress\n              style = PR_PLAIN;\n            }\n          }\n\n          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);\n          if (isEmbedded && !(match && typeof match[1] === 'string')) {\n            isEmbedded = false;\n            style = PR_SOURCE;\n          }\n\n          if (!isEmbedded) { styleCache[token] = style; }\n        }\n\n        var tokenStart = pos;\n        pos += token.length;\n\n        if (!isEmbedded) {\n          decorations.push(basePos + tokenStart, style);\n        } else {  // Treat group 1 as an embedded block of source code.\n          var embeddedSource = match[1];\n          var embeddedSourceStart = token.indexOf(embeddedSource);\n          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;\n          if (match[2]) {\n            // If embeddedSource can be blank, then it would match at the\n            // beginning which would cause us to infinitely recurse on the\n            // entire token, so we catch the right context in match[2].\n            embeddedSourceEnd = token.length - match[2].length;\n            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;\n          }\n          var lang = style.substring(5);\n          // Decorate the left of the embedded source\n          appendDecorations(\n              basePos + tokenStart,\n              token.substring(0, embeddedSourceStart),\n              decorate, decorations);\n          // Decorate the embedded source\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceStart,\n              embeddedSource,\n              langHandlerForExtension(lang, embeddedSource),\n              decorations);\n          // Decorate the right of the embedded section\n          appendDecorations(\n              basePos + tokenStart + embeddedSourceEnd,\n              token.substring(embeddedSourceEnd),\n              decorate, decorations);\n        }\n      }\n      job.decorations = decorations;\n    };\n    return decorate;\n  }\n\n  /** returns a function that produces a list of decorations from source text.\n    *\n    * This code treats \", ', and ` as string delimiters, and \\ as a string\n    * escape.  It does not recognize perl's qq() style strings.\n    * It has no special handling for double delimiter escapes as in basic, or\n    * the tripled delimiters used in python, but should work on those regardless\n    * although in those cases a single string literal may be broken up into\n    * multiple adjacent string literals.\n    *\n    * It recognizes C, C++, and shell style comments.\n    *\n    * @param {Object} options a set of optional parameters.\n    * @return {function (Object)} a function that examines the source code\n    *     in the input job and builds the decoration list.\n    */\n  function sourceDecorator(options) {\n    var shortcutStylePatterns = [], fallthroughStylePatterns = [];\n    if (options['tripleQuotedStrings']) {\n      // '''multi-line-string''', 'single-line-string', and double-quoted\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\n           null, '\\'\"']);\n    } else if (options['multiLineStrings']) {\n      // 'multi-line-string', \"multi-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,  /^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,\n           null, '\\'\"`']);\n    } else {\n      // 'single-line-string', \"single-line-string\"\n      shortcutStylePatterns.push(\n          [PR_STRING,\n           /^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,\n           null, '\"\\'']);\n    }\n    if (options['verbatimStrings']) {\n      // verbatim-string-literal production from the C# grammar.  See issue 93.\n      fallthroughStylePatterns.push(\n          [PR_STRING, /^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/, null]);\n    }\n    var hc = options['hashComments'];\n    if (hc) {\n      if (options['cStyleComments']) {\n        if (hc > 1) {  // multiline hash comments\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);\n        } else {\n          // Stop C preprocessor declarations at an unclosed open comment\n          shortcutStylePatterns.push(\n              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\n               null, '#']);\n        }\n        // #include <stdio.h>\n        fallthroughStylePatterns.push(\n            [PR_STRING,\n             /^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,\n             null]);\n      } else {\n        shortcutStylePatterns.push([PR_COMMENT, /^#[^\\r\\n]*/, null, '#']);\n      }\n    }\n    if (options['cStyleComments']) {\n      fallthroughStylePatterns.push([PR_COMMENT, /^\\/\\/[^\\r\\n]*/, null]);\n      fallthroughStylePatterns.push(\n          [PR_COMMENT, /^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/, null]);\n    }\n    var regexLiterals = options['regexLiterals'];\n    if (regexLiterals) {\n      /**\n       * @const\n       */\n      var regexExcls = regexLiterals > 1\n        ? ''  // Multiline regex literals\n        : '\\n\\r';\n      /**\n       * @const\n       */\n      var regexAny = regexExcls ? '.' : '[\\\\S\\\\s]';\n      /**\n       * @const\n       */\n      var REGEX_LITERAL = (\n          // A regular expression literal starts with a slash that is\n          // not followed by * or / so that it is not confused with\n          // comments.\n          '/(?=[^/*' + regexExcls + '])'\n          // and then contains any number of raw characters,\n          + '(?:[^/\\\\x5B\\\\x5C' + regexExcls + ']'\n          // escape sequences (\\x5C),\n          +    '|\\\\x5C' + regexAny\n          // or non-nesting character sets (\\x5B\\x5D);\n          +    '|\\\\x5B(?:[^\\\\x5C\\\\x5D' + regexExcls + ']'\n          +             '|\\\\x5C' + regexAny + ')*(?:\\\\x5D|$))+'\n          // finally closed by a /.\n          + '/');\n      fallthroughStylePatterns.push(\n          ['lang-regex',\n           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')\n           ]);\n    }\n\n    var types = options['types'];\n    if (types) {\n      fallthroughStylePatterns.push([PR_TYPE, types]);\n    }\n\n    var keywords = (\"\" + options['keywords']).replace(/^ | $/g, '');\n    if (keywords.length) {\n      fallthroughStylePatterns.push(\n          [PR_KEYWORD,\n           new RegExp('^(?:' + keywords.replace(/[\\s,]+/g, '|') + ')\\\\b'),\n           null]);\n    }\n\n    shortcutStylePatterns.push([PR_PLAIN,       /^\\s+/, null, ' \\r\\n\\t\\xA0']);\n\n    var punctuation =\n      // The Bash man page says\n\n      // A word is a sequence of characters considered as a single\n      // unit by GRUB. Words are separated by metacharacters,\n      // which are the following plus space, tab, and newline: { }\n      // | & $ ; < >\n      // ...\n      \n      // A word beginning with # causes that word and all remaining\n      // characters on that line to be ignored.\n\n      // which means that only a '#' after /(?:^|[{}|&$;<>\\s])/ starts a\n      // comment but empirically\n      // $ echo {#}\n      // {#}\n      // $ echo \\$#\n      // $#\n      // $ echo }#\n      // }#\n\n      // so /(?:^|[|&;<>\\s])/ is more appropriate.\n\n      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3\n      // suggests that this definition is compatible with a\n      // default mode that tries to use a single token definition\n      // to recognize both bash/python style comments and C\n      // preprocessor directives.\n\n      // This definition of punctuation does not include # in the list of\n      // follow-on exclusions, so # will not be broken before if preceeded\n      // by a punctuation character.  We could try to exclude # after\n      // [|&;<>] but that doesn't seem to cause many major problems.\n      // If that does turn out to be a problem, we should change the below\n      // when hc is truthy to include # in the run of punctuation characters\n      // only when not followint [|&;<>].\n      '^.[^\\\\s\\\\w.$@\\'\"`/\\\\\\\\]*';\n    if (options['regexLiterals']) {\n      punctuation += '(?!\\s*\\/)';\n    }\n\n    fallthroughStylePatterns.push(\n        // TODO(mikesamuel): recognize non-latin letters and numerals in idents\n        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/, null],\n        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],\n        [PR_LITERAL,\n         new RegExp(\n             '^(?:'\n             // A hex number\n             + '0x[a-f0-9]+'\n             // or an octal or decimal number,\n             + '|(?:\\\\d(?:_\\\\d+)*\\\\d*(?:\\\\.\\\\d*)?|\\\\.\\\\d\\\\+)'\n             // possibly in scientific notation\n             + '(?:e[+\\\\-]?\\\\d+)?'\n             + ')'\n             // with an optional modifier like UL for unsigned long\n             + '[a-z]*', 'i'),\n         null, '0123456789'],\n        // Don't treat escaped quotes in bash as starting strings.\n        // See issue 144.\n        [PR_PLAIN,       /^\\\\[\\s\\S]?/, null],\n        [PR_PUNCTUATION, new RegExp(punctuation), null]);\n\n    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);\n  }\n\n  var decorateSource = sourceDecorator({\n        'keywords': ALL_KEYWORDS,\n        'hashComments': true,\n        'cStyleComments': true,\n        'multiLineStrings': true,\n        'regexLiterals': true\n      });\n\n  /**\n   * Given a DOM subtree, wraps it in a list, and puts each line into its own\n   * list item.\n   *\n   * @param {Node} node modified in place.  Its content is pulled into an\n   *     HTMLOListElement, and each line is moved into a separate list item.\n   *     This requires cloning elements, so the input might not have unique\n   *     IDs after numbering.\n   * @param {boolean} isPreformatted true iff white-space in text nodes should\n   *     be treated as significant.\n   */\n  function numberLines(node, opt_startLineNum, isPreformatted) {\n    var nocode = /(?:^|\\s)nocode(?:\\s|$)/;\n    var lineBreak = /\\r\\n?|\\n/;\n  \n    var document = node.ownerDocument;\n  \n    var li = document.createElement('li');\n    while (node.firstChild) {\n      li.appendChild(node.firstChild);\n    }\n    // An array of lines.  We split below, so this is initialized to one\n    // un-split line.\n    var listItems = [li];\n  \n    function walk(node) {\n      var type = node.nodeType;\n      if (type == 1 && !nocode.test(node.className)) {  // Element\n        if ('br' === node.nodeName) {\n          breakAfter(node);\n          // Discard the <BR> since it is now flush against a </LI>.\n          if (node.parentNode) {\n            node.parentNode.removeChild(node);\n          }\n        } else {\n          for (var child = node.firstChild; child; child = child.nextSibling) {\n            walk(child);\n          }\n        }\n      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text\n        var text = node.nodeValue;\n        var match = text.match(lineBreak);\n        if (match) {\n          var firstLine = text.substring(0, match.index);\n          node.nodeValue = firstLine;\n          var tail = text.substring(match.index + match[0].length);\n          if (tail) {\n            var parent = node.parentNode;\n            parent.insertBefore(\n              document.createTextNode(tail), node.nextSibling);\n          }\n          breakAfter(node);\n          if (!firstLine) {\n            // Don't leave blank text nodes in the DOM.\n            node.parentNode.removeChild(node);\n          }\n        }\n      }\n    }\n  \n    // Split a line after the given node.\n    function breakAfter(lineEndNode) {\n      // If there's nothing to the right, then we can skip ending the line\n      // here, and move root-wards since splitting just before an end-tag\n      // would require us to create a bunch of empty copies.\n      while (!lineEndNode.nextSibling) {\n        lineEndNode = lineEndNode.parentNode;\n        if (!lineEndNode) { return; }\n      }\n  \n      function breakLeftOf(limit, copy) {\n        // Clone shallowly if this node needs to be on both sides of the break.\n        var rightSide = copy ? limit.cloneNode(false) : limit;\n        var parent = limit.parentNode;\n        if (parent) {\n          // We clone the parent chain.\n          // This helps us resurrect important styling elements that cross lines.\n          // E.g. in <i>Foo<br>Bar</i>\n          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.\n          var parentClone = breakLeftOf(parent, 1);\n          // Move the clone and everything to the right of the original\n          // onto the cloned parent.\n          var next = limit.nextSibling;\n          parentClone.appendChild(rightSide);\n          for (var sibling = next; sibling; sibling = next) {\n            next = sibling.nextSibling;\n            parentClone.appendChild(sibling);\n          }\n        }\n        return rightSide;\n      }\n  \n      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);\n  \n      // Walk the parent chain until we reach an unattached LI.\n      for (var parent;\n           // Check nodeType since IE invents document fragments.\n           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {\n        copiedListItem = parent;\n      }\n      // Put it on the list of lines for later processing.\n      listItems.push(copiedListItem);\n    }\n  \n    // Split lines while there are lines left to split.\n    for (var i = 0;  // Number of lines that have been split so far.\n         i < listItems.length;  // length updated by breakAfter calls.\n         ++i) {\n      walk(listItems[i]);\n    }\n  \n    // Make sure numeric indices show correctly.\n    if (opt_startLineNum === (opt_startLineNum|0)) {\n      listItems[0].setAttribute('value', opt_startLineNum);\n    }\n  \n    var ol = document.createElement('ol');\n    ol.className = 'linenums';\n    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;\n    for (var i = 0, n = listItems.length; i < n; ++i) {\n      li = listItems[i];\n      // Stick a class on the LIs so that stylesheets can\n      // color odd/even rows, or any other row pattern that\n      // is co-prime with 10.\n      li.className = 'L' + ((i + offset) % 10);\n      if (!li.firstChild) {\n        li.appendChild(document.createTextNode('\\xA0'));\n      }\n      ol.appendChild(li);\n    }\n  \n    node.appendChild(ol);\n  }\n  /**\n   * Breaks {@code job.sourceCode} around style boundaries in\n   * {@code job.decorations} and modifies {@code job.sourceNode} in place.\n   * @param {Object} job like <pre>{\n   *    sourceCode: {string} source as plain text,\n   *    sourceNode: {HTMLElement} the element containing the source,\n   *    spans: {Array.<number|Node>} alternating span start indices into source\n   *       and the text node or element (e.g. {@code <BR>}) corresponding to that\n   *       span.\n   *    decorations: {Array.<number|string} an array of style classes preceded\n   *       by the position at which they start in job.sourceCode in order\n   * }</pre>\n   * @private\n   */\n  function recombineTagsAndDecorations(job) {\n    var isIE8OrEarlier = /\\bMSIE\\s(\\d+)/.exec(navigator.userAgent);\n    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;\n    var newlineRe = /\\n/g;\n  \n    var source = job.sourceCode;\n    var sourceLength = source.length;\n    // Index into source after the last code-unit recombined.\n    var sourceIndex = 0;\n  \n    var spans = job.spans;\n    var nSpans = spans.length;\n    // Index into spans after the last span which ends at or before sourceIndex.\n    var spanIndex = 0;\n  \n    var decorations = job.decorations;\n    var nDecorations = decorations.length;\n    // Index into decorations after the last decoration which ends at or before\n    // sourceIndex.\n    var decorationIndex = 0;\n  \n    // Remove all zero-length decorations.\n    decorations[nDecorations] = sourceLength;\n    var decPos, i;\n    for (i = decPos = 0; i < nDecorations;) {\n      if (decorations[i] !== decorations[i + 2]) {\n        decorations[decPos++] = decorations[i++];\n        decorations[decPos++] = decorations[i++];\n      } else {\n        i += 2;\n      }\n    }\n    nDecorations = decPos;\n  \n    // Simplify decorations.\n    for (i = decPos = 0; i < nDecorations;) {\n      var startPos = decorations[i];\n      // Conflate all adjacent decorations that use the same style.\n      var startDec = decorations[i + 1];\n      var end = i + 2;\n      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {\n        end += 2;\n      }\n      decorations[decPos++] = startPos;\n      decorations[decPos++] = startDec;\n      i = end;\n    }\n  \n    nDecorations = decorations.length = decPos;\n  \n    var sourceNode = job.sourceNode;\n    var oldDisplay;\n    if (sourceNode) {\n      oldDisplay = sourceNode.style.display;\n      sourceNode.style.display = 'none';\n    }\n    try {\n      var decoration = null;\n      while (spanIndex < nSpans) {\n        var spanStart = spans[spanIndex];\n        var spanEnd = spans[spanIndex + 2] || sourceLength;\n  \n        var decEnd = decorations[decorationIndex + 2] || sourceLength;\n  \n        var end = Math.min(spanEnd, decEnd);\n  \n        var textNode = spans[spanIndex + 1];\n        var styledText;\n        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s\n            // Don't introduce spans around empty text nodes.\n            && (styledText = source.substring(sourceIndex, end))) {\n          // This may seem bizarre, and it is.  Emitting LF on IE causes the\n          // code to display with spaces instead of line breaks.\n          // Emitting Windows standard issue linebreaks (CRLF) causes a blank\n          // space to appear at the beginning of every line but the first.\n          // Emitting an old Mac OS 9 line separator makes everything spiffy.\n          if (isIE8OrEarlier) {\n            styledText = styledText.replace(newlineRe, '\\r');\n          }\n          textNode.nodeValue = styledText;\n          var document = textNode.ownerDocument;\n          var span = document.createElement('span');\n          span.className = decorations[decorationIndex + 1];\n          var parentNode = textNode.parentNode;\n          parentNode.replaceChild(span, textNode);\n          span.appendChild(textNode);\n          if (sourceIndex < spanEnd) {  // Split off a text node.\n            spans[spanIndex + 1] = textNode\n                // TODO: Possibly optimize by using '' if there's no flicker.\n                = document.createTextNode(source.substring(end, spanEnd));\n            parentNode.insertBefore(textNode, span.nextSibling);\n          }\n        }\n  \n        sourceIndex = end;\n  \n        if (sourceIndex >= spanEnd) {\n          spanIndex += 2;\n        }\n        if (sourceIndex >= decEnd) {\n          decorationIndex += 2;\n        }\n      }\n    } finally {\n      if (sourceNode) {\n        sourceNode.style.display = oldDisplay;\n      }\n    }\n  }\n\n  /** Maps language-specific file extensions to handlers. */\n  var langHandlerRegistry = {};\n  /** Register a language handler for the given file extensions.\n    * @param {function (Object)} handler a function from source code to a list\n    *      of decorations.  Takes a single argument job which describes the\n    *      state of the computation.   The single parameter has the form\n    *      {@code {\n    *        sourceCode: {string} as plain text.\n    *        decorations: {Array.<number|string>} an array of style classes\n    *                     preceded by the position at which they start in\n    *                     job.sourceCode in order.\n    *                     The language handler should assigned this field.\n    *        basePos: {int} the position of source in the larger source chunk.\n    *                 All positions in the output decorations array are relative\n    *                 to the larger source chunk.\n    *      } }\n    * @param {Array.<string>} fileExtensions\n    */\n  function registerLangHandler(handler, fileExtensions) {\n    for (var i = fileExtensions.length; --i >= 0;) {\n      var ext = fileExtensions[i];\n      if (!langHandlerRegistry.hasOwnProperty(ext)) {\n        langHandlerRegistry[ext] = handler;\n      } else if (win['console']) {\n        console['warn']('cannot override language handler %s', ext);\n      }\n    }\n  }\n  function langHandlerForExtension(extension, source) {\n    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {\n      // Treat it as markup if the first non whitespace character is a < and\n      // the last non-whitespace character is a >.\n      extension = /^\\s*</.test(source)\n          ? 'default-markup'\n          : 'default-code';\n    }\n    return langHandlerRegistry[extension];\n  }\n  registerLangHandler(decorateSource, ['default-code']);\n  registerLangHandler(\n      createSimpleLexer(\n          [],\n          [\n           [PR_PLAIN,       /^[^<?]+/],\n           [PR_DECLARATION, /^<!\\w[^>]*(?:>|$)/],\n           [PR_COMMENT,     /^<\\!--[\\s\\S]*?(?:-\\->|$)/],\n           // Unescaped content in an unknown language\n           ['lang-',        /^<\\?([\\s\\S]+?)(?:\\?>|$)/],\n           ['lang-',        /^<%([\\s\\S]+?)(?:%>|$)/],\n           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],\n           ['lang-',        /^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],\n           // Unescaped content in javascript.  (Or possibly vbscript).\n           ['lang-js',      /^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],\n           // Contains unescaped stylesheet content\n           ['lang-css',     /^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],\n           ['lang-in.tag',  /^(<\\/?[a-z][^<>]*>)/i]\n          ]),\n      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);\n  registerLangHandler(\n      createSimpleLexer(\n          [\n           [PR_PLAIN,        /^[\\s]+/, null, ' \\t\\r\\n'],\n           [PR_ATTRIB_VALUE, /^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/, null, '\\\"\\'']\n           ],\n          [\n           [PR_TAG,          /^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],\n           [PR_ATTRIB_NAME,  /^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],\n           ['lang-uq.val',   /^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],\n           [PR_PUNCTUATION,  /^[=<>\\/]+/],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-js',       /^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],\n           ['lang-css',      /^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],\n           ['lang-css',      /^style\\s*=\\s*\\'([^\\']+)\\'/i],\n           ['lang-css',      /^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]\n           ]),\n      ['in.tag']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\\s\\S]+/]]), ['uq.val']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CPP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'types': C_TYPES\n        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': 'null,true,false'\n        }), ['json']);\n  registerLangHandler(sourceDecorator({\n          'keywords': CSHARP_KEYWORDS,\n          'hashComments': true,\n          'cStyleComments': true,\n          'verbatimStrings': true,\n          'types': C_TYPES\n        }), ['cs']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JAVA_KEYWORDS,\n          'cStyleComments': true\n        }), ['java']);\n  registerLangHandler(sourceDecorator({\n          'keywords': SH_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true\n        }), ['bash', 'bsh', 'csh', 'sh']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PYTHON_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'tripleQuotedStrings': true\n        }), ['cv', 'py', 'python']);\n  registerLangHandler(sourceDecorator({\n          'keywords': PERL_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': 2  // multiline regex literals\n        }), ['perl', 'pl', 'pm']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUBY_KEYWORDS,\n          'hashComments': true,\n          'multiLineStrings': true,\n          'regexLiterals': true\n        }), ['rb', 'ruby']);\n  registerLangHandler(sourceDecorator({\n          'keywords': JSCRIPT_KEYWORDS,\n          'cStyleComments': true,\n          'regexLiterals': true\n        }), ['javascript', 'js']);\n  registerLangHandler(sourceDecorator({\n          'keywords': COFFEE_KEYWORDS,\n          'hashComments': 3,  // ### style block comments\n          'cStyleComments': true,\n          'multilineStrings': true,\n          'tripleQuotedStrings': true,\n          'regexLiterals': true\n        }), ['coffee']);\n  registerLangHandler(sourceDecorator({\n          'keywords': RUST_KEYWORDS,\n          'cStyleComments': true,\n          'multilineStrings': true\n        }), ['rc', 'rs', 'rust']);\n  registerLangHandler(\n      createSimpleLexer([], [[PR_STRING, /^[\\s\\S]+/]]), ['regex']);\n\n  function applyDecorator(job) {\n    var opt_langExtension = job.langExtension;\n\n    try {\n      // Extract tags, and convert the source code to plain text.\n      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);\n      /** Plain text. @type {string} */\n      var source = sourceAndSpans.sourceCode;\n      job.sourceCode = source;\n      job.spans = sourceAndSpans.spans;\n      job.basePos = 0;\n\n      // Apply the appropriate language handler\n      langHandlerForExtension(opt_langExtension, source)(job);\n\n      // Integrate the decorations and tags back into the source code,\n      // modifying the sourceNode in place.\n      recombineTagsAndDecorations(job);\n    } catch (e) {\n      if (win['console']) {\n        console['log'](e && e['stack'] || e);\n      }\n    }\n  }\n\n  /**\n   * Pretty print a chunk of code.\n   * @param sourceCodeHtml {string} The HTML to pretty print.\n   * @param opt_langExtension {string} The language name to use.\n   *     Typically, a filename extension like 'cpp' or 'java'.\n   * @param opt_numberLines {number|boolean} True to number lines,\n   *     or the 1-indexed number of the first line in sourceCodeHtml.\n   */\n  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {\n    var container = document.createElement('div');\n    // This could cause images to load and onload listeners to fire.\n    // E.g. <img onerror=\"alert(1337)\" src=\"nosuchimage.png\">.\n    // We assume that the inner HTML is from a trusted source.\n    // The pre-tag is required for IE8 which strips newlines from innerHTML\n    // when it is injected into a <pre> tag.\n    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie\n    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript\n    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';\n    container = container.firstChild;\n    if (opt_numberLines) {\n      numberLines(container, opt_numberLines, true);\n    }\n\n    var job = {\n      langExtension: opt_langExtension,\n      numberLines: opt_numberLines,\n      sourceNode: container,\n      pre: 1\n    };\n    applyDecorator(job);\n    return container.innerHTML;\n  }\n\n   /**\n    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with\n    * {@code class=prettyprint} and prettify them.\n    *\n    * @param {Function} opt_whenDone called when prettifying is done.\n    * @param {HTMLElement|HTMLDocument} opt_root an element or document\n    *   containing all the elements to pretty print.\n    *   Defaults to {@code document.body}.\n    */\n  function $prettyPrint(opt_whenDone, opt_root) {\n    var root = opt_root || document.body;\n    var doc = root.ownerDocument || document;\n    function byTagName(tn) { return root.getElementsByTagName(tn); }\n    // fetch a list of nodes to rewrite\n    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];\n    var elements = [];\n    for (var i = 0; i < codeSegments.length; ++i) {\n      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {\n        elements.push(codeSegments[i][j]);\n      }\n    }\n    codeSegments = null;\n\n    var clock = Date;\n    if (!clock['now']) {\n      clock = { 'now': function () { return +(new Date); } };\n    }\n\n    // The loop is broken into a series of continuations to make sure that we\n    // don't make the browser unresponsive when rewriting a large page.\n    var k = 0;\n    var prettyPrintingJob;\n\n    var langExtensionRe = /\\blang(?:uage)?-([\\w.]+)(?!\\S)/;\n    var prettyPrintRe = /\\bprettyprint\\b/;\n    var prettyPrintedRe = /\\bprettyprinted\\b/;\n    var preformattedTagNameRe = /pre|xmp/i;\n    var codeRe = /^code$/i;\n    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;\n    var EMPTY = {};\n\n    function doWork() {\n      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?\n                     clock['now']() + 250 /* ms */ :\n                     Infinity);\n      for (; k < elements.length && clock['now']() < endTime; k++) {\n        var cs = elements[k];\n\n        // Look for a preceding comment like\n        // <?prettify lang=\"...\" linenums=\"...\"?>\n        var attrs = EMPTY;\n        {\n          for (var preceder = cs; (preceder = preceder.previousSibling);) {\n            var nt = preceder.nodeType;\n            // <?foo?> is parsed by HTML 5 to a comment node (8)\n            // like <!--?foo?-->, but in XML is a processing instruction\n            var value = (nt === 7 || nt === 8) && preceder.nodeValue;\n            if (value\n                ? !/^\\??prettify\\b/.test(value)\n                : (nt !== 3 || /\\S/.test(preceder.nodeValue))) {\n              // Skip over white-space text nodes but not others.\n              break;\n            }\n            if (value) {\n              attrs = {};\n              value.replace(\n                  /\\b(\\w+)=([\\w:.%+-]+)/g,\n                function (_, name, value) { attrs[name] = value; });\n              break;\n            }\n          }\n        }\n\n        var className = cs.className;\n        if ((attrs !== EMPTY || prettyPrintRe.test(className))\n            // Don't redo this if we've already done it.\n            // This allows recalling pretty print to just prettyprint elements\n            // that have been added to the page since last call.\n            && !prettyPrintedRe.test(className)) {\n\n          // make sure this is not nested in an already prettified element\n          var nested = false;\n          for (var p = cs.parentNode; p; p = p.parentNode) {\n            var tn = p.tagName;\n            if (preCodeXmpRe.test(tn)\n                && p.className && prettyPrintRe.test(p.className)) {\n              nested = true;\n              break;\n            }\n          }\n          if (!nested) {\n            // Mark done.  If we fail to prettyprint for whatever reason,\n            // we shouldn't try again.\n            cs.className += ' prettyprinted';\n\n            // If the classes includes a language extensions, use it.\n            // Language extensions can be specified like\n            //     <pre class=\"prettyprint lang-cpp\">\n            // the language extension \"cpp\" is used to find a language handler\n            // as passed to PR.registerLangHandler.\n            // HTML5 recommends that a language be specified using \"language-\"\n            // as the prefix instead.  Google Code Prettify supports both.\n            // http://dev.w3.org/html5/spec-author-view/the-code-element.html\n            var langExtension = attrs['lang'];\n            if (!langExtension) {\n              langExtension = className.match(langExtensionRe);\n              // Support <pre class=\"prettyprint\"><code class=\"language-c\">\n              var wrapper;\n              if (!langExtension && (wrapper = childContentWrapper(cs))\n                  && codeRe.test(wrapper.tagName)) {\n                langExtension = wrapper.className.match(langExtensionRe);\n              }\n\n              if (langExtension) { langExtension = langExtension[1]; }\n            }\n\n            var preformatted;\n            if (preformattedTagNameRe.test(cs.tagName)) {\n              preformatted = 1;\n            } else {\n              var currentStyle = cs['currentStyle'];\n              var defaultView = doc.defaultView;\n              var whitespace = (\n                  currentStyle\n                  ? currentStyle['whiteSpace']\n                  : (defaultView\n                     && defaultView.getComputedStyle)\n                  ? defaultView.getComputedStyle(cs, null)\n                  .getPropertyValue('white-space')\n                  : 0);\n              preformatted = whitespace\n                  && 'pre' === whitespace.substring(0, 3);\n            }\n\n            // Look for a class like linenums or linenums:<n> where <n> is the\n            // 1-indexed number of the first line.\n            var lineNums = attrs['linenums'];\n            if (!(lineNums = lineNums === 'true' || +lineNums)) {\n              lineNums = className.match(/\\blinenums\\b(?::(\\d+))?/);\n              lineNums =\n                lineNums\n                ? lineNums[1] && lineNums[1].length\n                  ? +lineNums[1] : true\n                : false;\n            }\n            if (lineNums) { numberLines(cs, lineNums, preformatted); }\n\n            // do the pretty printing\n            prettyPrintingJob = {\n              langExtension: langExtension,\n              sourceNode: cs,\n              numberLines: lineNums,\n              pre: preformatted\n            };\n            applyDecorator(prettyPrintingJob);\n          }\n        }\n      }\n      if (k < elements.length) {\n        // finish up in a continuation\n        setTimeout(doWork, 250);\n      } else if ('function' === typeof opt_whenDone) {\n        opt_whenDone();\n      }\n    }\n\n    doWork();\n  }\n\n  /**\n   * Contains functions for creating and registering new language handlers.\n   * @type {Object}\n   */\n  var PR = win['PR'] = {\n        'createSimpleLexer': createSimpleLexer,\n        'registerLangHandler': registerLangHandler,\n        'sourceDecorator': sourceDecorator,\n        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,\n        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,\n        'PR_COMMENT': PR_COMMENT,\n        'PR_DECLARATION': PR_DECLARATION,\n        'PR_KEYWORD': PR_KEYWORD,\n        'PR_LITERAL': PR_LITERAL,\n        'PR_NOCODE': PR_NOCODE,\n        'PR_PLAIN': PR_PLAIN,\n        'PR_PUNCTUATION': PR_PUNCTUATION,\n        'PR_SOURCE': PR_SOURCE,\n        'PR_STRING': PR_STRING,\n        'PR_TAG': PR_TAG,\n        'PR_TYPE': PR_TYPE,\n        'prettyPrintOne':\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrintOne'] = $prettyPrintOne)\n             : (prettyPrintOne = $prettyPrintOne),\n        'prettyPrint': prettyPrint =\n           IN_GLOBAL_SCOPE\n             ? (win['prettyPrint'] = $prettyPrint)\n             : (prettyPrint = $prettyPrint)\n      };\n\n  // Make PR available via the Asynchronous Module Definition (AMD) API.\n  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:\n  // The Asynchronous Module Definition (AMD) API specifies a\n  // mechanism for defining modules such that the module and its\n  // dependencies can be asynchronously loaded.\n  // ...\n  // To allow a clear indicator that a global define function (as\n  // needed for script src browser loading) conforms to the AMD API,\n  // any global define function SHOULD have a property called \"amd\"\n  // whose value is an object. This helps avoid conflict with any\n  // other existing JavaScript code that could have defined a define()\n  // function that does not conform to the AMD API.\n  if (typeof define === \"function\" && define['amd']) {\n    define(\"google-code-prettify\", [], function () {\n      return PR; \n    });\n  }\n})();\n\ndefine(\"prettify\", function(){});\n\n",
        +    "define('itemView',[\n  'App',\n  // Templates\n  'text!tpl/item.html',\n  'text!tpl/class.html',\n  'text!tpl/itemEnd.html',\n  // Tools\n  'prettify'\n], function(App, itemTpl, classTpl, endTpl) {\n  'use strict';\n\n  var appVersion = App.project.version || 'master';\n\n  var itemView = Backbone.View.extend({\n    el: '#item',\n    init: function() {\n      this.$html = $('html');\n      this.$body = $('body');\n      this.$scrollBody = $('html, body'); // hack for Chrome/Firefox scroll\n\n      this.tpl = _.template(itemTpl);\n      this.classTpl = _.template(classTpl);\n      this.endTpl = _.template(endTpl);\n\n      return this;\n    },\n    getSyntax: function(isMethod, cleanItem) {\n      var isConstructor = cleanItem.is_constructor;\n      var syntax = '';\n      if (isConstructor) {\n        syntax += 'new ';\n      } else if (cleanItem.static && cleanItem.class) {\n        syntax += cleanItem.class + '.';\n      }\n      syntax += cleanItem.name;\n\n      if (isMethod || isConstructor) {\n        syntax += '(';\n        if (cleanItem.params) {\n          for (var i = 0; i < cleanItem.params.length; i++) {\n            var p = cleanItem.params[i];\n            if (p.optional) {\n              syntax += '[';\n            }\n            syntax += p.name;\n            if (p.optdefault) {\n              syntax += '=' + p.optdefault;\n            }\n            if (p.optional) {\n              syntax += ']';\n            }\n            if (i !== cleanItem.params.length - 1) {\n              syntax += ', ';\n            }\n          }\n        }\n        syntax += ')';\n      }\n\n      return syntax;\n    },\n    // Return a list of valid syntaxes across all overloaded versions of\n    // this item.\n    //\n    // For reference, we ultimately want to replicate something like this:\n    //\n    // https://processing.org/reference/color_.html\n    getSyntaxes: function(isMethod, cleanItem) {\n      var overloads = cleanItem.overloads || [cleanItem];\n      return overloads.map(this.getSyntax.bind(this, isMethod));\n    },\n    render: function(item) {\n      if (item) {\n        var itemHtml = '';\n        var cleanItem = this.clean(item);\n        var isClass = item.hasOwnProperty('itemtype') ? 0 : 1;\n        var collectionName = isClass\n            ? 'Constructor'\n            : this.capitalizeFirst(cleanItem.itemtype),\n          isConstructor = cleanItem.is_constructor;\n        cleanItem.isMethod = collectionName === 'Method';\n\n        var syntaxes = this.getSyntaxes(cleanItem.isMethod, cleanItem);\n\n        // Set the item header (title)\n\n        // Set item contents\n        if (isClass) {\n          var constructor = this.tpl({\n            item: cleanItem,\n            isClass: true,\n            isConstructor: isConstructor,\n            syntaxes: syntaxes\n          });\n          cleanItem.constructor = constructor;\n\n          var contents = _.find(App.classes, function(c) {\n            return c.name === cleanItem.name;\n          });\n          cleanItem.things = contents.items;\n\n          itemHtml = this.classTpl(cleanItem);\n        } else {\n          cleanItem.constRefs =\n            item.module === 'Constants' && App.data.consts[item.name];\n\n          itemHtml = this.tpl({\n            item: cleanItem,\n            isClass: false,\n            isConstructor: false,\n            syntaxes: syntaxes\n          });\n        }\n\n        itemHtml += this.endTpl({ item: cleanItem, appVersion: appVersion });\n\n        // Insert the view in the dom\n        this.$el.html(itemHtml);\n\n        renderCode(cleanItem.name);\n\n        // Set the document title based on the item name.\n        // If it is a method, add parentheses to the name\n        if (item.itemtype === 'method') {\n          App.pageView.appendToDocumentTitle(item.name + '()');\n        } else {\n          App.pageView.appendToDocumentTitle(item.name);\n        }\n\n        // Hook up alt-text for examples\n        setTimeout(function() {\n          var alts = $('.example-content')[0];\n          if (alts) {\n            alts = $(alts)\n              .data('alt')\n              .split('\\n');\n\n            var canvases = $('.cnv_div');\n            for (var j = 0; j < alts.length; j++) {\n              if (j < canvases.length) {\n                $(canvases[j]).append(\n                  '<span class=\"sr-only\">' + alts[j] + '</span>'\n                );\n              }\n            }\n          }\n        }, 1000);\n        Prism.highlightAll();\n      }\n\n      var renderEvent = new Event('reference-rendered');\n      window.dispatchEvent(renderEvent);\n\n      return this;\n    },\n    /**\n     * Clean item properties: url encode properties containing paths.\n     * @param {object} item The item object.\n     * @returns {object} Returns the same item object with urlencoded paths.\n     */\n    clean: function(item) {\n      var cleanItem = item;\n\n      if (cleanItem.hasOwnProperty('file')) {\n        cleanItem.urlencodedfile = encodeURIComponent(item.file);\n      }\n      return cleanItem;\n    },\n    /**\n     * Show a single item.\n     * @param {object} item Item object.\n     * @returns {object} This view.\n     */\n    show: function(item) {\n      if (item) {\n        this.render(item);\n      }\n\n      App.pageView.hideContentViews();\n\n      this.$el.show();\n\n      this.scrollTop();\n      $('#item').focus();\n      return this;\n    },\n    /**\n     * Show a message if no item is found.\n     * @returns {object} This view.\n     */\n    nothingFound: function() {\n      this.$el.html(\n        '<p><br><br>Ouch. I am unable to find any item that match the current query.</p>'\n      );\n      App.pageView.hideContentViews();\n      this.$el.show();\n\n      return this;\n    },\n    /**\n     * Scroll to the top of the window with an animation.\n     */\n    scrollTop: function() {\n      // Hack for Chrome/Firefox scroll animation\n      // Chrome scrolls 'body', Firefox scrolls 'html'\n      var scroll = this.$body.scrollTop() > 0 || this.$html.scrollTop() > 0;\n      if (scroll) {\n        this.$scrollBody.animate({ scrollTop: 0 }, 600);\n      }\n    },\n    /**\n     * Helper method to capitalize the first letter of a string\n     * @param {string} str\n     * @returns {string} Returns the string.\n     */\n    capitalizeFirst: function(str) {\n      return str.substr(0, 1).toUpperCase() + str.substr(1);\n    }\n  });\n\n  return itemView;\n});\n\n",
        +    "\ndefine('text!tpl/menu.html',[],function () { return '<div>\\n  <br>\\n  <span id=\"reference-description1\">Can\\'t find what you\\'re looking for? You may want to check out</span>\\n  <a href=\"#/libraries/p5.sound\">p5.sound</a>.<br><a href=\\'https://p5js.org/offline-reference/p5-reference.zip\\' target=_blank><span id=\"reference-description3\">You can also download an offline version of the reference.</span></a>\\n</div>\\n\\n<div id=\\'collection-list-categories\\'>\\n<h2 class=\"sr-only\" id=\"categories\">Categories</h2>\\n<% var i=0; %>\\n<% var max=Math.floor(groups.length/4); %>\\n<% var rem=groups.length%4; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% var m = rem > 0 ? 1 : 0 %>\\n  <% if (i === 0) { %>\\n    <ul aria-labelledby=\"categories\">\\n    <% } %>\\n    <li><a href=\"#group-<%=group%>\"><%=group%></a></li>\\n    <% if (i === (max+m-1)) { %>\\n    </ul>\\n  \\t<% rem-- %>\\n  \\t<% i=0 %>\\n  <% } else { %>\\n  \\t<% i++ %>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        +    "define('menuView',[\n  'App',\n  'text!tpl/menu.html'\n], function(App, menuTpl) {\n\n  var menuView = Backbone.View.extend({\n    el: '#collection-list-nav',\n    /**\n     * Init.\n     * @returns {object} This view.\n     */\n    init: function() {\n      this.menuTpl = _.template(menuTpl);\n      return this;\n    },\n    /**\n     * Render.\n     * @returns {object} This view.\n     */\n    render: function() {\n\n      var groups = [];\n      _.each(App.modules, function (item, i) {\n        if (!item.is_submodule) {\n          if (!item.file || item.file.indexOf('addons') === -1) { //addons don't get displayed on main page\n            groups.push(item.name);\n          }\n        }\n        //}\n      });\n\n      // Sort groups by name A-Z\n      groups.sort();\n\n      var menuHtml = this.menuTpl({\n        'groups': groups\n      });\n\n      // Render the view\n      this.$el.html(menuHtml);\n    },\n\n    hide: function() {\n      this.$el.hide();\n    },\n\n    show: function() {\n      this.$el.show();\n    },\n\n    /**\n     * Update the menu.\n     * @param {string} el The name of the current route.\n     */\n    update: function(menuItem) {\n      //console.log(menuItem);\n      // this.$menuItems.removeClass('active');\n      // this.$menuItems.find('a[href=#'+menuItem+']').parent().addClass('active');\n\n    }\n  });\n\n  return menuView;\n\n});\n\n",
        +    "\ndefine('text!tpl/library.html',[],function () { return '<h3><%= module.name %> library</h3>\\n\\n<p><%= module.description %></p>\\n\\n<div id=\"library-page\" class=\"reference-group clearfix\">  \\n\\n<% var t = 0; col = 0; %>\\n\\n<% _.each(groups, function(group){ %>\\n  <% if (t == 0) { %> \\n    <div class=\"column_<%=col%>\">\\n  <% } %>\\n  <% if (group.name !== module.name && group.name !== \\'p5\\') { %>\\n    <% if (group.hash) { %> <a href=\"<%=group.hash%>\" <% if (group.module !== module.name) { %>class=\"core\"<% } %>><% } %>  \\n    <h4 class=\"group-name <% if (t == 0) { %> first<%}%>\"><%=group.name%></h4>\\n    <% if (group.hash) { %> </a><br> <% } %>\\n  <% } %>\\n  <% _.each(group.items.filter(function(item) {return item.access !== \\'private\\'}), function(item) { %>\\n    <a href=\"<%=item.hash%>\" <% if (item.module !== module.name) { %>class=\"core\"<% } %>><%=item.name%><% if (item.itemtype === \\'method\\') { %>()<%}%></a><br>\\n    <% t++; %>\\n  <% }); %>\\n  <% if (t >= Math.floor(totalItems/4)) { col++; t = 0; %>\\n    </div>\\n  <% } %>\\n<% }); %>\\n</div>\\n';});\n\n",
        +    "define(\n  'libraryView',[\n    'App',\n    // Templates\n    'text!tpl/library.html'\n  ],\n  function(App, libraryTpl) {\n    var libraryView = Backbone.View.extend({\n      el: '#list',\n      events: {},\n      /**\n       * Init.\n       */\n      init: function() {\n        this.libraryTpl = _.template(libraryTpl);\n\n        return this;\n      },\n      /**\n       * Render the list.\n       */\n      render: function(m, listCollection) {\n        if (m && listCollection) {\n          var self = this;\n\n          // Render items and group them by module\n          // module === group\n          this.groups = {};\n          _.each(m.items, function(item, i) {\n            var module = item.module || '_';\n            var group;\n            // Override default group with a selected category\n            // TODO: Overwriting with the first category might not be the best choice\n            // We might also want to have links for categories\n            if (item.category && item.category[0]) {\n              group = item.category[0];\n              // Populate item.hash\n              App.router.getHash(item);\n\n              // Create a group list without link hash\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: undefined,\n                  items: []\n                };\n              }\n            } else {\n              group = item.class || '_';\n              var hash = App.router.getHash(item);\n\n              var ind = hash.lastIndexOf('/');\n              hash = hash.substring(0, ind);\n\n              // Create a group list\n              if (!self.groups[group]) {\n                self.groups[group] = {\n                  name: group.replace('_', '&nbsp;'),\n                  module: module,\n                  hash: hash,\n                  items: []\n                };\n              }\n            }\n\n            self.groups[group].items.push(item);\n          });\n\n          // Sort groups by name A-Z\n          self.groups = _.sortBy(self.groups, this.sortByName);\n\n          // Put the <li> items html into the list <ul>\n          var libraryHtml = self.libraryTpl({\n            title: self.capitalizeFirst(listCollection),\n            module: m.module,\n            totalItems: m.items.length,\n            groups: self.groups\n          });\n\n          // Render the view\n          this.$el.html(libraryHtml);\n        }\n\n        return this;\n      },\n      /**\n       * Show a list of items.\n       * @param {array} items Array of item objects.\n       * @returns {object} This view.\n       */\n      show: function(listGroup) {\n        if (App[listGroup]) {\n          this.render(App[listGroup], listGroup);\n        }\n        App.pageView.hideContentViews();\n\n        this.$el.show();\n\n        return this;\n      },\n      /**\n       * Helper method to capitalize the first letter of a string\n       * @param {string} str\n       * @returns {string} Returns the string.\n       */\n      capitalizeFirst: function(str) {\n        return str.substr(0, 1).toUpperCase() + str.substr(1);\n      },\n      /**\n       * Sort function (for the Array.prototype.sort() native method): from A to Z.\n       * @param {string} a\n       * @param {string} b\n       * @returns {Array} Returns an array with elements sorted from A to Z.\n       */\n      sortAZ: function(a, b) {\n        return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;\n      },\n\n      sortByName: function(a, b) {\n        if (a.name === 'p5') return -1;\n        else return 0;\n      }\n    });\n\n    return libraryView;\n  }\n);\n\n",
        +    "define('pageView',[\n  'App',\n\n  // Views\n  'searchView',\n  'listView',\n  'itemView',\n  'menuView',\n  'libraryView'\n], function(App, searchView, listView, itemView, menuView, libraryView) {\n\n  // Store the original title parts so we can substitue different endings.\n  var _originalDocumentTitle = window.document.title;\n\n  var pageView = Backbone.View.extend({\n    el: 'body',\n    /**\n     * Init.\n     */\n    init: function() {\n      App.$container = $('#container');\n      App.contentViews = [];\n\n      return this;\n    },\n    /**\n     * Render.\n     */\n    render: function() {\n\n      // Menu view\n      if (!App.menuView) {\n        App.menuView = new menuView();\n        App.menuView.init().render();\n      }\n\n      // Item view\n      if (!App.itemView) {\n        App.itemView = new itemView();\n        App.itemView.init().render();\n        // Add the item view to the views array\n        App.contentViews.push(App.itemView);\n      }\n\n      // List view\n      if (!App.listView) {\n        App.listView = new listView();\n        App.listView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.listView);\n      }\n\n      // Library view\n      if (!App.libraryView) {\n        App.libraryView = new libraryView();\n        App.libraryView.init().render();\n        // Add the list view to the views array\n        App.contentViews.push(App.libraryView);\n      }\n\n      // Search\n      if (!App.searchView) {\n        App.searchView = new searchView();\n        App.searchView.init().render();\n      }\n      return this;\n    },\n    /**\n     * Hide item and list views.\n     * @returns {object} This view.\n     */\n    hideContentViews: function() {\n      _.each(App.contentViews, function(view, i) {\n        view.$el.hide();\n      });\n\n      return this;\n    },\n    /**\n     * Append the supplied name to the first part of original document title.\n     * If no name is supplied, the title will reset to the original one.\n     */\n    appendToDocumentTitle: function(name){\n      if(name){\n        let firstTitlePart = _originalDocumentTitle.split(\" | \")[0];\n        window.document.title = [firstTitlePart, name].join(\" | \");\n      } else {\n        window.document.title = _originalDocumentTitle;\n      }\n    }    \n  });\n\n  return pageView;\n\n});\n\n",
        +    "define('router',[\n  'App'\n], function(App) {\n\n  'use strict'; //\n\n  var Router = Backbone.Router.extend({\n\n    routes: {\n      '': 'list',\n      'p5': 'list',\n      'p5/': 'list',\n      'classes': 'list',\n      'search': 'search',\n      'libraries/:lib': 'library',\n      ':searchClass(/:searchItem)': 'get'\n    },\n    /**\n     * Whether the json API data was loaded.\n     */\n    _initialized: false,\n    /**\n     * Initialize the app: load json API data and create searchable arrays.\n     */\n    init: function(callback) {\n      var self = this;\n      require(['pageView'], function(pageView) {\n\n        // If already initialized, move away from here!\n        if (self._initialized) {\n          if (callback)\n            callback();\n          return;\n        }\n\n        // Update initialization state: must be done now to avoid recursive mess\n        self._initialized = true;\n\n        // Render views\n        if (!App.pageView) {\n          App.pageView = new pageView();\n          App.pageView.init().render();\n        }\n\n        // If a callback is set (a route has already been called), run it\n        // otherwise, show the default list\n        if (callback)\n          callback();\n        else\n          self.list();\n      });\n    },\n    /**\n     * Start route. Simply check if initialized.\n     */\n    start: function() {\n      this.init();\n    },\n    /**\n     * Show item details by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     */\n    get: function(searchClass, searchItem) {\n\n      // if looking for a library page, redirect\n      if (searchClass === 'p5.sound' && !searchItem) {\n        window.location.hash = '/libraries/'+searchClass;\n        return;\n      }\n\n      var self = this;\n      this.init(function() {\n        var item = self.getItem(searchClass, searchItem);\n\n        App.menuView.hide();\n\n        if (item) {\n          App.itemView.show(item);\n        } else {\n          //App.itemView.nothingFound();\n\n          self.list();\n        }\n\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Returns one item object by searching a class or a class item (method, property or event).\n     * @param {string} searchClass The class name (mandatory).\n     * @param {string} searchItem The class item name: can be a method, property or event name.\n     * @returns {object} The item found or undefined if nothing was found.\n     */\n    getItem: function(searchClass, searchItem) {\n      var classes = App.classes,\n              items = App.allItems,\n              classesCount = classes.length,\n              itemsCount = items.length,\n              className = searchClass ? searchClass.toLowerCase() : undefined,\n              itemName = searchItem ? searchItem : undefined,\n              found;\n\n      // Only search for a class, if itemName is undefined\n      if (className && !itemName) {\n        for (var i = 0; i < classesCount; i++) {\n          if (classes[i].name.toLowerCase() === className) {\n            found = classes[i];\n            _.each(found.items, function(i, idx) {\n              i.hash = App.router.getHash(i);\n            });\n            break;\n          }\n        }\n        // Search for a class item\n      } else if (className && itemName) {\n        // Search case sensitively\n        for (var i = 0; i < itemsCount; i++) {\n          if (items[i].class.toLowerCase() === className &&\n            items[i].name === itemName) {\n            found = items[i];\n            break;\n          }\n        }\n\n        // If no match was found, fallback to search case insensitively\n        if(!found){\n          for (var i = 0; i < itemsCount; i++) {\n            if(items[i].class.toLowerCase() === className &&\n              items[i].name.toLowerCase() === itemName.toLowerCase()){\n              found = items[i];\n              break;\n            }\n          }\n        }\n      }\n\n      return found;\n    },\n    /**\n     * List items.\n     * @param {string} collection The name of the collection to list.\n     */\n    list: function(collection) {\n\n      collection = 'allItems';\n\n      // Make sure collection is valid\n      if (App.collections.indexOf(collection) < 0) {\n        return;\n      }\n\n      this.init(function() {\n        App.menuView.show(collection);\n        App.menuView.update(collection);\n        App.listView.show(collection);\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Display information for a library.\n     * @param {string} collection The name of the collection to list.\n     */\n    library: function(collection) {\n      this.init(function() {\n        App.menuView.hide();\n        App.libraryView.show(collection.substring(3)); //remove p5.\n        styleCodeLinks();\n      });\n    },\n    /**\n     * Close all content views.\n     */\n    search: function() {\n      this.init(function() {\n        App.menuView.hide();\n        App.pageView.hideContentViews();\n      });\n    },\n\n    /**\n     * Create an hash/url for the item.\n     * @param {Object} item A class, method, property or event object.\n     * @returns {String} The hash string, including the '#'.\n     */\n     getHash: function(item) {\n\n       if (!item.hash) {\n\n         // FIX TO INVISIBLE OBJECTS: DH (see also listView.js)\n\n         if (item.class) {\n           var clsFunc = '#/' + item.class + '.' + item.name;\n           var idx = clsFunc.lastIndexOf('.');\n           item.hash = clsFunc.substring(0,idx) + '/' + clsFunc.substring(idx+1);\n         } else {\n          item.hash = '#/' + item.name;\n         }\n       }\n\n       return item.hash;\n    }\n  });\n\n  \n  function styleCodeLinks() {\n    var links = document.getElementsByTagName(\"a\");\n    for (var iLink = 0; iLink < links.length; iLink++) {\n      var link = links[iLink];\n      if (link.hash.startsWith('#/p5')) {\n        link.classList.add('code');\n      }\n    }\n  }\n\n\n  // Get the router\n  App.router = new Router();\n\n  // Start history\n  Backbone.history.start();\n\n  return App.router;\n\n});\n\n",
        +    "/**\n * Define global App.\n */\nvar App = window.App || {};\ndefine('App', [],function() {\n  return App;\n});\n\n/**\n * Load json API data and start the router.\n * @param {module} App\n * @param {module} router\n */\nrequire([\n  'App',\n  './documented-method'], function(App, DocumentedMethod) {\n\n  // Set collections\n  App.collections = ['allItems', 'classes', 'events', 'methods', 'properties', 'p5.sound'];\n\n  // Get json API data\n  $.getJSON('data.min.json', function(data) {\n    App.data = data;\n    App.classes = [];\n    App.methods = [];\n    App.properties = [];\n    App.events = [];\n    App.allItems = [];\n    App.sound = { items: [] };\n    App.dom = { items: [] };\n    App.modules = [];\n    App.project = data.project;\n\n\n    var modules = data.modules;\n\n    // Get class items (methods, properties, events)\n    _.each(modules, function(m, idx, array) {\n      App.modules.push(m);\n      if (m.name == \"p5.sound\") {\n        App.sound.module = m;\n      }\n    });\n\n\n    var items = data.classitems;\n    var classes = data.classes;\n\n    // Get classes\n    _.each(classes, function(c, idx, array) {\n      if (!c.private) {\n        App.classes.push(c);\n      }\n    });\n\n\n    // Get class items (methods, properties, events)\n    _.each(items, function(el, idx, array) {\n      if (el.itemtype) {\n        if (el.itemtype === \"method\") {\n          el = new DocumentedMethod(el);\n          App.methods.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"property\") {\n          App.properties.push(el);\n          App.allItems.push(el);\n        } else if (el.itemtype === \"event\") {\n          App.events.push(el);\n          App.allItems.push(el);\n        }\n\n        // libraries\n        if (el.module === \"p5.sound\") {\n          App.sound.items.push(el);\n        }\n      }\n    });\n\n    _.each(App.classes, function(c, idx) {\n      c.items = _.filter(App.allItems, function(it){ return it.class === c.name; });\n    });\n\n    require(['router']);\n  });\n});\n\ndefine(\"main\", function(){});\n\n",
             "}());"
           ]
         }
        \ No newline at end of file
        
        From 3846928b35f7580736f84a20db05f82194724196 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Wed, 13 May 2020 17:19:52 +0900
        Subject: [PATCH 17/36] minor changes on ko.yml
        
        ---
         src/data/ko.yml | 40 ++++++++++++++++++++--------------------
         1 file changed, 20 insertions(+), 20 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 762cb0b6ca..902706f305 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -36,9 +36,9 @@ home:
           p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 오브젝트를 사용할 수 있습니다."
           p2xh2: "커뮤니티"
           p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        -  p2x2: "p5.js는 "
        -  p2x3: " (프로세싱)을 오늘날의 웹에 맞게 해석한 버전이라 볼 수 있습니다. p5의 행사와 모임은 "
        -  p2x4: " (프로세싱 재단)의 지원을 받아 개최됩니다."
        +  p2x2: "p5.js는 프로세싱 "
        +  p2x3: "을 오늘날의 웹에 맞게 해석한 버전이라 볼 수 있습니다. p5의 행사와 모임은 프로세싱 재단 "
        +  p2x4: "의 지원을 받아 개최됩니다."
           p2x5: ""
           p2x6: "커뮤니티"
           p2x7: "에 대해 더 알아보세요."
        @@ -185,15 +185,15 @@ download:
           support-14: ", 그리고 "
           support-15: "커뮤니티 행사"
           support-16: "를 지원하는 데에 사용됩니다. 여러분의 도움이 필요합니다!"
        -  support-17: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-17: "미국 피츠버그 CMU STUDIO for Creative Inquiry에서 진행된 p5.js 공헌자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
           support-18: "프로세싱 재단 펠로우 Saskia Freeke이 런던에서 주관한 Liberation x Processing workshops (이미지 저작권: Code Liberation Foundation)"
           support-19: "SPFC와 함께한 Learning to Teach, Teaching to Learn 컨퍼런스 (이미지 저작권: Kira Simon-Kennedy)"
           support-20: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
           support-21: "Signing Coders p5.js workshop에서의 최태윤(Taeyoon Choi)과 미국 수어(ASL) 해설자 (이미지 저작권: 최태윤 Taeyoon Choi)"
           support-22: "구글 썸머 오브 코드(Google Summer of Code) 킥오프 행사 (이미지 저작권: 최태윤 Taeyoon Choi)"
           support-23: "프로세싱 재단 펠로우 Cassie Tarakajian가 Code Art Miami에서 진행한 워크숍 (이미지 저작권: Christian Arévalo Photography)"
        -  support-24: "최태윤의 수어 기반 p5.js workshop에서 진행을 돕는 Luisa Pereira와 송예슬Yeseul Song (이미지 저작권: 최태윤 Taeyoon Choi)"
        -  support-25: "미국 피츠버그(Pittsburgh) CMU STUDIO for Creative Inquiry에서 진행된 p5.js 기여자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-24: "최태윤의 수어 기반 p5.js workshop에서 진행을 돕는 Luisa Pereira와 송예슬 Yeseul Song (이미지 저작권: 최태윤 Taeyoon Choi)"
        +  support-25: "미국 피츠버그 CMU STUDIO for Creative Inquiry에서 진행된 p5.js 공헌자 컨퍼런스 (이미지 저작권: 최태윤 Taeyoon Choi)"
           support-26: "프로세싱 재단 펠로우 Digital Citizens Lab가 International Center of Photography에서 주최한 STEM teaching 패널 (이미지 저작권: International Center of Photography)"
           support-27: "칠레 산티아고에서 Aarón Montoya-Moraga가 진행한 p5.js workshop (이미지 저작권: Aarón Montoya-Moraga.)"
           support-28: "Claire Kearney-Volpe helping facilitate a sign language based p5.js workshop led by Taeyoon Choi (Image credit: Taeyoon Choi)"
        @@ -274,7 +274,7 @@ learn:
           writing-tutorial: "프로그래밍 튜토리얼 제작 가이드."
           writing-a-tutorial-title: "p5.js 튜토리얼 기여를 위한 가이드"
           writing-a-tutorial-author: "이 튜토리얼은 테가 브레인(Tega Brain)이 제작하였습니다."
        -  writing-a-tutorial-1: "p5.js 튜토리얼 기여는 이에 열정을 느끼는 교육자와 모든분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 기여 방법 등에 대한 내용을 다룹니다."
        +  writing-a-tutorial-1: "p5.js 튜토리얼 기여는 이에 열정을 느끼는 교육자와 모든분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 공헌 방법 등에 대한 내용을 다룹니다."
           writing-a-tutorial-2: "새로운 튜토리얼을 제안하거나, 튜토리얼 준비 및 기여에 대한 가이드라인 제작을 환영합니다."
           writing-a-tutorial-how-start-title: "커뮤니티 기여 시작하기:"
           writing-a-tutorial-how-start-1: "우선, 제안하려는 튜토리얼이 현재 진행 중인 내용들과 겹치는 지의 여부를 이 "
        @@ -443,7 +443,7 @@ libraries:
           p5.3D: "WebGL로 3D 텍스트 및 이미지를 쓸 수 있습니다. "
           using-a-library-title: "라이브러리 이용하기"
           using-a-library1: "라이브러리란 p5.js의 핵심 기능을 확장하거나 추가하는 자바스크립트 코드를 말합니다. 라이브러리에는 크게 두 종류가 있습니다. 주요 라이브러리인 "
        -  using-a-library3: "의 경우 p5.js 자체 배포물인 반면, 커뮤니티 라이브러리는 커뮤니티 기여자에 의해 개발, 소유, 유지됩니다."
        +  using-a-library3: "의 경우 p5.js 자체 배포물인 반면, 커뮤니티 라이브러리는 커뮤니티 공헌자에 의해 개발, 소유, 유지됩니다."
           using-a-library4: "스케치에 라이브러리를 사용하려면 우선 스케치에 p5.js 링크를 걸고, 그 다음 HTML 파일에 라이브러리 링크를 걸면 됩니다. 링크가 걸린 HTML 파일은 이렇게 보입니다:"
           create-your-own-title: "나만의 라이브러리 만들기"
           create-your-own1: "p5.js는 여러분만의 라이브러리 제작을 환영합니다! 라이브러리 제작에 대해 더 알고 싶다면 "
        @@ -461,7 +461,7 @@ community:
           in-practice1: "우리는 잘난체하는 개발자들이 아닙니다. 우리는 상대가 이미 어떠한 것을 알고 있을거라 섣불리 가정하거나, 모든 사람이 반드시 알아야 할 지식이 있다고 생각하지 않습니다. "
           in-practice2: "피드백이 필요한 경우, 언제든 적극적으로 응합니다."
           in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 초심자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
        -  in-practice4: "우리는 언제나 모든 형태의 기여와 참여를 적극적으로 인정하고 인증하고자 합니다."
        +  in-practice4: "우리는 언제나 모든 형태의 기여, 공헌, 참여를 적극적으로 인정하고 인증하고자 합니다."
           in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다."
           in-times-conflict-title: "갈등이 발생할 경우:"
           in-times-conflict1: "서로의 생각에 귀 기울입니다. "
        @@ -506,12 +506,12 @@ community:
           donate1: " p5.js는 예술가들이 만든 무료 오픈 소스입니다. "
           donate2: "프로세싱 재단"
           donate3: " 기부를 통해 p5.js를 후원해주세요!"
        -  contributors-conference-title: "p5.js 기여자 컨퍼런스"
        -  contributors-conference1: "대부분의 커뮤니티 활동은 온라인에서 진행되지만, 오프라인에서도 일어난답니다! 그동안 두 차례의 기여자 컨퍼런스가 있었는데요, 미국 피츠버그(Pittsburgh) 소재 카네기 멜론 대학교(Carnegie Mellon University)의 "
        +  contributors-conference-title: "p5.js 공헌자 컨퍼런스"
        +  contributors-conference1: "대부분의 커뮤니티 활동은 온라인에서 진행되지만, 오프라인에서도 일어난답니다! 그동안 두 차례의 공헌자 컨퍼런스가 있었는데요, 미국 피츠버그 소재 카네기 멜론 대학교(Carnegie Mellon University)의 "
           contributors-conference2: "에서 진행된 것이 그 중 하나입니다. 예술가, 디자이너, 개발자, 교육자들이 모여 p5.js의 개선 방향에 대해 논의하였습니다."
           participants-title: "참여자"
           support-title: "지원"
        -  support1: "기여자 컨퍼러스는 카네기 멜론 대학교의"
        +  support1: "공헌자 컨퍼러스는 카네기 멜론 대학교의"
           support2: "에서 열렸습니다. 이 곳은 예술, 과학, 기술, 그리고 문화의 교차점에서, 비정형적, 반-학제적 및 간-기관적 연구를 진행하는 학술랩입니다."
           support3: "이 행사는 "
           support4: "의 기금과 "
        @@ -520,7 +520,7 @@ community:
           mailing-list-title: "소식지 받기"
           mailing-list-1: "프로세싱 재단의 정기 소식을 수신하려면 이메일 주소를 입력하세요."
         
        -  2015contributors-conference-title: "2015년 기여자 컨퍼런스"
        +  2015contributors-conference-title: "2015년 공헌자 컨퍼런스"
           2015contributors-conference-date: "5월 25-31일"
           2015contributors-conference1: "약 30여명의 참여자들이 "
           2015contributors-conference2: "에 모여, p5.js의 프로그래밍 코드와 문서화 작업을 진전시키고, 커뮤니티를 확장하는 방안에 대해 논의하였습니다. 멀리서는 홍콩, 그리고 시애틀, 로스 엔젤레스, 보스턴, 뉴욕 등지에서 찾아온 참여자들이 함께하였습니다. 대부분의 참여자들이 크리에이티브 기술, 인터랙션 디자인, 그리고 뉴미디어 아트 분야의 전문 종사자였고, 카네기 멜론 미술 및 건축 대학교 출신의 학부생 및 대학원생도 6명 정도 포함하였습니다."
        @@ -550,7 +550,7 @@ community:
           2015cc_13: "둥그렇게 앉아 토론하는 5명의 사람들"
           2015cc_14: "노트북과 함께 둥그렇게 앉아 자신의 필기를 공유하는 5명의 사람들"
           2015cc_15: "교실에서 참여자들을 향해 마이크로 발표하는 남성"
        -  2019contributors-conference-title: "2019년 기여자 컨퍼런스"
        +  2019contributors-conference-title: "2019년 공헌자 컨퍼런스"
           2019contributors-conference-date: "8월 13-18일"
           2019contributors-conference1: "다학제적 배경을 지닌 35명의 참여자들이 "
           2019contributors-conference2: "에 모여 p5.js의 프로그래밍 환경과 그 현주소를 탐색하고, 코드 및 문서 개발, 그리고 커뮤니티 확장 방법에 대해 논의하였습니다. 참여자들은 크리에이티브 기술, 인터랙션 디자인, 뉴미디어 아트를 아우르는 다양한 분야의 종사자들로 구성되었으며, 컨퍼런스에서의 논의는 이러한 다학제적인 시각을 바탕으로 진행되었습니다. 참여자 그룹은 접근성, 퍼포먼스 속 음악과 코딩, 크리에이티브 기술 지형, 그리고 국제화를 포함한 여러 주제에 초점을 두었습니다." 
        @@ -567,7 +567,7 @@ community:
           output6-1: "p5.js를 위한 노트북 인터페이스"
           output6-2: "의 프로토타입. 제작: 앨리슨 패리쉬(Allison Parrish)"
           output7: "새로운 설치 예술 작품. 제작: Stalgia Grigg, LaJuné McMillian, Aatish Bhatia, 그리고 Jon Chambers."
        -  output8: "p5.js의 전세계 기여자를 위한 툴킷"
        +  output8: "p5.js의 전세계 공헌자를 위한 툴킷"
           output8-1: "제작: Aarón Montoya-Moraga, Kenneth Lim, Guillermo Montecinos, Qianqian Ye, Dorothy R. Santos, 그리고 Yasheng She."
           output9: "비폭력적 크리이에티브 코드 작성법. "
           output9-1: "올리비아 로스(Olivia Ross) 진행 잡지."
        @@ -610,7 +610,7 @@ books:
           book-1-publisher: "2015년 10월 Maker Media 출판. "
           book-1-pages: "246 페이지. "
           book-1-type: "페이퍼백."
        -  book-1-description: "p5.js의 리드 개발자와 프로세싱(Processing)의 창립자들이 저술한 이 책은, 자바스크립트(JavaScript)와 HTML을 통해 오늘날 웹아 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
        +  book-1-description: "p5.js의 리드 개발자와 프로세싱의 창립자들이 저술한 이 책은, 자바스크립트와 HTML을 통해 오늘날 웹아 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
           book-1-order-a: "O'Reilly에서 인쇄물/e북 주문하기"
           book-1-order-b: "아마존에서 주문하기"
           book-2-title: "Introduction to p5.js (스페인어 에디션)"
        @@ -618,7 +618,7 @@ books:
           book-2-publisher: "2018년 Processing Foundation, Inc. 출판. "
           book-2-pages: "246 페이지. "
           book-2-type: "소프트커버."
        -  book-2-description: "p5.js의 리드 개발자와 프로세싱(Processing)의 창립자들이 저술한 이 책은, 자바스크립트(JavaScript)와 HTML을 통해 오늘날 웹이 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
        +  book-2-description: "p5.js의 리드 개발자와 프로세싱의 창립자들이 저술한 이 책은, 자바스크립트와 HTML을 통해 오늘날 웹이 보다 창의적으로 사용될 수 있는 가능성을 소개합니다."
           book-2-order-a: "Processing Foundation Press에서 PDF 주문하기"
           book-2-order-b: "아마존에서 인쇄물 주문하기"
           book-3-title: "Generative Design(제너레이티브 디자인)"
        @@ -626,7 +626,7 @@ books:
           book-3-publisher: "2018년 10월 30일 Princeton Architectural Press 출판; 별쇄본. "
           book-3-pages: "255 페이지. "
           book-3-type: "페이퍼백."
        -  book-3-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
        +  book-3-description: "p5.js의 자바스크립트와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
           book-3-order-a: "Princeton Architectural Press에서 주문하기"
           book-3-order-b: "아마존에서 주문하기"
           book-4-title: "Generative Gestaltung (제너레이티브 디자인 독일어 에디션)"
        @@ -634,7 +634,7 @@ books:
           book-4-publisher: "2018년 1월 Schmidt Hermann Verlag 출판. "
           book-4-pages: "256 페이지."
           book-4-type: "하드커버."
        -  book-4-description: "p5.js의 자바스크립트(JavaScript)와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
        +  book-4-description: "p5.js의 자바스크립트와 같은 간단한 언어를 통해, 예술가들과 창작자들은 인터랙티브 타이포그래피와 섬유로부터, 3D 프린팅 가구, 그리고 복잡하고 우아한 인포그래픽 등에 이르는 모든 것을 만들 수 있습니다."
           book-4-order-a: "Verlag Hermann Schmidt에서 주문하기"
           book-4-order-b: "아마존에서 주문하기"
           book-5-title: "Learn JavaScript with p5.js <br> (p5.js로 자바스크립트 배우기)"
        @@ -642,7 +642,7 @@ books:
           book-5-publisher: "2018년 Apress 출판. "
           book-5-pages: "217 페이지."
           book-5-type: "페이퍼백."
        -  book-5-description: "널리 사용되는 자바스크립트(JavaScript)와 그 프로그래밍 라이브러리인 p5.js을 통해 아주 매력적이고 시각적인 방식으로 코딩에 입문하세요. 이 책에서 습득할 수 있는 기술은 수많은 산업계에서도 호환되는 것이며, 웹 어플리케이션, 로봇 프로그래밍, 제너레이티브 아트를 제작하는 데에도 쓰입니다."
        +  book-5-description: "널리 사용되는 자바스크립트와 그 프로그래밍 라이브러리인 p5.js을 통해 아주 매력적이고 시각적인 방식으로 코딩에 입문하세요. 이 책에서 습득할 수 있는 기술은 수많은 산업계에서도 호환되는 것이며, 웹 어플리케이션, 로봇 프로그래밍, 제너레이티브 아트를 제작하는 데에도 쓰입니다."
           book-5-order-a: "Apress에서 주문하기"
           book-5-order-b: "아마존에서 주문하기"
         
        
        From 885eb47d005a0a15a0a180564f23ff4cdce999d8 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 16 May 2020 11:16:52 +0900
        Subject: [PATCH 18/36] updating reference for korean translation
        
        ---
         src/data/reference/ko.json | 1595 +++++++++++++++++++++++++++++++++++-
         1 file changed, 1566 insertions(+), 29 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index f6e9e1ca95..4f10b73a86 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -18,7 +18,6 @@
           "reference-description1": "찾는 항목이 없다면, 다음의 페이지를 살펴보세요:",
           "reference-description2": " 또는 ",
           "reference-description3": "오프라인 버전의 레퍼런스는 다음 링크에서 다운받을 수 있습니다: ",
        -  "reference-description4": "레퍼런스 다운로드",
           "reference-contribute1": "잘못된 부분이나 제안사항이 있다면",
           "reference-contribute2": "언제든 알려주세요",
           "reference-error1": "오타나 버그를 발견했다면",
        @@ -31,7 +30,7 @@
           "reference-extends": "확장",
           "reference-parameters": "변수",
           "reference-syntax": "문법",
        -  "reference-returns": "반환(return)",
        +  "reference-returns": "반환",
           "footer1": "p5.js는 ",
           "footer2": "가 창안하고 협력자 커뮤니티와 함께 개발되었습니다. 지원: 프로세싱 재단 ",
           "footer3": " 과 ",
        @@ -49,9 +48,9 @@
           "Creating & Reading": "만들기 & 읽기", 
           "Setting": "설정하기", 
           "2D Primitives": "2D 기본 조형", 
        -  "Attributes": "Attributes",  
        -  "Curves": "곡선 Curves", 
        -  "Vertex": "버텍스 Vertex", 
        +  "Attributes": "설정 요소",  
        +  "Curves": "곡선", 
        +  "Vertex": "버텍스", 
           "3D Models": "3D 모델",  
           "3D Primitives": "3D 기본 조형", 
           "Constants": "상수",  
        @@ -61,12 +60,12 @@
           "Rendering": "렌더링",  
           "Transform": "변형", 
           "Data": "데이터",  
        -  "Dictionary": "사전(Dictionary)",  
        +  "Dictionary": "사전",  
           "Array Functions": "배열 기능",  
        -  "Conversion": "변환(Conversion)", 
        +  "Conversion": "변환", 
           "String Functions": "문자열 기능",  
           "Events": "이벤트",  
        -  "Acceleration": "가속",  
        +  "Acceleration": "가속도",  
           "Keyboard": "키보드",  
           "Mouse": "마우스", 
           "Touch": "터치", 
        @@ -85,11 +84,69 @@
           "Trigonometry": "삼각법",  
           "Typography": "타이포그래피", 
           "Font": "폰트", 
        -  "Lights, Camera": "라이트, 카메라",  
        +  "Lights, Camera": "조명, 카메라",  
           "Camera": "카메라",  
        -  "Lights": "라이트"",  
        -  "Material": "재질(Material)",
        +  "Lights": "조명",  
        +  "Material": "재질(Material)", 
           "p5": {
        +   "alpha": {
        +      "description": "픽셀 배열로부터 알파값을 추출합니다.",
        +      "params": ["p5.Color | 숫자[] | 문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        +      "returns": "알파값"
        +    },
        +    "blue": {
        +      "description": "색상 또는 픽셀 배열로부터 파랑색값 추출합니다.",
        +      "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        +      "returns": "파랑색값"
        +    },
        +    "brightness": {
        +      "description": "색상 또는 픽셀 배열로부터 HSB 밝기값 추출합니다.",
        +      "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        +      "returns": "밝기값"
        +    },
        +    "color": {
        +      "description": "색상 함수를 이용해 색상 데이터의 매개변수를 저장해보세요. 이 때, 매개변수는 colorMode()의 설정에 따라 RGB 또는 HSB 값으로 처리됩니다. 기본 모드인 RGB값은 0부터 255까지이며, 따라서 color(255,204,0)와 같은 함수는 밝은 노랑색을 반환하게 됩니다. <br><br>         만약에 color() 함수에 매개변수가 1개만 적히면, 회색 음영(grayscale)값으로 처리됩니다. 여기에 추가되는 두번째 변수는 투명도를 설정할 수 있는 알파값으로서 처리됩니다. 세번째 변수가 추가되었을 때 비로소 RGB나 HSB값으로 처리되지요. RGB나 HSB값을 정하는 3개의 변수가 존재할 때 추가되는 네번째 변수는 알파값으로 적용됩니다. <br><br> 나아가, p5는 RGB, RGBA, Hex CSS 색상 문자열과 모든 색상명 문자열 역시 지원합니다. 그 경우, 알파값은 괄호 내 2번째 매개변수 추가를 통해서가 아닌, RGBA 형식에 따라 지정될 수 있습니다.",
        +      "params": ["숫자: 흑과 백 사이의 값 지정",
        +      "숫자: 현재 색상 범위(기본값: 0-255)에 대한 알파값)",
        +      "숫자: 현재 색상 범위 내 빨강색(R) 또는 색조값 지정",
        +      "숫자: 현재 색상 범위 내 파랑색(B) 또는 색조값 지정",
        +      "문자열: 색상 문자열",
        +      "숫자[]: RGB 및 알파값을 포함한 숫자열"],
        +      "returns": "색상 결과"
        +    },
        +
        +    "green": {
        +      "description": "색상 또는 픽셀 배열로부터 초록색값 추출합니다.",
        +      "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        +      "returns": "초록색값"
        +    },
        +    "hue": {
        +      "description": "색상 또는 픽셀 배열로부터 색조를 추출합니다. 색조는 HSB와 HSL상 모두 존재합니다. 이 함수는 HSB 색상 객체를 사용할 경우(또는 HSB 색상 모드로 지정된 픽셀 배열을 사용할 경우) HSB로 표준화된 색조 값을 반환합니다. 기본값으로는 HSL로 표준화된 색조를 반환합니다. (단, 최대 색조가 별도로 지정되어있을 경우 다른 값을 반환합니다.)",
        +      "params": ["p5.COlor 객체, 색상 요소 또는 CSS 색상"],
        +      "returns": "색조"
        +    },
        +    "lerpColor": {
        +      "description": "두 가지 색상을 혼합하고, 그 사이에 존재하는 제 3의 색상을 찾습니다. amt 매개변수는 선형보간하는 Mezcla dos colores para encontrar un tercer color según la combinación de ambos. El parámetro amt es la cantidad a interpolar entre los dos valores, donde 0.0 es igual al primer color, 0.1 es muy cercano al primer color, 0.5 está a medio camino entre ambos, etc. Un valor menor que 0 será tratado como 0. Del mismo modo, valores sobre 1 serán tratados como 1. Esto es distinto al comportamiento de lerp(), pero necesario porque de otra manera los números fuera de rango producirían colores no esperados y extraños. La manera en que los colores son interpolados depende del modo de color actual.",
        +      "params": ["Arreglo/Número: interpola desde este color",
        +      "Arreglo/Número: interpola hacia este color",
        +      "Número: número entre 0 y 1"],
        +      "returns": "Arreglo/Número: color interpolado"
        +    },
        +    "lightness": {
        +      "description": "Extrae el valor de luminosidad HSL de un color o de un arreglo de pixeles.",
        +      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        +      "returns": "el objeto p5"
        +    },
        +    "red": {
        +      "description": "Extrae el valor de rojo de un color o de un arreglo de pixeles.",
        +      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        +      "returns": "el objeto p5"
        +    },
        +    "saturation": {
        +      "description": "Extrae el valor de saturación de un color o de un arreglo de pixeles. La saturación es escalada en HSB y HSL de forma distinta. Esta función retornará la saturación HSB cuando le sea provisto un objeto de color HSB (o cuando le sea provisto un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará saturación HSL.",
        +      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        +      "returns": "el objeto p5"
        +    },
             "background": {
               "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 일회적으로 설정할 경우 setup() 함수 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.",
               "params": ["p5.Color: color() 함수를 통해 만들어진 값",
        @@ -169,13 +226,7 @@
               "정수: 원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WEGBL 모드용)"],
               "returns": "the p5 object"
             },
        -    "circle": {
        -      "description": "화면에 원을 그립니다. 원은 단순한 단일폐곡선으로, 중심점으로부터 같은 좌표에 위치한 점들의 집합입니다. 원은 너비와 높이가 동일한 타원으로 ellipse() 함수를 이용해 그리는 것도 가능합니다. 이 경우 타원의 너비와 높이는 원의 지름과 동일합니다. 본 함수의 첫번째 두번째 변수는 원의 중심점을, 세번째 변수는 지름을 설정합니다.",
        -      "params": ["숫자: 원 중심점의 x 좌표",
        -      "숫자: 원 중심점의 y 좌표",
        -      "숫자: 원의 지름"],
        -      "returns": "the p5 object"
        -    },
        +
             "line": {
               "description": "화면에 선, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하는 경우 이차원 평면에 선을 그립니다. 선의 색을 지정하려면 stroke() 함수를 이용하세요. 선은 면은 가지고 있지 않기 때문에 면 색을 채우는 fill() 함수는 적용되지 않습니다. 선의 굵기 초기값은 1픽셀이며 이를 변경하기 위해서는 strokeWeight() 함수를 이용합니다.",
               "params": ["숫자: 첫번째 점의 x 좌표",
        @@ -223,23 +274,711 @@
               "정수: y 방향의 segment 수 (WEBGL 모드에서 사용)"],
               "returns": "the p5 object"
             },
        -    "square": {
        -      "description": "화면에 정사각형을 그립니다. 정사각형은 변이 네개이면서 모든 각도가 90도이며 네 변의 길이가 같은 도형입니다. 정사격형은 사실상 rect() 함수로도 그릴 수 있는 도형으로, 너비와 높이가 모두 s로 같은 직사각형인 셈입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 한 변의 길이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 네번째, 다섯번째, 여섯번째, 일곱번째 변수를 입력해 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 각각 지정할 수 있습니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.",
        -      "params": ["숫자: 정사각형의 x 좌표값",
        -      "숫자: 정사각형의 y 좌표값",
        -      "숫자: 정사각형 한 변의 길이",
        -      "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력."],
        -      "returns": "the p5 object"
        +    "triangle": {
        +      "description": "三角形是个由连接三个点所形成的平面形。前两个参数定义第一个点,中间两个参数定义第二个点而最后两个参数定义第三个点。",
        +      "params": ["数字:第一个点的 x 坐标",
        +                 "数字:第一个点的 y 坐标",
        +                 "数字:第二个点的 x 坐标",
        +                 "数字:第二个点的 y 坐标",
        +                 "数字:第三个点的 x 坐标",
        +                 "数字:第三个点的 y 坐标"],
        +      "returns": ""
        +    },
        +    "ellipseMode": {
        +      "description": "更改 ellipse() 参数被解读的方式,用以更改椭圆形被画在画布上的位置。<br><br>默认模式为 ellipseMode(CENTER),ellipse() 前两个参数将被解读成椭圆形的中心点,而第三和第四个参数为宽度和高度。<br><br>ellipseMode(RADIUS) 将 ellipse() 的前两个参数解读成形状的中心点,但是第三和第四个参数被用于定义形状的半径宽度和半径高度<br><br>ellipseMode(CORNER) 将 ellipse() 的前两个参数解读成形状左上角的位置,而第三和第四个参数为宽度和高度<br><br>ellipseMode(CORNERS) 将 ellipse() 的前两个参数解读成形状其中一个角落的位置,而第三和第四个参数则被解读成对面角落的位置。<br><br>参数必须全是大写因为 Javascript 是个区分大小写的编程语言。",
        +      "params": ["常量:CENTER、RADIUS、CORNER 或 CORNERS"],
        +      "returns": ""
        +    },
        +    "noSmooth": {
        +      "description": "所有形状的边缘都为锯齿状。注意 smooth() 为默认模式所以您必须调用 noSmooth() 以禁用平滑形状、图像及字体。",
        +      "returns": ""
        +    },
        +    "rectMode": {
        +      "description": "更改 rect() 参数被解读的方式,用以更改方形被画在画布上的位置。<br><br>默认模式为 rectMode(CORNER), rect() 前两个参数将被解读成形状的左上角的位置,而第三和第四个参数为宽度和高度。<br><br>rectMode(CORNERS) 将 rect() 的前两个参数解读成形状其中一个角落的位置,而第三和第四个参数则被解读成对面角落的位置。<br><br>rectMode(CENTER) 将 rect() 的前两个参数解读成形状的中心点,而第三和第四个参数为宽度和高度。<br><br>rectMode(RADIUS) 也将的前两个参数解读成形状的中心点,但第三和第四个参数被用来定义形状一半的宽度和一半的高度。<br><br>参数必须全是大写因为 Javascript 是个区分大小写的编程语言。",
        +      "params": ["常量:CORNER、CORNERS、CENTER 或 RADIUS"],
        +      "returns": ""
        +    },
        +    "smooth": {
        +      "description": "所有形状的边缘都为非锯齿(平滑)状。smooth() 也将提高调整过大小的图像的素质。注意 smooth() 为默认模式;noSmooth() 也能用来禁用平滑形状、图像及字体。",
        +      "returns": ""
        +    },
        +    "strokeCap": {
        +      "description": "定义线条顶点的风格。顶点风格可以是方形、扩展式或圆形,它们个别参数为:SQUARE、PROJECT 及 ROUND。默认模式为 ROUND。",
        +      "params": ["常量:SQUARE、PROJECT 或 ROUND"],
        +      "returns": ""
        +    },
        +    "strokeJoin": {
        +      "description": "定义线条连接的风格。这些链接可以是尖角、斜角或圆角,它们个别参数为:MITER、BEVEL 及 ROUND。默认模式为 MITER。",
        +      "params": ["常量:MITER、BEVEL 或 ROUND"],
        +      "returns": ""
        +    },
        +    "strokeWeight": {
        +      "description": "定义线条、点及形状边线的宽度(粗度)。所有宽度单位都是像素。",
        +      "params": ["数字:线条的粗度(像素单位)"],
        +      "returns": ""
        +    },
        +    "bezier": {
        +      "description": "在荧幕上画个三次贝塞尔曲线。这些曲线是由一系列锚点和控制点所定义的。前两个参数定义第一个锚点而最后两个参数定义另一个锚点,这也是曲线的第一和最后一个点。中间的参数是用来定义控制点的位置并将决定曲线的形状。一般来说,控制点会将曲线“拉”向它们的方向。",
        +      "params": ["数字:第一个锚点的 x 坐标",
        +                 "数字:第一个锚点的 y 坐标",
        +                 "数字:第一个控制点的 x 坐标",
        +                 "数字:第一个控制点的 y 坐标",
        +                 "数字:第二个控制点的 x 坐标",
        +                 "数字:第二个控制点的 y 坐标",
        +                 "数字:第二个锚点的 x 坐标",
        +                 "数字:第二个锚点的 y 坐标",
        +                 "数字:第一个锚点的 z 坐标",
        +                 "数字:第一个控制点的 z 坐标",
        +                 "数字:第二个锚点的 z 坐标",
        +                 "数字:第二个控制点的 z 坐标"],
        +      "returns": ""
        +    },
        +    "bezierDetail": {
        +      "description": "定义贝塞尔曲线的解析度<br><br>默认值为 20。<br><br>这函数只有在 WEBGL 模式下有效果因为默认画布渲染模式并不会使用这设定。",
        +      "params": ["数字:曲线的解析度"],
        +      "returns": ""
        +    },
        +    "bezierPoint": {
        +      "description": "计算在 a、b、c、d 点定义的贝塞尔曲线上 t 位置的坐标。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。这函数可以先调用 x 坐标然后在调用 y 坐标已找到曲线上 t 位置的点坐标。",
        +      "params": ["数字:曲线上第一个点的坐标",
        +                 "数字:第一个控制点的坐标",
        +                 "数字:第二个控制点的坐标",
        +                 "数字:曲线上第二个点的坐标",
        +                 "数字:介于 0 和 1 之间的值"],
        +      "returns": "数字:贝塞尔曲线上 t 位置的值"
        +    },
        +    "bezierTangent": {
        +      "description": "计算在 a、b、c、d 点定义的贝塞尔曲线上 t 位置的切线值。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。",
        +      "params": ["数字:曲线上第一个点的坐标",
        +                 "数字:第一个控制点的坐标",
        +                 "数字:第二个控制点的坐标",
        +                 "数字:曲线上第二个点的坐标",
        +                 "数字:介于 0 和 1 之间的值"],
        +      "returns": "数字:贝塞尔曲线上 t 位置的切线值"
        +    },
        +    "curve": {
        +      "description": "在荧幕上的两点之间画一个曲线,两点由中间四个参数定义。前两个参数为控制点,可以当作曲线是从这个点开始的虽然它并不会被画出来。最后两个参数同样也是用来定义另外一个控制点。<br><br>更长的曲线能使用一系列 curve() 函数创造或使用 curveVertex()。另外一个叫 curveTightness() 的函数提供曲线视觉质量的控制。curve() 函数使用的是 Catmull-Rom 样条函数。",
        +      "params": ["数字:起点控制点的 x 坐标",
        +                 "数字:起点控制点的 y 坐标",
        +                 "数字:第一个点的 x 坐标",
        +                 "数字:第一个点的 y 坐标",
        +                 "数字:第二个点的 x 坐标",
        +                 "数字:第二个点的 y 坐标",
        +                 "数字:终点控制点的 x 坐标",
        +                 "数字:终点控制点的 y 坐标",
        +                 "数字:起点控制点的 z 坐标",
        +                 "数字:第一个点的 z 坐标",
        +                 "数字:第二个点的 z 坐标",
        +                 "数字:终点控制点的 z 坐标"],
        +      "returns": ""
        +    },
        +    "curveDetail": {
        +      "description": "定义曲线的解析度<br><br>默认值为 20。<br><br>这函数只有在 WEBGL 模式下有效果因为默认画布渲染模式并不会使用这设定。",
        +      "params": ["数字:曲线的解析度"],
        +      "returns": ""
        +    },
        +    "curveTightness": {
        +      "description": "更改由 curve() 及 curveVertex() 所创造的曲线的质量。所提供的参数将决定曲线如何切合顶点。0.0 是紧实度的默认值(这值表示曲线为 Catmull-Rom 样条)而 1.0 将使用直线连接所有点。在 -5.0 及 5.0 之间的值会是曲线变形不过他们仍然能被识别而当值越来越大时,曲线也会跟着变形。",
        +      "params": ["数字:从原顶点的变形量"],
        +      "returns": ""
        +    },
        +    "curvePoint": {
        +      "description": "计算在 a、b、c、d 点定义的曲线上 t 位置的坐标。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。这函数可以先调用 x 坐标然后在调用 y 坐标已找到曲线上 t 位置的点坐标。",
        +      "params": ["数字:曲线上第一个点的坐标",
        +                 "数字:第一个控制点的坐标",
        +                 "数字:第二个控制点的坐标",
        +                 "数字:曲线上第二个点的坐标",
        +                 "数字:介于 0 和 1 之间的值"],
        +      "returns": "数字:贝塞尔曲线上 t 位置的值"
        +    },
        +    "curveTangent": {
        +      "description": "计算在 a、b、c、d 点定义的曲线上 t 位置的切线值。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。",
        +      "params": ["数字:曲线上第一个点的坐标",
        +                 "数字:第一个控制点的坐标",
        +                 "数字:第二个控制点的坐标",
        +                 "数字:曲线上第二个点的坐标",
        +                 "数字:介于 0 和 1 之间的值"],
        +      "returns": "数字:贝塞尔曲线上 t 位置的切线值"
        +    },
        +    "beginContour": {
        +      "description": "使用 beginContour() 及 endContour() 函数以在其他形状内创造剪影形状,比如说 “O” 字母内的空间。beginContour() 将开始记录形状的顶点而 endContour() 则停止记录。定义剪影形状的顶点定义的方向(顺时或逆时针)必须和包含它的形状不同。如果外形的顶点是顺时针方向定义的,那么它里面的形状的顶点需是逆时针方向定义。<br><br>这些函数只能在一对 beginShape()/endShape() 函数之间使用而变形函数如 translate()、rotate() 及 scale() 在一对 beginContour()/endContour() 内并不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在里面使用。",
        +      "returns": ""
        +    },
        +    "beginShape": {
        +      "description": "使用 beginShape() 及 endShape() 函数可让您创造更复杂的形状。beginShape() 将开始记录形状的顶点而 endShape() 则停止记录。所提供的参数将决定由所提供的顶点该画出怎样的形状。如果模式没有被提供,所定义的形状可以是任何不规则的多边形。<br><br>可提供给 beginShape() 的参数包括 POINTS、LINES、TRIANGLES、TRIANGLE_FAN、TRIANGLE_STRIP、QUADS 及 QUAD_STRIP。在调用 beginShape() 函数之后,一系列 vertex() 函数必须接着调用。调用 endShape() 以停止绘制形状。每个形状都将会有由当时外线色所定义的外线色及当时的填充色。<br><br>变形函数如 translate()、rotate() 及 scale() 在 beginShape() 内不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在beginShape()里面使用。",
        +      "params": ["常量:POINTS、LINES、TRIANGLES、TRIANGLE_FAN、TRIANGLE_STRIP、QUADS 或 QUAD_STRIP"],
        +      "returns": ""
        +    },
        +    "bezierVertex": {
        +      "description": "定义贝塞尔曲线的顶点坐标。每次调用 bezierVertex() 将定义贝塞尔曲线的两个控制点和一个锚点,以在线或形状上增加一个新部分。<br><br>在 beginShape() 内第一次调用 bezierVertex() 之前必须先调用一次 vertex() 以定义第一个锚点。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。",
        +      "params": ["数字:第一个控制点的 x 坐标",
        +                 "数字:第一个控制点的 y 坐标",
        +                 "数字:第二个控制点的 x 坐标",
        +                 "数字:第二个控制点的 y 坐标",
        +                 "数字:第一个锚点的 x 坐标",
        +                 "数字:第二个锚点的 x 坐标"],
        +      "returns": ""
        +    },
        +    "curveVertex": {
        +      "description": "定义曲线顶点的坐标。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。<br><br>在一系列 curveVertex() 线条中第一个和最后一个点将被用来引导曲线的起点和终点。至少必须提供四个点以画一个介于第二和第三个点的小曲线。增加第五个点将会在第二、第三及第四个点之间画个曲线。curveVertex() 函数使用的是 Catmull-Rom 样条函数。",
        +      "params": ["数字:顶点的 x 坐标",
        +                 "数字:顶点的 y 坐标"],
        +      "returns": ""
        +    },
        +    "endContour": {
        +      "description": "使用 beginContour() 及 endContour() 函数以在其他形状内创造剪影形状,比如说 “O” 字母内的空间。beginContour() 将开始记录形状的顶点而 endContour() 则停止记录。定义剪影形状的顶点定义的方向(顺时或逆时针)必须和包含它的形状不同。如果外形的顶点是顺时针方向定义的,那么它里面的形状的顶点需是逆时针方向定义。<br><br>这些函数只能在一对 beginShape()/endShape() 函数之间使用而变形函数如 translate()、rotate() 及 scale() 在一对 beginContour()/endContour() 内并不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在里面使用。",
        +      "returns": ""
        +    },
        +    "endShape": {
        +      "description": "endShape() 函数和 beginShape() 是一对的而且它只能在 beginShape() 后使用。当 endshape() 被调用时,自上一次 beginShape() 调用后的所有被定义的图像资料将被写进图像缓冲区。定义常量 CLOSE 给 MODE 参数将会关闭该形状(连接起点和终点)。",
        +      "params": ["常量:使用 CLOSE 以关闭形状"],
        +      "returns": ""
        +    },
        +    "quadraticVertex": {
        +      "description": "定义二次贝塞尔曲线顶点的坐标。每次调用 quadraticVertex() 将定义贝塞尔曲线的一个控制点和一个锚点,以在线或形状上增加一个新部分。在 beginShape() 内第一次调用 quadraticVertex() 之前必须先调用一次 vertex() 以定义第一个锚点。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。",
        +      "params": ["数字:控制点的 x 坐标",
        +                 "数字:控制点的 y 坐标",
        +                 "数字:锚点的 x 坐标",
        +                 "数字:锚点的 y 坐标"],
        +      "returns": ""
        +    },
        +    "vertex": {
        +      "description": "所有形状都是由连接一系列顶点形成的。vertex() 可用于定义点、线、三角形、四角形及多边形的顶点坐标。它只能在 beginShape() 和 endShape() 函数之间使用。",
        +      "params": ["数字:顶点的 x 坐标",
        +                 "数字:顶点的 y 坐标",
        +                 "数字:顶点的 z 坐标",
        +                 "数字:顶点的纹理 u 坐标",
        +                 "数字:顶点的纹理 v 坐标"],
        +      "returns": ""
        +    },
        +    "loadModel": {
        +      "description": "从一个 OBJ 档案加载一个三维模型。<br><br>OBJ 格式的其中一个限制是它没有内建的大小值。这表示不同程式输出的模型可能有非常不同的大小。如果您的模型没被展示的话,请试着调用 loadModel() 并给予 normalized 参数“真”(true)值。这会将模型缩放成适合 p5 的大小。您也可以使用 scale() 函数对您的模型最后大小做与更多的调整。",
        +      "params": ["字符串:要加载的模型的路径",
        +                 "布尔值:如果为真,在加载时将模型缩放成标准大小。",
        +                 "函数(p5.Geometry):此函数将在模型完成加载后被调用,将被给予该三维模型为参数。",
        +                 "函数(Event):如果模型加载失败,此函数将被调用并给予错误事件(event)为参数。"],
        +      "returns": "p5.Geometry:p5.Geometry 物件"
        +    },
        +    "model": {
        +      "description": "将一个三维模型渲染在荧幕上。",
        +      "params": ["p5.Geometry:要渲染的已加载的模型"],
        +      "returns": ""
        +    },
        +    "plane": {
        +      "description": "用给予的宽度和高度画一个平面。",
        +      "params": ["数字:平面的宽度",
        +                 "数字:平面的高度",
        +                 "整数:(可选)在 x 轴的三角形细分数",
        +                 "整数:(可选)在 y 轴的三角形细分数"],
        +      "returns": ""
        +    },
        +    "box": {
        +      "description": "用给予的宽度、高度及深度画一个立方体。",
        +      "params": ["数字:立方体的宽度",
        +                 "数字:立方体的高度",
        +                 "数字:立方体的深度",
        +                 "整数:(可选)在 x 轴的三角形细分数",
        +                 "整数:(可选)在 y 轴的三角形细分数"],
        +      "returns": ""
        +    },
        +    "sphere": {
        +      "description": "用给予的半径画一个球形。",
        +      "params": ["数字:球形的半径",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 16"],
        +      "returns": ""
        +    },
        +    "cylinder": {
        +      "description": "用给予的半径和高度画一个圆筒形。",
        +      "params": ["数字:表面的半径",
        +                 "数字:圆筒形的高度",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        +                 "整数:y 轴分割的数量,越多分割几何形越平滑,默认值为 1",
        +                 "布尔值:是否该画圆筒形的底部",
        +                 "布尔值:是否该画圆筒形的顶部"],
        +      "returns": ""
        +    },
        +    "cone": {
        +      "description": "用给予的半径和高度画一个锥体形。",
        +      "params": ["数字:底部表面的半径",
        +                 "数字:锥体形的高度",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 1",
        +                 "布尔值:是否该画锥体形的底部"],
        +      "returns": ""
        +    },
        +    "ellipsoid": {
        +      "description": "用给予的半径画一个椭球形。",
        +      "params": ["数字:椭球形 x 轴的半径",
        +                 "数字:椭球形 y 轴的半径",
        +                 "数字:椭球形 z 轴的半径",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24。避免多于 150 的细节数量,因为它可能是浏览器停止运作。",
        +                 "整数:分割的数量,越多分割几何形越平滑,默认值为 16。避免多于 150 的细节数量,因为它可能是浏览器停止运作。"],
        +      "returns": ""
        +    },
        +    "torus": {
        +      "description": "用给予的半径和管半径画一个圆环形。",
        +      "params": ["数字:整个圆环形的半径",
        +                 "数字:圆管的半径",
        +                 "整数:x 轴分割的数量,越多分割几何形越平滑,默认值为 24。",
        +                 "整数:y 轴分割的数量,越多分割几何形越平滑,默认值为 16。"],
        +      "returns": ""
        +    },
        +    "HALF_PI": {
        +      "description": "HALF_PI 是个值为 1.57079632679489661923 的数学常量。它是圆形周长与直径的比例的一半。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "returns": ""
        +    },
        +    "PI": {
        +      "description": "PI 是个值为 3.14159265358979323846 的数学常量。它是圆形周长与直径的比例。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "returns": ""
        +    },
        +    "QUARTER_PI": {
        +      "description": "QUARTER_PI 是个值为 0.7853982 的数学常量。它是圆形周长与直径的比例的四分之一。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "returns": ""
        +    },
        +    "TAU": {
        +      "description": "TAU 是 TWO_PI 的别名,是个值为 6.28318530717958647693 的数学常量。它是圆形周长与直径的比例的两倍。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "returns": ""
        +    },
        +    "TWO_PI": {
        +      "description": "TWO_PI 是个值为 6.28318530717958647693 的数学常量。它是圆形周长与直径的比例的两倍。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "returns": ""
        +    },
        +    "DEGREES": {
        +      "description": "与 angleMode() 函数一起使用的常量,用于设定 p5.js 如何解读及计算角度(可以是 DEGREES 或 RADIANS)。",
        +      "returns": ""
        +    },
        +    "RADIANS": {
        +      "description": "与 angleMode() 函数一起使用的常量,用于设定 p5.js 如何解读及计算角度(可以是 DEGREES 或 RADIANS)。",
        +      "returns": ""
        +    },
        +    "preload": {
        +      "description": "在 setup() 之前被调用,preload() 函数可用来以阻断的方式处理异步加载外来文件。如果 preload 函数有被定义,setup() 将等到其中的加载工作都完成后才开始执行。preload 函数只能含有加载函数(如 loadImage、loadJSON、loadFont、loadStrings 等)。如果您想使用异步加载,加载函数可在 setup() 内或任何其他地方调用,您只需使用其回调函数参数。<br><br>在默认情况下 “loading...” 字眼将会被显示。如果您想只做您自己的加载页面,只需在您也页面上加个 id 为 “p5_loading” 的 HTML 元素。更多详情请查看<a href='http://bit.ly/2kQ6Nio'>这里</a>。",
        +      "returns": ""
        +    },
        +    "setup": {
        +      "description": "setup() 函数将在程式开始时被调用一次。它可在程序开始时被用来定义初始的环境属性如荧幕大小、背景颜色及媒体加载如图像及字体。每个程序只能有一个 setup() 函数并且他不能在一开始执行后再次被调用。<br><br>请注意:在 setup() 内定义的变量并不能在其他函数内使用,这包括 draw() 。",
        +      "returns": ""
        +    },
        +    "draw": {
        +      "description": "在 setup() 之后被调用,draw() 函数将持续地重复执行其中的代码直到该程式终止或当 noLoop() 被调用。注意如果 noLoop() 在 setup() 内被调用,draw() 仍然会被执行一个然后才停止。draw() 将会自动被调用并不应该被直接调用。<br><br>您应该使用 noLoop()、redraw() 及 loop() 来控制它。当 noLoop() 停止执行 draw() 内的代码,redraw() 会使 draw() 内的代码执行一次,而 loop() 将会使 draw() 内的代码继续重复执行。<br><br>每一秒 draw() 执行的次数可使用 frameRate() 函数来控制。<br><br>每个绘图只能有一个 draw() 函数,而如果您想持续重复执行代码或处理事件如 mousePressed(),draw() 必须存在。有时候您的程式可能会有空白的 draw() 函数,如以上的范例所示。<br><br>请特别注意绘图坐标系统将在每次 draw() 在开始被调用时重置。任何在 draw() 内执行的变形指令(如 scale、rotate、translate)将会在下一个 draw() 开始时复原,所以变形指令并不会随着时间积累。另一方面,样式(如 fill、stroke等)将会持续同样的效果。",
        +      "returns": ""
        +    },
        +    "remove": {
        +      "description": "移除整个 p5 绘图。这函数将移除画布及任何由 p5.js 创造的元素。它也会终止绘图循环及解除任何被绑定在窗口对象的属性或函数。它会留下一个 p5 变量以防您还想创造一个新的 p5 绘图。您也可以舍去 p5 = null 以完全删除它。虽然所有由 p5 程式库所创造的函数、变量和物件将会被移除,任何其他由您的代码所定义的公共变量将会被保留。",
        +      "returns": ""
        +    },
        +    "noLoop": {
        +      "description": "停止 p5.js 持续重复执行 draw() 内的代码。如果 loop() 被调用,draw() 内的代码将开始继续重复执行。如果 noLoop() 在 setup() 被调用,它应该是代码块的最后一行代码。<br><br>在使用 noLoop() 时,您并不能在事件处理函数如 mousePressed() 或 keyPressed() 内操纵或存取荧幕。不过您可以使用哪些函数调用 redraw() 或 loop(),从而执行 draw(),以正确的更新荧幕。这表示当 noLoop() 被调用后,您不能绘制任何东西,同时某些函数如 saveFrame() 或 loadPixels() 也不能使用。<br><br>注意如果绘图的大小改变,redraw() 将会被调用以更新绘图,即使 noLoop() 已经被调用,不然绘图将会处于一个奇怪的状态直到 loop() 再次被调用。",
        +      "returns": ""
        +    },
        +    "loop": {
        +      "description": "在默认下,p5.js 将会循环执行 draw() 内的代码。不过 draw() 循环能使用 noLoop() 停止。在这情况下 draw() 循环可使用 loop() 函数恢复执行。",
        +      "returns": ""
        +    },
        +    "push": {
        +      "description": "push() 函数将储存当时的绘画样式设置及变形,而 pop() 将恢复这些设置。注意这两个函数需要一起使用。它们让您改变样式及变形设置然后再回到您之前的设置。当使用 push() 开始一个新的状态时,它将继续建立在当时的样式和变形上。push() 和 pop() 函数可被重复嵌入以提供更复杂的控制。(请参考第二个范例)<br><br>push() 将现有的变形及样式设置资料储存上来,这包括以下的函数:fill()、stroke()、tint()、strokeWeight()、strokeCap()、strokeJoin()、imageMode()、rectMode()、ellipseMode()、colorMode()、textAlign()、textFont()、textMode()、textSize()、textLeading()。",
        +      "returns": ""
        +    },
        +    "pop": {
        +      "description": "push() 函数将储存当时的绘画样式设置及变形,而 pop() 将恢复这些设置。注意这两个函数需要一起使用。它们让您改变样式及变形设置然后再回到您之前的设置。当使用 push() 开始一个新的状态时,它将继续建立在当时的样式和变形上。push() 和 pop() 函数可被重复嵌入以提供更复杂的控制。(请参考第二个范例)<br><br>push() 将现有的变形及样式设置资料储存上来,这包括以下的函数:fill()、stroke()、tint()、strokeWeight()、strokeCap()、strokeJoin()、imageMode()、rectMode()、ellipseMode()、colorMode()、textAlign()、textFont()、textMode()、textSize()、textLeading()。"
        +    },
        +    "redraw": {
        +      "description": "执行在 draw() 内的代码一次。这函数让该程序只在需要的时候更新显示窗口,比如说当 mousePressed() 或 keyPressed()事件被触发时。<br><br>再构造程式时,只有在如 mousePressed() 之类的时间内调用 redraw() 才有意义,因为 redraw() 并不会直接调用 draw() (它只会表示绘图有需要更新)。<br><br>redraw() 函数并不会在 draw() 内正常运作。以启用/禁用动画,请使用 loop() 及 noLoop()。<br><br>此外您也能定义每次调用 redraw() 将使 draw() 被调用几次。您这需给予一个整数参数已表示执行的次数。",
        +      "params": ["整数:重绘 n 次。默认值为 1"],
        +      "returns": ""
        +    },
        +    "print": {
        +      "description": "print() 函数将写入浏览器的控制台区。这函数适用于查看程式生成的资料。这函数每一次被调用将创造新的一行字串。个别元素可使用引号(\"\")分隔并使用加号(+)连接在一起。",
        +      "params": ["任何:任何要写进控制台的数字、字符串、物件、布尔值或数组的组合"],
        +      "returns": ""
        +    },
        +    "frameCount": {
        +      "description": "系统变量 frameCount 存着自程序开始已被展示的影格数量。在 setup() 这值为 0,在第一次执行 draw() 后为 1 等等。",
        +      "returns": ""
        +    },
        +    "focused": {
        +      "description": "确定 p5.js 程式正在运行的窗口是否获得“焦点”,这表示绘图可接受滑鼠或键盘输入。如果窗口获得焦点,次变量为 “true” 否则为 “false”。",
        +      "returns": ""
        +    },
        +    "cursor": {
        +      "description" : "设置鼠标成预定的符号或一个图像,或者如果鼠标被隐藏显示鼠标。如果你想要设置一个图像为鼠标,建议的图像大小为 16x16 或 32x32 像素。 It is not possible to load an image as the cursor if you are exporting your program for the Web, and not all MODES work with all browsers. 参数 x 及 y 必须低于图像的大小。",
        +      "params": ["字符串|常量:ARROW、CROSS、HAND、MOVE、TEXT 或图像的路径",
        +                 "数字:鼠标的横向活跃点",
        +                 "数字:鼠标的直向活跃点"],
        +      "returns": ""
             },
        +    "frameRate": {
        +      "description": "定义每一秒应该显示的影格数。比如说,调用 frameRate(30) 将使绘图每秒刷新 30 次。如果处理器没法跟上所定义的速率,该帧率将不会被达到。建议在 setup() 内设置帧率。默认的帧率值为每秒 60 影格。这和调用 setFrameRate(val) 的效果一样。<br><br>调用 frameRate() 但不给予任何参数将会返回当时的帧率。draw() 函数必须至少执行一次它才会返回帧率。这和调用 getFrameRate() 的效果一样。<br><br>调用 frameRate() 并给予任何不是数字或正数的参数也将会返回当时的帧率。",
        +      "params": ["数字:每一秒该显示的影格数"],
        +      "returns": ""
        +    },
        +    "noCursor": {
        +      "description": "隐藏鼠标。",
        +      "returns": ""
        +    },
        +
        +    "displayWidth": {
        +      "description": "储存整个荧幕宽度的系统变量。这可用来在任何大小的荧幕制作任何大小的全屏程序。",
        +      "returns": ""
        +    },
        +    "displayHeight": {
        +      "description": "储存整个荧幕高度的系统变量。这可用来在任何大小的荧幕制作任何大小的全屏程序。",
        +      "returns": ""
        +    },
        +    "windowWidth": {
        +      "description": "储存窗口内部宽度的系统变量, 此函数映射 window.innerWidth。",
        +      "returns": ""
        +    },
        +    "windowHeight": {
        +      "description": "储存窗口内部高度的系统变量, 此函数映射 window.innerHeight。",
        +      "returns": ""
        +    },
        +    "windowResized": {
        +      "description": "windowResized() 函数将在每次浏览器窗口缩放时被调用。这是个适合缩放画布及或任何其他调整以符合新的窗口大小的地方。",
        +      "returns": ""
        +    },
        +    "width": {
        +      "description": "储存画布宽度的系统变量。这值是由 createCanvas() 函数的第一个参数所定义。比如说,调用函数 createCanvas(320, 240) 将定义此宽度变量为 320。如果一个程式没有使用 createCanvas() 宽度值将默认为 100。",
        +      "returns": ""
        +    },
        +    "height": {
        +      "description": "储存画布高度的系统变量。这值是由 createCanvas() 函数的第二个参数所定义。比如说,调用函数 createCanvas(320, 240) 将定义此高度变量为 240。如果一个程式没有使用 createCanvas() 高度值将默认为 100。",
        +      "returns": ""
        +    },
        +    "fullscreen": {
        +      "description": "如果提供一个参数,依该参数而定该绘图是否是全屏。如果没有给予任何参数,将返回当时的全屏状态。注意因为浏览器限制,此函数只能在使用者输入时调用,比如说在滑鼠点击时如以上范例。",
        +      "params": ["布尔值:该绘图是否应该是全屏"],
        +      "returns": "布尔值:当时的全屏状态"
        +    },
        +    "pixelDensity": {
        +      "description": "定义像素缩放值,用于高像素密度显示器。默认像素密度为显示器的像素密度,可调用 pixelDensity(1) 以关闭此功能。调用 pixelDensity() 并不给予任何参数将返回该绘图的像素密度。",
        +      "params": ["数字:绘图是否应该缩放及缩放多少"],
        +      "returns": "数字:该绘图的像素密度"
        +    },
        +    "displayDensity": {
        +      "description": "返回正在运行该绘图的显示器的像素密度。",
        +      "returns": "数字:该显示器的像素密度"
        +    },
        +    "getURL": {
        +      "description": "返回当下的网址。",
        +      "returns": "字符串:网址"
        +    },
        +    "getURLPath": {
        +      "description": "返回当下的网址的路径数组",
        +      "returns": "字符串[]:路径组"
        +    },
        +    "getURLParams": {
        +      "description": "返回当下网址的参数物件",
        +      "returns": "物件:网址参数"
        +    },
        +
             "createCanvas": {
               "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를  참고하세요.",
               "params": ["숫자: 캔버스의 너비",
               "숫자: 캔버스의 높이",
               "상수: P2D 또는 WEBGL"]
             },
        +      
        +    "resizeCanvas": {
        +      "description": "缩放画布至给予的宽度和高度。该画布将会马上被清空及调用 draw(),使得画布能在缩放后重新渲染。",
        +      "params": ["数字:画布的宽度",
        +                 "数字:画布的高度",
        +                 "布尔值:不要马上更新画布"],
        +      "returns": ""
        +    },
        +    "noCanvas": {
        +      "description": "如果该 p5 绘图不需要画布,此函数将移除默认画布。",
        +      "returns": ""
        +    },
        +    "createGraphics": {
        +      "description": "创造及返回一个新的 p5.Renderer 物件。如果您需要在一个画面外的图形缓冲区作画,您可以使用这个函数。前两个参数将定义宽度和高度像素。",
        +      "params": ["数字:画面外图形缓冲区的宽度",
        +                 "数字:画面外图形缓冲区的高度",
        +                 "常量:P2D 或 WEBGL,默认为 P2D"],
        +      "returns": "buffer gráfico fuera de pantalla"
        +    },
        +    "blendMode": {
        +      "description": "根据所设定的模式在显示窗口内混合像素。以下模式选择可用来混合源像素(A)与已经在显示窗口的像素(B):<ul><li><code>BLEND</code> - 颜色线性插值:C = A*系数 + B。这是默认混合模式。</li><li><code>ADD</code> - A 与 B 的总和</li><li><code>DARKEST</code> - 将显示当中最深的颜色:C = min(A*系数, B)。</li><li><code>LIGHTEST </code> - 将显示当中最浅的颜色:C = max(A*系数, B)。</li><li><code>DIFFERENCE</code> - 从底下的图像中减去颜色。</li><li><code>EXCLUSION</code> - 与 DIFFERENCE 相似但不那么强烈。</li><li><code>MULTIPLY</code> - 将颜色相乘,效果一定会更暗。</li><li><code>SCREEN</code> - 与 MULTIPLY 相反,使用颜色的反值。</li><li><code>REPLACE</code> - 像素将完全盖过其他像素并将不会使用透明度值。</li><li><code>OVERLAY</code> - MULTIPLY 及 SCREEN 和混合。暗值将相乘,亮值将相乘反值。</li><li><code>HARD_LIGHT</code> - 当高于 50% 灰时 SCREEN,低于时 MULTIPLY。</li><li><code>SOFT_LIGHT</code> - DARKEST 及 LIGHTEST 的混合。与 OVERLAY 的效果相似,但不那么强烈。</li><li><code>DODGE</code> - 使浅色更浅及增加对比度,忽略暗色。</li><li><code>BURN</code> - 是深色更深及增加对比度,忽略浅色。</li></ul>",
        +      "params": ["常量:画布的混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL"],
        +      "returns": ""
        +    },
        +    "setAttributes": {
        +      "description": "设置 WebGL 绘图环境的属性。这是调整 WebGL 渲染器的一个方法,可用于微调显示及性能。这函数应该在 setup() 内使用。可使用的属性为:<br>alpha - 表示画布是否有透明度缓冲,默认为 true<br><br>depth - 表示绘图缓冲是否有至少 16 bits 的深度缓冲 - 默认为 true<br><br>stencil - 表示绘图缓冲是否有至少 8 bits 的模版缓冲<br><br>antialias - 表示是否应该执行抗锯齿,默认为 false<br><br>premultipliedAlpha - 表示页面合成器将假设绘图缓冲存在着预乘透明值的颜色,默认为 false<br><br>preserveDrawingBuffer - 如果为真缓冲区将不会被清空并将会保留现有的值直到它们被清空或被作者覆盖(注意 p5 在绘图循环将自动清空),默认为 true<br><br>perPixelLighting - 如果为真,照明着色器将使用个别像素照明。默认为 false",
        +      "params": ["字符串:属性名",
        +                 "布尔值:属性的新值",
        +                 "物件:有键值对的物件"]
        +    },
        +    "applyMatrix": {
        +      "description": "将现有的矩阵乘于由参数所定义的矩阵。这是个强大的功能并能够同时执行平移、缩放、切变及旋转。您能在<a href='https://zh.wikipedia.org/wiki/%E5%8F%98%E6%8D%A2%E7%9F%A9%E9%98%B5'>维基百科</a>了解更多关于变形矩阵的资讯。<br><br>这里的参数命名跟着 <a href='https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform'>WHATWG 规范</a>(英文页面)的命名方式并代表着一个如下的变形矩阵:<blockquote><p><img style='max-width: 150px' src='assets/transformation-matrix.png' alt='当 applyMatrix 被调用时所使用的变形矩阵'></p></blockquote>",
        +      "params": ["数字:定义该乘于的 2x3 矩阵",
        +                 "数字:定义该乘于的 2x3 矩阵",
        +                 "数字:定义该乘于的 2x3 矩阵",
        +                 "数字:定义该乘于的 2x3 矩阵",
        +                 "数字:定义该乘于的 2x3 矩阵",
        +                 "数字:定义该乘于的 2x3 矩阵"],
        +      "returns": ""
        +    },
        +    "resetMatrix": {
        +      "description": "将现有的矩阵替换成单位矩阵。",
        +      "returns": ""
        +    },
        +    "rotate": {
        +      "description": "将一个形状根据参数所定义的角度旋转。这函数将考虑角度模式,所以角度可以是弧度或角度定义。<br><br>所有物件都会绕着原点旋转而正数将使物件在顺时针方向旋转。此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 rotate(HALF_PI) 然后 rotate(HALF_PI) 效果会与 rotate(PI) 相同。所有变形将会在 draw() 重新开始时恢复。",
        +      "params": ["数字:旋转的角度,根据当时的角度模式,以弧度或角度定义",
        +                 "p5.Vector|数字[]:(3D 模式下)旋转轴"],
        +      "returns": ""
        +    },
        +    "rotateX": {
        +      "description": "绕着 x 轴旋转。",
        +      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "returns": ""
        +    },
        +    "rotateY": {
        +      "description": "绕着 y 轴旋转。",
        +      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "returns": ""
        +    },
        +    "rotateZ": {
        +      "description": "绕着 x 轴旋转。只适用于 WEBGL 模式。",
        +      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "returns": ""
        +    },
        +    "scale": {
        +      "description": "通过扩大和收缩顶点,放大或缩小形状。形状物件将会从坐标系统的原点开始缩放。缩放值为十进制百分比。比如说,调用函数 scale(2.0) 将使该形状放大 200%。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积相乘。比如说,调用 scale(2.0) 然后 scale(1.5) 效果会与 scale(3.0) 相同。如果 scale() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>给予此函数一个 z 参数只在 WEBGL 模式下受支持。这函数能使用 push() 及 pop() 控制。",
        +      "params": ["数字|p5.Vector|数字[]:缩放物件的百分比,或如果给予多个参数 x 轴的缩放百分比",
        +                 "数字:y 轴的缩放百分比",
        +                 "数字:z 轴的缩放百分比(只适用于 WEBGL 模式)",
        +                 "p5.Vector|数字[]:各轴缩放百分比"],
        +      "returns": ""
        +    },
        +    "shearX": {
        +      "description": "有角度参数所定义的形状 x 轴切变量。角度必须符合当时的角度模式。形状物件将会从坐标系统的原点开始切变而正数表示切变方向为顺时针方向。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 shearX(PI/2) 然后 shearX(PI/2) 效果会与 shearX(PI) 相同。如果 shearX() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>技术上,shearX() 将现有的变形矩阵乘以一个旋转矩阵。这函数能使用 push() 及 pop() 控制。",
        +      "params": ["数字:根据当时的角度模式,以弧度或角度定义和切变角度"],
        +      "returns": ""
        +    },
        +    "shearY": {
        +        "description": "有角度参数所定义的形状 y 轴切变量。角度必须符合当时的角度模式。形状物件将会从坐标系统的原点开始切变而正数表示切变方向为顺时针方向。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 shearY(PI/2) 然后 shearY(PI/2) 效果会与 shearY(PI) 相同。如果 shearY() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>技术上,shearY() 将现有的变形矩阵乘以一个旋转矩阵。这函数能使用 push() 及 pop() 控制。",
        +        "params": ["数字:根据当时的角度模式,以弧度或角度定义和切变角度"],
        +        "returns": ""
        +    },
        +    "translate": {
        +      "description": "定义在显示窗口内平移物件的量。x 参数将定义左/右平移,y 参数将定义上/下平移。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 translate(50, 0) 然后 translate(20, 0) 效果会与 translate(70, 0) 相同。如果 translate() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。这函数能使用 push() 及 pop() 控制。",
        +      "params": ["数字:左/右平移",
        +                 "数字:上/下平移",
        +                 "数字:前/后平移(只适用于 WEBGL 模式)",
        +                 "p5.Vector:平移向量"],
        +      "returns": ""
        +    },
        +
        +    "deviceOrientation": {
        +      "description": "deviceOrientation 系统变量将会储存设备的旋转方向。此变量的值可以是 ‘landscape’ 或 ‘portrait’。如果没有资料可用他会被定义成 ‘undefined’。LANDSCAPE 或 PORTRAIT。",
        +      "returns": ""
        +    },
        +    "accelerationX": {
        +      "description": "accelerationX 系统变量将会储存设备的 x 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "accelerationY": {
        +      "description": "accelerationY 系统变量将会储存设备的 y 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "accelerationZ": {
        +      "description": "accelerationZ 系统变量将会储存设备的 z 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "pAccelerationX": {
        +      "description": "pAccelerationX 系统变量将会储存上一个影格该设备的 x 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "pAccelerationY": {
        +      "description": "pAccelerationY 系统变量将会储存上一个影格该设备的 y 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "pAccelerationZ": {
        +      "description": "pAccelerationZ 系统变量将会储存上一个影格该设备的 z 轴加速度。值的单位为每平方秒米。",
        +      "returns": ""
        +    },
        +    "rotationX": {
        +      "description": "rotationX 系统变量将会储存设备在 x 轴的旋转角度。值介于 0 与 +/-180 度之间。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "returns": ""
        +    },
        +    "rotationY": {
        +      "description": "rotationY 系统变量将会储存设备在 y 轴的旋转角度。值介于 0 与 +/-90 度之间。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "returns": ""
        +    },
        +    "rotationZ": {
        +      "description": "rotationZ 系统变量将会储存设备在 z 轴的旋转角度。值介于 0 与 359 度之间。<br><br>与 rotationX 及 rotationY 不同的是,这变量只能在有内建指南针的设备使用。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "returns": ""
        +    },
        +    "pRotationX": {
        +      "description": "pRotationX 系统变量将会储存上一个影格该设备在 x 轴的旋转角度。值介于 0 与 +/-180 度之间。<br><br>pRotationX 可以和 rotationX 一起使用以找出设备 x 轴的旋转方向。",
        +      "returns": ""
        +    },
        +    "pRotationY": {
        +      "description": "pRotationY 系统变量将会储存上一个影格该设备在 y 轴的旋转角度。值介于 0 与 +/-90 度之间。<br><br>pRotationY 可以和 rotationY 一起使用以找出设备 y 轴的旋转方向。",
        +      "returns": ""
        +    },
        +    "pRotationZ": {
        +      "description": "pRotationZ 系统变量将会储存上一个影格该设备在 z 轴的旋转角度。值介于 0 与 359 度之间。<br><br>pRotationZ 可以和 rotationZ 一起使用以找出设备 z 轴的旋转方向。",
        +      "returns": ""
        +    },
        +    "setMoveThreshold": {
        +      "description": "setMoveThreshold() 函数可用来设置 deviceMoved() 函数的移动阈值。默认阈值为 0.5。",
        +      "params": ["数字:阈值"],
        +      "returns": ""
        +    },
        +    "setShakeThreshold": {
        +      "description": "setShakeThreshold() 函数可用来设置 deviceShaken() 函数的摇动阈值。默认阈值为 30。",
        +      "params": ["数字:阈值"],
        +      "returns": ""
        +    },
        +    "deviceMoved": {
        +      "description": "deviceMoved() 函数将在设备在 X、Y 或 Z 轴被移动多过阈值时被调用。默认阈值为 0.5。",
        +      "returns": ""
        +    },
        +    "deviceTurned": {
        +      "description": "deviceTurned() 函数将在设备被连续旋转多过 90 度时被调用。<br><br>触发 deviceTurned() 的旋转轴将被储存在 turnAxis 变量中。deviceTurned() 函数能被锁定在 X、Y 或 Z 以确保只有所定义的轴会导致函数被调用,您只需比较 turnAxis 变量和 'X'、'Y' 或 'Z' 字符串。",
        +      "returns": ""
        +    },
        +    "deviceShaken": {
        +      "description": "deviceShaken() 函数将在设备的 accelerationX 及 accelerationY 加速度值改变超过阈值。默认阈值为 30。",
        +      "returns": ""
        +    },
        +    "keyIsPressed": {
        +      "description": "keyIsPressed 布尔系统变量将会在任何键被按下时为真(true)而没键被按下时为假(false)。",
        +      "returns": ""
        +    },
        +    "key": {
        +      "description": "key 系统变量将会储存上一个被键入的键盘键值。以获得正确的大小写,最好在 keyTyped() 内使用。至于非 ASCII 值的键,请使用 keyCode 变量。",
        +      "returns": ""
        +    },
        +    "keyCode": {
        +      "description": "keyCode 变量可用来探测特别键如 BACKSPACE、DELETE、ENTER、RETURN、TAB、ESCAPE、SHIFT、CONTROL、OPTION、ALT、UP_ARROW、DOWN_ARROW、LEFT_ARROW、RIGHT_ARROW 是否被按下。您也可以使用特别网站如 <a href='http://keycode.info/'>keycode.info</a> 以找出自定义键的 keyCode。",
        +      "returns": ""
        +    },
        +    "keyPressed": {
        +      "description": "keyPressed() 函数将会在每一次任何键被按下时被调用。被按下的键的 keyCode 将被储存在 keyCode 变量内。<br><br>对于非 ASCII 值的键,请使用 keyCode 变量。您能查看 keyCode 是否等于 BACKSPACE、DELETE、ENTER、RETURN、TAB、ESCAPE、SHIFT、CONTROL、OPTION、ALT、UP_ARROW、DOWN_ARROW、LEFT_ARROW、RIGHT_ARROW。<br><br>至于 ASCII 键值它们的值会被储存在 key 变量内。不过,它并不会分辨大小写。因此,建议使用 keyTyped() 以读取 key 变量,因为其大小写在这里会被分辨出来。<br><br>取决于操作系统如何处理按键重复,按住一个键可能使 keyTyped() (及 keyReleased())被调用多过一次。重复的速度应操作系统及该电脑的设置而定。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "keyReleased": {
        +      "description": "keyReleased() 函数将会在每一次任何键被释放时被调用。请查看 key 及 keyCode 以知更多详情。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "keyTyped": {
        +      "description": "keyTyped() 函数将会在每一次任何键被按下时被调用,可是会忽略操作键如 Ctrl、Shift 及 Alt。被按下的键的 keyCode 将被储存在 keyCode 变量内。<br><br>取决于操作系统如何处理按键重复,按住一个键可能使 keyTyped() (及 keyReleased())被调用多过一次。重复的速度应操作系统及该电脑的设置而定。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "keyIsDown": {
        +      "description": "keyIsDown() 函数将查看被提供的键是否正被按下。它能在当您需要使用多个不同的键同时用来移动一个物件时使用(如将一个图像往斜移动)。您能给予任何代表该键的 keyCode 会任何<a href='http://p5js.org/zh-Hans/reference/#p5/keyCode'>此页</a>的 keyCode 变量名为参数。",
        +      "params": ["数字:该查看的键"],
        +      "returns": ""
        +    },
        +    "mouseX": {
        +      "description": "mouseX 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的横向位置。如果使用的是触动而不是滑鼠的话,mouseX 将会储存上一个触动点的 x 值。",
        +      "returns": ""
        +    },
        +    "mouseY": {
        +      "description": "mouseY 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的直向位置。如果使用的是触动而不是滑鼠的话,mouseY 将会储存上一个触动点的 y 值。",
        +      "returns": ""
        +    },
        +    "pmouseX": {
        +        "description": "pmouseX 系统变量将会储存上一个影格鼠标或触动点相对于画布 (0, 0) 位置的的横向位置。",
        +        "returns": ""
        +    },
        +    "pmouseY": {
        +      "description": "pmouseY 系统变量将会储存上一个影格鼠标或触动点相对于画布 (0, 0) 位置的的直向位置。",
        +      "returns": ""
        +    },
        +    "winMouseX": {
        +      "description": "winMouseX 系统变量将会储存当时鼠标相对于窗口 (0, 0) 位置的横向位置。",
        +      "returns": ""
        +    },
        +    "winMouseY": {
        +      "description": "winMouseY 系统变量将会储存当时鼠标相对于窗口 (0, 0) 位置的直向位置。",
        +      "returns": ""
        +    },
        +    "pwinMouseX": {
        +      "description": "pwinMouseX 系统变量将会储存上一个影格鼠标相对于窗口 (0, 0) 位置的横向位置。",
        +      "returns": ""
        +    },
        +    "pwinMouseY": {
        +      "description": "pwinMouseY 系统变量将会储存上一个影格鼠标相对于窗口 (0, 0) 位置的直向位置。",
        +      "returns": ""
        +    },
        +    "mouseButton": {
        +      "description": "p5 将自动记录滑鼠键是否被按下及哪个键被按下。mouseButton 系统变量的值可能是 LEFT、RIGHT 或 CENTER,取决于上一个被按下的滑鼠键。请注意:不同的浏览器可能记录不同的 mouseButton 值。",
        +      "returns": ""
        +    },
        +    "mouseIsPressed": {
        +      "description": "mouseIsPressed 系统变量将会在滑鼠键被按下时为真(true),而没按下时为假(false)。",
        +      "returns": ""
        +    },
        +    "mouseMoved": {
        +      "description": "mouseMoved() 函数将在每次鼠标移动而滑鼠键没有被按下的时候被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "mouseDragged": {
        +      "description": "mouseDragged() 函数将在每次鼠标移动及滑鼠键正被按下的时候被调用。如果 mouseDragged() 函数并未有被定义,touchMoved() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "mousePressed": {
        +      "description": "mousePressed() 函数将在每次滑鼠键被按下时被调用。mouseButton 函数(请参考其文献)可以被用来探测哪一个滑鼠键刚被按下。如果 mousePressed() 函数并未有被定义,touchStarted() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "mouseReleased": {
        +      "description": "mouseReleased() 函数将在每次滑鼠键被释放时被调用。如果 mouseReleased() 函数并未有被定义,touchEnded() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "mouseClicked": {
        +      "description": "mouseClicked() 函数将在滑鼠键被按下然后被释放后被调用。<br><br>不同浏览器处理滑鼠点击的方式不大一样,所以这函数只有在滑鼠左键被点击时才保证会被触发。如果想要处理其他滑鼠键的点击或释放事件,请参考 mousePressed() 或 mouseReleased()。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "doubleClicked": {
        +      "description": "doubleClicked() 函数将在 dblclick 事件被触发式被调用,dblclick 时间是 DOM L3 规范的一部分。doubleClicked 将在滑鼠键(通常为左键)连续两次在同样一个元素上点击时被触发。以知更多详情请参考 Mozilla 的参考文献:<a href='https://developer.mozilla.org/en-US/docs/Web/Events/dblclick'>https://developer.mozilla.org/en-US/docs/Web/Events/dblclick</a>。"
        +    },
        +    "mouseWheel": {
        +      "description": "mouseWheel() 函数将在每次直向滑鼠滚轮事件被触发式被调用,可以由实际的滑鼠滚轮或摸板触发。<br><br>event.delta 属性将返回滑鼠滚轮所滚动的量。这值可以是正数或负数,取决于滚动的方向(在 OS X 如果启用“自然”滚屏方向,正反方向将相反)。",
        +      "returns": ""
        +    },
        +    "touches": {
        +      "description": "touches[] 系统变量将储存一个含有现在所有触动点相对于画布 (0, 0) 位置的位置数组,及分辨个别触动点移动时的 ID。数组内的每个元素都会有 x、y 及 id 属性。<br><br>touches[] 数组并不受 Safari 及 IE 移动设备(包括手提电脑)所支持。",
        +      "returns": ""
        +    },
        +    "touchStarted": {
        +      "description": "touchStarted() 函数将在每次触动事件被触发时被调用。如果 touchStarted() 函数并未有被定义,mousePressed() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "touchMoved": {
        +      "description": "touchMoved() 函数将在每次触点移动事件被触发时被调用。如果 touchMoved() 函数并未有被定义,mouseDragged() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "touchEnded": {
        +      "description": "touchEnded() 函数将在每次触动结束时被调用。如果 touchEnded() 函数并未有被定义,mouseReleased() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "returns": ""
        +    },
        +    "createImage": {
        +      "description": "创造一个新的 p5.Image 物件(储存图像的数据类型)。这将提供一个全新的像素缓冲供您使用。缓冲区的大小将由所提供的宽度和高度参数决定。<br><br>.pixels 将提供一个含有所有像素资料的数组。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。请参考 .pixels 文献。您也能使用更简单的 set() 或 get()。<br><br>在获取一个图像的像素之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。",
        +      "params": ["整数:像素宽度",
        +                 "整数:像素宽度"],
        +      "returns": "p5.Image:p5.Image 物件"
        +    },
        +    "saveCanvas": {
        +      "description": "将现有的画布储存成图像。In Safari, this will open the image in the window and the user must provide their own filename on save-as. Other browsers will either save the file immediately, or prompt the user with a dialogue window.",
        +      "params": ["p5.Element|HTMLCanvasElement:una variable representando un canvas HTML5 específico (opcional)",
        +                 "字符串",
        +                 "字符串:'jpg' 或 'png'"],
        +      "returns": ""
        +    },
        +    "saveFrames": {
        +      "description": "捕捉一系列可用于制作影响的影格图像。接受回调函数。比如说,您可能想要将影格传送至伺服器以方便储存或转变成影像。如果回调函数没有被提供,浏览器将弹出储存文件对话框以尝试下载所有刚被创造的图像。如果提供回调函数,图像资料默认上并不会被储存而是以物件数组的形式被转送至回调函数做参数,数组大小为储存影格的总数。",
        +      "params": ["字符串",
        +                 "字符串:'jpg' 或 'png'",
        +                 "数字:该捕捉的影格的秒数",
        +                 "数字:捕捉影格的帧率",
        +                 "函数(数组):一个用来处理图像资料的回调函数。此函数将会被给予一个数组为参数。此数组将会储存所定义的捕捉影格物件。每一个物件都会有三个属性:imageData - 为 image/octet-stream 类型、filename 及 extension。"],
        +      "returns": ""
        +    },
             "loadImage": {
               "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.",
               "params": ["문자열: 불러올 이미지 경로",
        @@ -263,7 +1002,805 @@
               "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"]
             }
           },
        -  "p5.Image": {
        +    "tint": {
        +      "description": "定义显示图像的填色值。图像能着色成所定义的颜色或提供透明度值以使其透明化。<br><br>如想是图像透明化但不想影响其颜色,可使用白色为着色值并定义透明度值。比如说,tint(255, 128) 将会使一个图像成为 50% 透明(假设为默认透明度范围 0-255,可使用 colorMode() 调整)。<br><br>灰阶值参数必须低于或等于当时 colorMode() 所定义的最高值。默认最高值为 255。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值,需在被定义的范围内",
        +                 "数字:蓝彩值或亮度值,需在被定义的范围内",
        +                 "数字:",
        +                 "字符串:颜色字符串",
        +                 "数字:灰阶值",
        +                 "数字[]:一个有红、绿、蓝及透明度值的数组",
        +                 "p5.Color:着色色值"],
        +      "returns": ""
        +    },
        +    "noTint": {
        +      "description": "移除当时显示图像的填色值并将其恢复成显示图形的原色调。",
        +      "returns": ""
        +    },
        +    "imageMode": {
        +      "description": "定义图像模式。更改 image() 解读参数的方式以更改图像开始绘制的位置。默认模式为 imageMode(CORNER),此模式将解读第二及第三个参数为图像的左上角位置。如果加多两个参数,它们则被用来定义图像的宽度和高度。<br><br>imageMode(CORNERS) 将使 image() 函数解读第二及第三个参数为一个角落的位置,而第四个第五个参数为对面角落的位置。<br><br>imageMode(CENTER) 将使 image() 函数解读第二及第三个参数为图像的中心点。如果提供多两个参数,它们将被用来定义图像的宽度和高度。",
        +      "params": ["常量:CORNER、CORNERS 或 CENTER"],
        +      "returns": ""
        +    },
        +    "pixels": {
        +      "description": "此数组为一个储存显示窗口内所有像素值的 Uint8ClampedArray。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。视网膜显示及其他高密度显示器将会有更多像素(pixelDensity^2 倍)。比如说,如果图像为 100x100 像素,总共会有 40,000 个元素在 pixels[] 数组内。而在一个视网膜显示,将会有 160,000 个元素。<br><br>数组内最初四个值(指数 0-3)将会是在坐标 (0, 0) 的像素的 R、G、B、A 值。下四个值(指数 4-7)将会是在坐标 (1, 0) 的像素的 R、G、B、A 值。一般上,如果要设置像素 (x, y) 的值: <pre>CODE BLOCK PENDING</pre> 虽然以上的方式有点复杂,它能提供足够的弹性以应对任何像素密度的显示。注意 set() 将会自动处理设定所有在任何像素密度下 (x, y) 坐标在 pixels[] 内的值,不过程序性能可能在像素数组被更改很多次时时不佳。<br><br>在使用这个数组之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。<br><br>注意这不是个普通的 Javascript 数组。这表示 Javascript 数组函数如 <code>slice()</code> 或 <code>arrayCopy()</code> 将不会有效果。",
        +      "returns": ""
        +    },
        +    "blend": {
        +      "description": "将一个图像内一个区域的像素复制去另一个图像,同时使用所定义的混合模式执行复制。",
        +      "params": ["p5.Image:原图像",
        +                 "整数:原图像的左上角 x 坐标",
        +                 "整数:原图像的左上角 y 坐标",
        +                 "整数:原图像的宽度",
        +                 "整数:原图像的高度",
        +                 "整数:终点图像左上角的 x 坐标",
        +                 "整数:终点图像左上角的 y 坐标",
        +                 "整数:终点图像的宽度",
        +                 "整数:终点图像的高度",
        +                 "常量:混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL。"],
        +      "returns": ""
        +    },
        +    "copy": {
        +      "description": "将画布内一个区域的像素复制去画布内另外一个区域同时也复制一个由 srcImg 参数所定义的图像内一个区域的像素去定义 srcImage 的画布上,这将是原图像。如果原图像与重点区域的大小不同,它将会自动缩放原图像的像素以符合所定义的终点区域。",
        +      "params": ["p5.Image:原图像",
        +                 "整数:原图像的左上角 x 坐标",
        +                 "整数:原图像的左上角 y 坐标",
        +                 "整数:原图像的宽度",
        +                 "整数:原图像的高度",
        +                 "整数:终点图像左上角的 x 坐标",
        +                 "整数:终点图像左上角的 y 坐标",
        +                 "整数:终点图像的宽度",
        +                 "整数:终点图像的高度"],
        +      "returns": ""
        +    },
        +    "filter": {
        +      "description": "在画布上使用过滤器。<br><br>预设选择为:<br><br>THRESHOLD 将图像转换成黑与白像素,取决于它们是否高于或低于所定义的 level 参数值。参数值必须在 0.0(黑色)与 1.0(白色)之间。如果并没有提供参数的话,默认将设为 0.5。<br><br>GRAY 将图像内的颜色转换成灰阶色。不使用任何参数。<br><br>OPAQUE 设置所有透明度值成完全不透明。不使用任何参数。<br><br>INVERT 设置每个像素成其反值。不使用任何参数。<br><br>POSTERIZE 将限制每个图像的彩色通道至参数所定义的颜色数。参数值可以介于 2 至 255 之间,但是效果会在较低值是比较明显。<br><br>BLUR 将使用 level 参数所定义的模糊度执行高斯模糊。如果没有提供参数,模糊度为高斯模糊半径为 1。越大的值越模糊。<br><br>ERODE 减少亮区。不使用任何参数。<br><br>DILATE 增加亮区。不使用任何参数。",
        +      "params": ["常量:THRESHOLD、GRAY、OPAQUE、INVERT、POSTERIZE、BLUR、ERODE、DILATE 或 BLUR。",
        +                 "数字:每个过滤器独有的可选性参数,请看以上"],
        +      "returns": ""
        +    },
        +    "get": {
        +      "description": "返回任何像素值的一个为 [R,G,B,A] 的数组或捕捉图像的一部分。如果没有提供任何参数,将会返回整个图像。可使用 x 及 y 参数以取得一个像素的值。多加定义 w 及 h 参数可取的显示窗口的一部分。当在取得图像时,x 及 y 参数将定义图像的左上角坐标值,无论当时的图像模式为何。<br><br>如果欲取得的像素在图像外,将返回 [0,0,0,255]。以取得根据当时的颜色值范围及颜色模式的数字,请使用 getColor 而不是 get。<br><br>使用 get(x, y) 以取得一个像素的颜色相对来说简单,但是其速度并没有直接从 pixels[] 数组获取数据来的快。与使用 get(x, y) 有相同的效果但使用 pixels[] 及像素密度 d 的范例如下 <code>var x, y, d; // 设置这为坐标 var off = (y width + x) d * 4; var components = [ pixels[off], pixels[off + 1], pixels[off + 2], pixels[off + 3] ]; print(components);</code><br><br>请参考 pixels[] 文献以知更多详情。",
        +      "params": ["数字:像素的 x 坐标",
        +                 "数字:像素的 y 坐标",
        +                 "数字:宽度",
        +                 "数字:高度"],
        +      "returns": "数字[]|p5.Image:在 x,y 的像素值数组或 p5.Image"
        +    },
        +    "loadPixels": {
        +      "description": "将显示窗口的像素资料加载到 pixels[] 数组里。这函数必须在读写 pixels[] 之前被调用。注意只有使用 set() 或直接修改 pixels[] 的改变会发生。",
        +      "returns": ""
        +    },
        +    "set": {
        +      "description": "改变任何像素的颜色,或直接在显示窗口内绘画一个图像。<br><br>x 及 y 参数用于定义该改变的像素而 c 参数用于定义颜色值。这可以是一个 p5.Color 物件或一个 [R, G, B, A] 像素数组。它也能是一个灰阶值。在设定一个图像时,x 及 y 参数将定义图像左上角的坐标值,无论当时的图像模式为何。<br><br>在使用 set() 后,您必须调用 updatePixels() 以使您的改变生效。这应该在所有像素都被设定后才被调用,而且也必须在调用 get() 或绘制图像之前调用。<br><br>使用 set(x, y) 设置一个像素的颜色相对来说简单,但使其速度并没有直接将数据写在 pixels[] 数组里来的快。直接使用 pixels[] 设置像素值可能在使用视网膜显示器时比较复杂,不过它会在每一个循环有很多像素需要被设定时表现得更好。<br><br>请参考 pixels[] 文献以知更多详情。",
        +      "params": ["数字:像素的 x 坐标",
        +                 "数字:像素的 y 坐标",
        +                 "数字|数字[]|物件:插入一个灰阶值 | 一个像素数组 | 一个 p5.Color 物件 | 一个用于复制的 p5.Image"],
        +      "returns": ""
        +    },
        +    "updatePixels": {
        +      "description": "使用 pixels[] 数组内的资料更新显示窗口。通常与 loadPixels() 一起使用。如果您只需从该数组中读取像素资料,您不需要调用 updatePixels() — 更新只有在进行更改时需要被调用。updatePixels() 应该在像素数组被更改或 set() 被调用时使用,只有使用 set() 或直接修改 pixels[] 的改变会发生。",
        +      "params": ["数字:欲更新的区域的左上角 x 坐标",
        +                 "数字:欲更新的区域的左上角 y 坐标",
        +                 "数字:欲更新的区域的宽度",
        +                 "数字:欲更新的区域的高度"],
        +      "returns": ""
        +    },
        +    "loadFont": {
        +      "description": "从一个文件或网址加载一个 opentype 字形文件(.otf、.ttf),将返回一个 p5.Font 物件。这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。<br><br>字形的路径应该相对于链接您的绘图的 HTML 文件。从其他 URL 或远程位置加载字形可能会被浏览器的内建安全模式阻止。",
        +      "params": ["字符串:该加载的字形名字或网址",
        +                 "函数:在 loadFont() 完成后该调用的函数",
        +                 "函数:在发生错误时该调用的函数"],
        +      "returns": "p5.Font:p5.Font 物件"
        +    },
        +    "loadJSON": {
        +      "description": "从一个文件或网址加载一个 JSON 文件,将返回一个物件。注意如果该 JSON 文件内涵一个数组,此函数仍然会返回一个以数字为指数的物件。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。JSONP 功能支持是由填充工具所提供而您可以使用第二个参数来定义一个有 JSON 回调定义的物件,只需跟从这里的<a href='https://github.com/camsong/fetch-jsonp'>指示</a>。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "物件:关于 jsonp 设置的设置物件",
        +                 "字符串:\"json\" 或 \"jsonp\"",
        +                 "函数:在 loadJSON() 完成后该执行的函数,返回的数据将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": "物件:JSON 数据"
        +    },
        +    "loadStrings": {
        +      "description": "读取一个文件的内容并使用个别字行创造一个字符串数组。如果文件名被用作第一个参数,如以上范例,该文件必须被储存在绘图文件夹内。<br><br>除此之外,该文件也能从本地电脑任何位置加载,只需使用绝对路径(任何在 Unix 及 Linux 内由 / 开始的路径,或在 Windows 内由驱动器符号开始的路径),又或者任何在网络上的文件网址也能用来当作 filename 参数。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "函数:在 loadStrings() 完成后该执行的函数,返回的数组将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": "字符串[]:字符串数组"
        +    },
        +    "loadTable": {
        +      "description": "读取一个文件的内容并使用其内容创造一个 p5.Table 物件。如果文件名被用作第一个参数,该文件必须被储存在绘图文件夹内。文件名参数也能是一个在网络上的文件的网址。默认上,该文件被假定为以逗号分隔(格式为 CSV)。该表格只会在 ‘header’ 设置被使用时才会寻找标签。<br><br>可使用的设置包括:<ul><li>csv - 将表格解析为逗号分隔值</li><li>tsv - 将表格解析为制表符分隔值</li><li>header - 这表格有标签行</li></ul><br><br>当使用多个设置时,您只需将他们分为个别的参数并使用逗号分隔。例如:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>所有加载及储存的文件都需使用 UTF-8 编码。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。在 preload() 内调用 loadTable() 将保证加载工作会在 setup() 及 draw() 被调用前完成<br><br>在 preload() 外,您可以提供一个回调函数以处理加载物件。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "字符串:\"header\" \"csv\" \"tsv\"",
        +                 "函数:在 loadTable() 完成后该执行的函数,返回的 Table 物件将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": "物件:含有数据的 Table 物件"
        +    },
        +    "loadXML": {
        +      "description": "读取一个文件的内容并使用其内容创造一个 XML 物件。如果文件名被用作第一个参数,该文件必须被储存在绘图文件夹内。<br><br>除此之外,该文件也能从本地电脑任何位置加载,只需使用绝对路径(任何在 Unix 及 Linux 内由 / 开始的路径,或在 Windows 内由驱动器符号开始的路径),又或者任何在网络上的文件网址也能用来当作 filename 参数。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。在 preload() 内调用 loadTable() 将保证加载工作会在 setup() 及 draw() 被调用前完成<br><br>在 preload() 外,您可以提供一个回调函数以处理加载物件。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "函数:在 loadXML() 完成后该执行的函数,返回的 XML 物件将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": "物件:含有数据的 XML 物件"
        +    },
        +    "loadBytes": {
        +      "description": "",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "函数:在 load() 完成后该执行的函数",
        +                 "函数:在发生错误时该执行的函数"],
        +      "returns": "物件:一个 ‘bytes’ 属性将为被加载的缓冲区的物件"
        +    },
        +    "httpGet": {
        +      "description": "执行 HTTP GET 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。这和调用 httpDo(path, 'GET') 的效果一样。‘binary’ 数据类型将会返回一个 Blob 物件,而 ‘arrayBuffer’ 数据类型将会返回一个 ArrayBuffer 并可用来创造类型化数组(如 Uint8Array)。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "字符串:\"json\"、\"jsonp\"、\"binary\"、\"arrayBuffer\"、\"xml\"或\"text\"",
        +                 "物件|布尔值:与请求一起传送的参数资料",
        +                 "函数:在 httpGet() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": ""
        +    },
        +    "httpPost": {
        +      "description": "执行 HTTP POST 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。这和调用 httpDo(path, 'POST') 的效果一样。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "字符串:\"json\"、\"jsonp\"、\"xml\" 或 \"text\"。如果不提供此参数,httpPost() 将尝试猜",
        +                 "物件|布尔值:与请求一起传送的参数资料",
        +                 "函数:在 httpPost() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        +      "returns": ""
        +    },
        +    "httpDo": {
        +      "description": "执行 HTTP 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。<br><br>如果需要更高等的使用法,您可以在第一个参数给予路径而第二个参数给予一个物件,物件内容设置与 Fetch API 规范的一样。",
        +      "params": ["字符串:该加载的文件名或网址",
        +                 "字符串:\"GET\"、\"POST\" 或 \"PUT\",默认为 \"GET\"",
        +                 "字符串:\"json\"、\"jsonp\"、\"xml\" 或 \"text\"",
        +                 "物件|布尔值:与请求一起传送的参数资料",
        +                 "函数:在 httpDo() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        +                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数",
        +                 "物件:Request 物件,请参考 “fetch” API <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>文献</a>以了解可使用设置"],
        +      "returns": ""
        +    },
        +    "createWriter": {
        +      "description": "",
        +      "params": ["字符串:该创造的文件的名",
        +                 "字符串:"]
        +    },
        +    "save": {
        +      "description": "储存一个图像、文字、JSON、csv、wav 或 html 文件。将提示客户电脑下载文件。<b>注意 save() 函数不建议在正在循环执行的 draw 函数内使用,因为每一次被调用 save() 函数将会弹出一个储存对话框。</b><br><br>默认上此函数将储存画布成一个图像。您也可以选择定义一个文件名。例如:<pre>CODE BLOCK PENDING</pre>除此之外,第一个参数也能是个画布 p5.Element 的对象、字符串数组、JSON 数组、JSON 物件、p5.Table、p5.Image 或 p5.SoundFile(需要 p5.sound)。第二个参数为文件名(包括扩展名)。第三个参数适用于特别给这一类物件的设定。这函数将会储存一个符合给予的参数的文件。例如:<pre>CODE BLOCK PENDING</pre>",
        +      "params": ["物件|字符串:如果所提供的是文件名,此函数将会使用该文件名加上 png 或 jpg 文件扩展名来储存画布为一个图像。如果所提供的是物件,此函数则会一物件所定义的方式储存文件(请参考以上范例)。",
        +                 "字符串:如果所提供的第一个参数为物件,那第二个参数则定义文件名,同时必须包括适当的文件扩展名(请参考以上范例)。",
        +                 "布尔值|字符串:依文件类型而定的设定。比如说,在储存 JSON 时,true 表示输出文件将会针对文件大小进行优化,而同时牺牲可读性。"],
        +      "returns": ""
        +    },
        +    "saveJSON": {
        +      "description": "将一个数组或 JSON 物件的内容写进一个 .json 文件内。文件的储存方式及地点在不同浏览器之间有所不同。",
        +      "params": ["数组|物件:",
        +                 "字符串:",
        +                 "布尔值:如果为 true,将移除输出文件内的换行符及空格以优化文件大小(但牺牲可读性)"],
        +      "returns": ""
        +    },
        +    "saveStrings": {
        +      "description": "将一个字符串数组写进一个文字文件内,每一行为每一组字符串。文件的储存方式及地点在不同浏览器之间有所不同。",
        +      "params": ["字符串[]:该输出的字符串数组",
        +                 "字符串:输出文件的名字",
        +                 "字符串:文件扩展名"],
        +      "returns": ""
        +    },
        +    "saveTable": {
        +      "description": "将一个表格(Table)物件的内容写进一个文件内。默认将储存为逗号分隔值('csv')的文字文件但也可以使用制表符分隔('tsv')或生成一个 HTML 表格('html')。文件的储存方式及地点在不同浏览器之间有所不同。",
        +      "params": ["p5.Table:该储存在文件内的表格物件",
        +                 "字符串:储存表格文件的名字",
        +                 "字符串:可以是 \"tsv\"、\"csv\" 或 \"html\""],
        +      "returns": ""
        +    },
        +    "p5.Table": {
        +      "description": "Los objetos Table almacenan datos con múltiples filas y columnas, tal como una hoja de cálculo tradicional. Los objetos Table pueden ser generados desde cero, dinámicamente, o usando datos desde un archivo existente.",
        +      "params": ["Arreglo: un arreglo de objetos p5.TableRow"],
        +      "returns": "p5.Table: 该 p5 物件.Table generado"
        +    },
        +    "p5.TableRow": {
        +      "description": "Un objeto TableRow representa una única fila de datos, grabados en columnas, de una tabla. Un objeto TableRow contiene tanto un arreglo ordenado, como un objeto JSON desordenado.",
        +      "params": ["String: opcional, puebla la fila con una serie de valores, separados por el separador",
        +      "String: por defecto, valores separados por coma (csv)"],
        +      "returns": "该 p5 物件"
        +    },
        +    "day": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,day() 函数将返回当天的日期天数在 1 - 31 的范围内。",
        +      "returns": "整数:当天的日期天数"
        +    },
        +    "hour": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,hour() 函数将返回当时时间的小时数在 0 - 23 的范围内。",
        +      "returns": "整数:当时时间的小时数"
        +    },
        +    "minute": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,minute() 函数将返回当时时间的分钟数在 0 - 59 的范围内。",
        +      "returns": "整数:当时时间的分钟数"
        +    },
        +    "millis": {
        +      "description": "返回自程序开始以来的毫秒(一秒的一千分之一)数。这资料一般可用于定时事件及动画序列。",
        +      "returns": "整数:自程序开始以来的毫秒数"
        +    },
        +    "month": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,month() 函数将返回当天的日期月数在 1 - 12 的范围内。",
        +      "returns": "整数:当时日期的月数"
        +    },
        +    "second": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,second() 函数将返回当时时间的秒数在 0 - 59 的范围内。",
        +      "returns": "整数:当时时间的秒数"
        +    },
        +    "year": {
        +      "description": "p5.js 将与您的电脑的时钟沟通,year() 函数将返回当天的日期年数为一个整数(2014、2015、2016等等)。",
        +      "returns": "整数:当时日期的年数"
        +    },
        +    "p5.XML": {
        +      "description": "XML es una representación de un objeto XML, capaz de procesar código XML. Usa loadXML() para cargar archivos externos XML y crear objetos XML",
        +      "params": ["String:"],
        +      "returns": "p5.XML: 该 p5 物件.XML generado"
        +    },
        +    "createVector": {
        +      "description": "创造一个新的 p5.Vector 向量(用以储存向量的数据类型)。此函数将提供一个二维或三维的向量,准确来说一个欧几里得(也称为几何)向量。向量为一个有大小及方向的量。",
        +      "params": ["数字:该向量的 x 分量",
        +                 "数字:该向量的 y 分量",
        +                 "数字:该向量的 z 分量"],
        +      "returns": "p5.Vector"
        +    },
        +    "p5.Vector": {
        +      "description": "Una clase para describir un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección. El tipo de datos, sin embargo, graba los componentes del vector (x, y para 2D y x,y,z para 3D). La magnitud y la dirección pueden ser calculados con los métodos mag() y heading(). En muchos de los ejemplos de p5.js, verás que p5.Vector es usado para describir una posición, velocidad o aceleración. Por ejemplo, si consideras un rectángulo moviéndose a lo largo de la pantalla, en cada instante tiene una posición (un vector que apunta desde el origen hasta su ubicación), una velocidad(la tasa a la que la posición del objeto cambia por unidad de tiempo, expresada como vector), y aceleración (la tasa a la que la velocidad del objeto cambia por unidad de tiempo, expresada como vector). Como los vectores representan grupos de valores, no podemos simplemente usar las operaciones tradicionales de adición, multiplicación, etc. En vez de eso, necesitaremos hacer matemática de vectores, lo que es simplificado con los métodos dentro de la clase p5.Vector.",
        +      "params": ["Número: componente x del vector",
        +                 "Número: componente y del vector",
        +                 "Número: componente z del vector"],
        +      "returns": "该 p5 物件"
        +    },
        +    "abs": {
        +      "description": "计算一个数字的绝对值(大小值)。映射到 Math.abs()。一个数字的绝对值一定是个正数。",
        +      "params": ["数字:用于计算的数字"],
        +      "returns": "数字:被给予数字的绝对值"
        +    },
        +    "ceil": {
        +      "description": "计算最靠近并大于或等于参数值的整数。映射到 Math.ceil()。比如说,ceil(9.03) 将返回 10。",
        +      "params": ["数字:该取整的数字"],
        +      "returns": "整数:取整后的数字"
        +    },
        +    "constrain": {
        +      "description": "限制一个数字于最低值与最高值之间。",
        +      "params": ["数字:该限制的数字",
        +                 "数字:最低值",
        +                 "数字:最高值"],
        +      "returns": "数字:被限制后的数字"
        +    },
        +    "dist": {
        +      "description": "计算两点之间的距离。",
        +      "params": ["数字:第一个点的 x 坐标",
        +                 "数字:第一个点的 y 坐标",
        +                 "数字:第二个点的 x 坐标",
        +                 "数字:第二个点的 y 坐标",
        +                 "数字:第一个点的 z 坐标",
        +                 "数字:第二个点的 z 坐标"],
        +      "returns": "数字:两点之间的距离"
        +    },
        +    "exp": {
        +      "description": "返回欧拉数 e (2.71828...)提升到由参数 n 定义的指数。映射到 Math.exp()。",
        +      "params": ["数字:该提升的指数"],
        +      "returns": "数字:e^n"
        +    },
        +    "floor": {
        +      "description": "计算最靠近并小于或等于参数值的整数。映射到 Math.floor()。",
        +      "params": ["数字:该取整的数字"],
        +      "returns": "整数:取整后的数字"
        +    },
        +    "lerp": {
        +      "description": "计算一个介于两个数字之间所定义的插值量位置的数字。amt 参数为两个值之间的插值量,0.0 为第一个值,0.1 为非常接近第一个值,0.5 为两者之间等等。lerp 函数可用来沿着直线制作动画及绘制虚线。",
        +      "params": ["数字:第一个值",
        +                 "数字:第二个值",
        +                 "数字:介于 0.0 与 1.0 之间的数字"],
        +      "returns": "数字:插值"
        +    },
        +    "log": {
        +      "description": "计算一个数字的自然对数(e 为底数的对数)。这函数需要 n 参数大于 0.0。映射到 Math.log()。",
        +      "params": ["数字:大于 0 的数字"],
        +      "returns": "数字:n 的自然对数"
        +    },
        +    "mag": {
        +      "description": "计算一个向量的大小(或长度)。向量为一个空间内的方向,通常用于电脑图形及线性代数。因为它没有“开始”位置,一个向量的大小可以被想成是 0,0 坐标与向量 x,y 坐标之间的距离。因此,mag() 是 dist(0, 0, x, y) 的缩写。",
        +      "params": ["数字:第一个值",
        +                 "数字:第二个值"],
        +      "returns": "数字:从 (0, 0) 至 (a, b) 的向量的大小"
        +    },
        +    "map": {
        +      "description": "从一个范围内映射一个数字去另一个范围。<br><br>在以上第一个范例,25 被从 0 至 100 之间的范围映射去窗口最左方 (0) 至最右方 (width) 的范围内。",
        +      "params": ["数字:该转换的值",
        +                 "数字:现在值的最低值",
        +                 "数字:现在值的最低值",
        +                 "数字:目标值的最低值",
        +                 "数字:目标值的最高值",
        +                 "布尔值:限制目标值在最高及最低值之间"],
        +      "returns": "数字:映射后的数字"
        +    },
        +    "max": {
        +      "description": "找出一系列数字中最大的值,并返回该值。max() 能接受任何数量的数字参数,或是一个任何大小的数组。",
        +      "params": ["数字:用于比较的数字",
        +                 "数字:用于比较的数字",
        +                 "数字[]:用于比较的数字"],
        +      "returns": "数字:最高值的数字"
        +    },
        +    "min": {
        +      "description": "找出一系列数字中最小的值,并返回该值。min() 能接受任何数量的数字参数,或是一个任何大小的数组。",
        +      "params": ["数字:用于比较的数字",
        +                 "数字:用于比较的数字",
        +                 "数字[]:用于比较的数字"],
        +      "returns": "数字:最低值的数字"
        +    },
        +    "norm": {
        +      "description": "将一个数字由一个范围标准化成介于 0 及 1 之间的值。与 map(value, low, high, 0, 1) 的效果相同。在范围外的数字将不会被限制在 0 与 1 之间,因为范围外的值通常是有意及有用的。(参考以上第二个范例)",
        +      "params": ["数字:该标准化的值",
        +                 "数字:现在值的最低值",
        +                 "数字:现在值的最高值"],
        +      "returns": "数字:标准化后的数字"
        +    },
        +    "pow": {
        +      "description": "执行幂运算。pow() 函数是个能有效率地将数字大量乘于自己(或其倒数)的方式。比如说,pow(3, 5) 等同于 3*3*3*3*3 而 pow(3, -5) 等同于 1 / (3*3*3*3*3)。映射到 Math.pow()。",
        +      "params": ["数字:幂运算的底数",
        +                 "数字:幂运算的指数"],
        +      "returns": "数字:n^e"
        +    },
        +    "round": {
        +      "description": "计算最靠近 n 参数的整数。比如说,round(133.8) 将返回 134。映射到 Math.round()。",
        +      "params": ["数字:该取整的数字"],
        +      "returns": "整数:取整后的数字"
        +    },
        +    "sq": {
        +      "description": "平方一个数字(将数字乘于自己)。结果一定是个正数,因为将两个负数相乘一定会有一个正数结果。比如说 -1 * -1 = 1。",
        +      "params": ["数字:该平方的数字"],
        +      "returns": "数字:平方后的数字"
        +    },
        +    "sqrt": {
        +      "description": "计算一个数字的平方根。一个数字的平方根一定是个正数,虽然也可能有正确的负数平方根。一个数字 a 的平方根 s 有以下属性 s*s = a。此函数为取平方的相反。映射到 Math.sqrt()。",
        +      "params": ["数字:该取平方根的非负数"],
        +      "returns": "数字:取平方根后的数字"
        +    },
        +    "noise": {
        +      "description": "返回所定义坐标的柏林噪声值。柏林噪声是个用来生成比 random() 所能生成更自然及更谐波的随机数字系列。在 1980 年代有 Ken Perlin 所发明,柏林噪声至今常被用在图形应用程序中生成程序纹理、自然运动、形状、地形等等。<br><br>柏林噪声与 random() 函数最主要的不同点在于前者是在一个无限的 n 维空间内定义的,这空间内每一对坐标都相对于一个固定的半随机值(只有在程序进行时为固定的;请参考 noiseSeed() 函数)。p5.js 能计算 1 维、2 维及 3 维噪声,这取决于所给予的坐标数。返回的值一定会在 0.0 至 1.0 之间。噪音值可以通过在噪音空间内移动以制成动画,如以上范例所示。第二及第三个空间维度也能被解读成时间。<br><br>所生成的噪音结构上和一般音频信号相似,尤其是此函数的频率。与物理学上谐波的概念相似,泊林噪音也是在计算几个八度后再将其结果加起来以得到最后的结果。<br><br>另外一个控制返回随机数系列的特征的方法是控制输入坐标值的大小。因为此函数能在无限之的空内内应用,输入坐标的值并不重要,只有个别坐标之间的距离需要被注意(如在循环内使用 noise() 时)。一般来说坐标之间的距离越小,生成噪声随机数列将会越平滑。介于 0.005-0.03 之间的距离应该适合大多数应用场合,不过这可能因应用需求而变。",
        +      "params": ["数字:噪声空间的 x 坐标",
        +                 "数字:噪声空间的 y 坐标",
        +                 "数字:噪声空间的 z 坐标"],
        +      "returns": "数字:柏林噪声在特定坐标的值(介于 0 与 1 之间)"
        +    },
        +    "noiseDetail": {
        +      "description": "调整柏林噪声函数所生成的噪声特征及细节度。与物理学上谐波的概念相似,泊林噪音也是在计算几个八度后才得到最后的结果。越低的八度将会影响输出信号值越多因此同时会定义噪音的整体强度,而较高的八度将会在噪音系列中制作更精细的细节。<br><br>默认上,此噪音将使用四个八度计算而每个八度将有其前者一半的影响力,第一个八度的影响力为 50% 。这衰退值能通过加多一个参数而改变。比如说如果衰退因数为 0.75 那表示每个八度将会有其前者的 75% 的影响力(减少 25%)。任何介于 0.0 与 1.0 的值都能被接受,不过注意高于 0.5 的值可能会造成 noise() 函数会返回大于 1.0 的值。<br><br>通过改变这些参数,noise() 函数所生成的信号可适应于非常特别的需求或特点。",
        +      "params": ["数字:噪音该使用的八度数",
        +                 "数字:每个八度的衰退因数"],
        +      "returns": ""
        +    },
        +    "noiseSeed": {
        +      "description": "定义 noise() 使用的随机种子值。默认上,noise() 将在每一次改程序被执行时生成不同的结果。只需定义 value 参数至一个常量就能确保每一次软件执行时都会返回一样的随机数列。",
        +      "params": ["数字:随机种子值"],
        +      "returns": ""
        +    },
        +    "acos": {
        +      "description": "cos() 的反值,将返回一个值的反余弦值。此函数接受介于 -1 与 1 之间的值并将返回介于 0 与 PI(3.1415927)之间的值。",
        +      "params": ["数字:该取反余弦值的值"],
        +      "returns": "数字:该值的反余弦值"
        +    },
        +    "asin": {
        +      "description": "sin() 的反值,将返回一个值的反正弦值。此函数接受介于 -1 与 1 之间的值并将返回介于 -PI/2 与 PI/2 之间的值。",
        +      "params": ["数字:该取反正弦值的值"],
        +      "returns": "数字:该值的反正弦值"
        +    },
        +    "atan": {
        +      "description": "tan() 的反值,将返回一个值的反正切值。此函数接受介于 -Infinity 与 Infinity(包括 Infinity)之间的值并将返回介于 -PI/2 与 PI/2 之间的值。",
        +      "params": ["数字:该取反正切值的值"],
        +      "returns": "数字:该值的反正切值"
        +    },
        +    "atan2": {
        +      "description": "计算从一个被定义的点到坐标原点的弧度,并由正 x 轴开始计算。将返回介于 PI 与 -PI 之间的浮点数。atan2() 函数通常用于定向几何图形至鼠标的位置。<br><br>注意:第一个参数为 y 坐标,而第二个参数为 x 坐标,这是为了适应计算正切值的结构。",
        +      "params": ["数字:该点的 y 坐标",
        +                 "数字:该点的 x 坐标"],
        +      "returns": "数字:该点的反正切值"
        +    },
        +    "cos": {
        +      "description": "计算一个角度的余弦值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        +      "params": ["数字:角度"],
        +      "returns": "数字:该角度的余弦值"
        +    },
        +    "sin": {
        +      "description": "计算一个角度的正弦值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        +      "params": ["数字:角度"],
        +      "returns": "数字:该角度的正弦值"
        +    },
        +    "tan": {
        +      "description": "计算一个角度的正切值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        +      "params": ["数字:角度"],
        +      "returns": "数字:该角度的正切值"
        +    },
        +    "degrees": {
        +      "description": "将一个弧度值转换成其相对的角度值。弧度和角度为两个测量同样一个东西的方法。一个圆形里有 360 度而也有 2*PI 个弧度。比如说,90° = PI/2 = 1.5707964。此函数将不会使用当时的角度模式。",
        +      "params": ["数字:由弧度转换成角度的值"],
        +      "returns": "数字:转换后的角度值"
        +    },
        +    "radians": {
        +      "description": "将一个角度值转换成其相对的弧度值。弧度和角度为两个测量同样一个东西的方法。一个圆形里有 360 度而也有 2*PI 个弧度。比如说,90° = PI/2 = 1.5707964。此函数将不会使用当时的角度模式。",
        +      "params": ["数字:由角度转换成弧度的值"],
        +      "returns": "数字:转换后的角度值"
        +    },
        +    "angleMode": {
        +      "description": "定义当时 p5 的角度模式。默认模式为 RADIANS(弧度)。",
        +      "params": ["常量:RADIANS 或 DEGREES"],
        +      "returns": ""
        +    },
        +    "randomSeed": {
        +      "description": "定义 random() 使用的随机种子值。<br><br>默认上,random() 将在每一次改程序被执行时生成不同的结果。只需定义 seed 参数至一个常量就能确保每一次软件执行时都会返回一样的伪随机数。",
        +      "params": ["数字:随机种子值"],
        +      "returns": ""
        +    },
        +    "random": {
        +      "description": "返回一个随机的浮点数。<br><br>可使用 0、1 或 2 个参数。<br><br>如果并没有定义任何参数,将返回一个介于 0 与 1(但不包括 1)的随机数。<br><br>如果只定义一个参数并且该参数为数字,将返回一个介于 0 与 该数字(但不包括该数字)的随机数。<br><br>如果值定义一个参数并且该参数为数组,将返回该数组中随机一个元素。<br><br>如果定义两个参数,将返回一个介于第一个参数与第二个参数(但不包括第二个参数)的随机数。",
        +      "params": ["数字:最低值(包括此值)",
        +                 "数字:最高值(不包括此值)",
        +                 "数组:供选择的数组"],
        +      "returns": "数字:随机数"
        +    },
        +    "randomGaussian": {
        +      "description": "返回一个符合高斯,或正态,分布的随机数。理论上 randomGaussian() 没有最高或最低返回值。不过,差均值很多的值被返回的机率将会很低;而接近均质的值被返回的机率将会相对较高。<br><br>可使用 0、1 或 2 个参数。<br>如果并没有定义任何参数,将使用均值为 0 与 标准差为 1。<br>如果只定义一个参数,该参数将为均值(标准差为 1)。<br>如果定义两个参数,第一个参数为均值,第二个参数为标准差。",
        +      "params": ["数字:均值",
        +                 "数字:标准偏差"],
        +      "returns": "数字:随机数"
        +    },
        +    "textAlign": {
        +      "description": "定义绘制问题的对齐方向。使用两个参数:horizAlign(LEFT、CENTER 或 RIGHT)及 vertAlign(TOP、BOTTOM、CENTER 或 BASELINE)。<br><br>horizAlign 参数为 text() 函数的 x 值,而 vertAlign 参数为 y 值。<br><br>因此如果您使用 textAlign(LEFT),您将会使文字最左方对齐 text() 函数所使用的 x 参数。如果您使用 textAlign(RIGHT, TOP),您将会使文字最右方对齐 x 值而文字最上方对齐 y 值。",
        +      "params": ["常量:水平对齐,LEFT、CENTER 或 RIGHT",
        +                 "常量:垂直对齐,TOP、BOTTOM、CENTER 或 BASELINE"],
        +      "returns": ""
        +    },
        +    "textLeading": {
        +      "description": "定义或获取行与行之间的像素距离。此设置将会在所有接下来的 text() 函数调用时生效。",
        +      "params": ["数字:行与行之间的像素距离"],
        +      "returns": ""
        +    },
        +    "textSize": {
        +      "description": "定义或获取当时的字体大小。这大小将会在所有接下来的 text() 函数调用时生效。字形大小是使用像素定义。",
        +      "params": ["数字:字体的像素大小"],
        +      "returns": ""
        +    },
        +    "textStyle": {
        +      "description": "定义或获取系统字体的风格,可以是 NORMAL、ITALIC 或 BOLD。注意:这可能被 CSS 风格所覆盖。至与非系统字体(opentype、truetype 等)请直接加载已风格化的字体。",
        +      "params": ["常量:字体的风格,可以是 NORMAL、ITALIC 或 BOLD"],
        +      "returns": ""
        +    },
        +    "textWidth": {
        +      "description": "计算及返回任何字符或字符串的宽度。",
        +      "params": ["字符串:该测量的字符串"],
        +      "returns": "数字"
        +    },
        +    "textAscent": {
        +      "description": "返回当时字体在当时所定的大小的整体高度。这高度代表从基准线算起至最高字体的顶点的距离。",
        +      "returns": "数字"
        +    },
        +    "textDescent": {
        +      "description": "返回当时字体在当时所定的大小的下端线高度。",
        +      "returns": "数字"
        +    },
        +    "text": {
        +      "description": "将文字绘制在荧幕上。显示第一个参数内的资料在荧幕上由其他参数所定义的位置。将会使用默认字形除非使用 textFont() 函数定义使用其他字形同时也将使用默认大小除非使用 textSize() 定义文字大小。文字的颜色可使用 fill() 函数定义。可使用 stroke() 及 strokeWeight() 函数添加文字外形线。<br><br>文字显示将位于 textAlign() 函数所定义的位置,您可将文字绘制在坐标的左边、右边或中间。<br><br>x2 及 y2 参数将定义一个方形文字显示区而且只适用于字符串资料类型。当这两个参数被定义时,它们将使用当时的 rectMode() 设置被解读。不符合方形大小的文字将不会被绘制在荧幕上。",
        +      "params": ["字符串|物件|数组|数字|布尔值:该显示的字母数字符号",
        +                 "数字:文字的 x 坐标",
        +                 "数字:文字的 y 坐标",
        +                 "数字:默认上,文字格的宽度,请参考 rectMode()",
        +                 "数字:默认上,文字格的高度,请参考 rectMode()"],
        +      "returns": ""
        +    },
        +    "textFont": {
        +      "description": "定义使用 text() 函数绘制文字时该使用的字形。",
        +      "params": ["物件|字符串:一个使用 loadFont() 加载的字形,或一个代表 Web 安全字体(一个所有系统都通用的字形)的字符串",
        +                 "数字:字形大小"],
        +      "returns": ""
        +    },
        +    "p5.Font": {
        +      "description": "Clase base para manipulación de tipografía",
        +      "params": ["物件:puntero a la instancia p5"],
        +      "returns": "该 p5 物件"
        +    },
        +    "append": {
        +      "description": "弃用:append() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>。<br><br>在数组的尾端增加一个值。将增加数组的一个大小。映射到 Array.push()。",
        +      "params": ["数组:该附加到的数组",
        +                 "任何:该附加进数组的元素"],
        +      "returns": ""
        +    },
        +    "arrayCopy": {
        +      "description": "弃用:arrayCopy() 已被弃用并将会在未来的 p5 版本中移除。<br><br>复制一个数组(或该数组的一部分)去另外一个数组。src 数组将会被复制去 dst 数组,开端位置由 srcPosition 参数定义并复制进由 dstPosition 定义的位置。该复制的元素数量由 length 参数定义。注意在复制元素时该元素将覆盖终点数组原有的元素。如果想要添加元素,请使用 use concat()。<br><br>简化版本将只使用两个参数:arrayCopy(src, dst) 将复制整个数组去另一个相同大小的数组。这等同于使用 arrayCopy(src, 0, dst, 0, src.length)。<br><br>使用这函数将比使用 for 循环数组内每一个元素并一一复制来的更有效率。",
        +      "params": ["数组:原数组",
        +                 "数字:在原数组内的开端指数",
        +                 "数组:终点数组",
        +                 "数字:在终点数组内的开端指数",
        +                 "数字:该复制的元素量"],
        +      "returns": ""
        +    },
        +    "concat": {
        +      "description": "弃用:concat() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>。<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
        +      "params": ["数组:串接的第一个数组",
        +                 "数组:串接的第二个数组"],
        +      "returns": "数组:串接后的数组"
        +    },
        +    "reverse": {
        +      "description": "弃用:reverse() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>。<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
        +      "params": ["数组:该倒转的数组"],
        +      "returns": ""
        +    },
        +    "shorten": {
        +      "description": "弃用:shorten() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>。<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
        +      "params": ["数组:该缩短的数组"],
        +      "returns": "数组:缩短后的数组"
        +    },
        +    "shuffle": {
        +      "description": "弃用:shuffle() 已被弃用并将会在未来的 p5 版本中移除。请参考<a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>(英文页面)。<br><br>随机排列数组内的元素。使用 Fisher-Yates 混洗函数。",
        +      "params": ["数组:该混洗的数组",
        +                 "布尔值:修改所给予的数组"],
        +      "returns": "数组:混洗后的数组"
        +    },
        +    "sort": {
        +      "description": "弃用:sort() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>。<br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
        +      "params": ["数组:该排列的数组",
        +                 "整数:该排列的元素数,由 0 开始"],
        +      "returns": ""
        +    },
        +    "splice": {
        +      "description": "弃用:splice() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>。<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
        +      "params": ["数组:拼接进的数组",
        +                 "任何:欲拼接进数组的值",
        +                 "整数:数组内该添加该元素的位置"],
        +      "returns": ""
        +    },
        +    "subset": {
        +      "description": "弃用:subset() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>。<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
        +      "params": ["数组:该提取元素的数组",
        +                 "整数:开始位置",
        +                 "整数:提取元素数"],
        +      "returns": "数组:提取出来的元素数组"
        +    },
        +    "float": {
        +      "description": "将一个字符串转换成其浮点值。字符串内内容必须是数字,不然将返回 NaN(不是数字)。比如说,float(\"1234.56\") 将返回 1234.56,但 float(\"giraffe\") 将返回 NaN。<br><br>当给予一数组的值时,将返回一个等同大小的浮点数组。",
        +      "params": ["字符串:该解析的浮点字符串"],
        +      "returns": "数字:该字符串的浮点值"
        +    },
        +    "int": {
        +      "description": "转换一个布尔值、字符串或浮点值成其整数值。当给予一数组的值时,将返回一个等同大小的整数数组。",
        +      "params": ["字符串|布尔值|数字:该解析的值",
        +                 "整数:该转换成的基数",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的整数值"
        +    },
        +    "str": {
        +      "description": "转换一个布尔值、字符串或数字成其字符串值。当给予一数组的值时,将返回一个等同大小的字符串数组。",
        +      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        +      "returns": "字符串:该值的字符串值"
        +    },
        +    "boolean": {
        +      "description": "转换一个数字或字符串成其布尔值。在数字上,任何非零的值(无论正负)都将转换为 true,而零将转换为 false。在字符串上,\"true\" 将转换成 true,而任何其他值都会转换成 false。当给予一数组的数字或字符串时,将返回一个等同大小的布尔值数组。",
        +      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        +      "returns": "布尔值:该值的布尔值"
        +    },
        +    "byte": {
        +      "description": "转换一个数字、代表数字的字符串或布尔值成其字节值.一个字节只能是一个介于 -128 与 127 之间的整数,因此如果在这范围外的值被转换时,它将会绕回相对的字节值。当给予一数组的数字、字符串或布尔值时,将返回一个等同大小的字节数组。",
        +      "params": ["字符串|布尔值|数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的字节值"
        +    },
        +    "char": {
        +      "description": "转换一个数字或字符串成其单一字符的值。如果提供一个字符串参数,它将会先被解析成整数然后再被转换成单一字符。当给予一数组的数字或字符串时,将返回一个等同大小的单一字符数组。",
        +      "params": ["字符串|数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "字符串:该值的字符串值"
        +    },
        +    "unchar": {
        +      "description": "转换一个单一字符成其整数值。当给予一数组的单一字符值时,将返回一个等同大小的整数数组。",
        +      "params": ["字符串:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的整数值"
        +    },
        +    "hex": {
        +      "description": "转换一个数字成其十六进制值的字符串。如果提供第二个参数,它将被用来定义该生成的十六进制值的字符量。当给予一数组时,将返回一个等同大小的十六进制字符串数组。",
        +      "params": ["数字:该解析的值",
        +                 "数字",
        +                 "数字[]:该解析的值"],
        +      "returns": "字符串:该值的十六进制值"
        +    },
        +    "unhex": {
        +      "description": "转换一个十六进制字符串成其整数值。当给予一数组的十六进制字符串时,将返回一个等同大小的整数数组。",
        +      "params": ["数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该十六进制值的整数值"
        +    },
        +    "join": {
        +      "description": "将一数组的字符串合成一个字符串,每一个元素由 separator 参数定义的字符分隔开。如果要连接整数或浮点数数组,它们必须先使用 nf() 或 nfs() 转换成字符串。",
        +      "params": ["数组:该连接的字符串",
        +                 "字符串:在个元素之间穿插的字符串"],
        +      "returns": "字符串:连接后的字符串"
        +    },
        +    "match": {
        +      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,将返回一个大小为 1 的数组(匹配的文字为数组的第一个元素)。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。正则表达式匹配返回的元素 [0] 将会是整个匹配的字符串,而匹配组合将从元素 [1] 开始(第一组为 [1]、第二组为 [2] 等)。",
        +      "params": ["字符串:在此字符串内搜寻",
        +                 "字符串:用于搜寻的正则表达式"],
        +      "returns": "数组:搜寻到的字符串数组"
        +    },
        +    "matchAll": {
        +      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的二维字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,仍然将返回一个二维数组,但第二维度数组的大小将为一。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个二维数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。假设有一个有计算其变量 i 的循环,正则表达式匹配返回的元素 [i][0] 将会是整个匹配的字符串,而匹配组合将从元素 [i][1] 开始(第一组为 [i][1]、第二组为 [i][2] 等)。",
        +      "params": ["字符串:在此字符串内搜寻",
        +                 "字符串:用于搜寻的正则表达式"],
        +      "returns": "字符串[]:搜寻到的二维字符串数组"
        +    },
        +    "nf": {
        +      "description": "用于将数字格式化成字符串的辅助函数。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点左边的位数",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfc": {
        +      "description": "用于将数字格式化成字符串并在适当的地方添加逗号以示意 1000 位的辅助函数。此函数有两个版本:一个用于格式化整数,另一个用于格式化一数组的整数。参数 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点左边的位数",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfp": {
        +      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \"+\" 号而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfs": {
        +      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \" \"(空格)而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字:该格式化的数字",
        +                 "整数:小数点左边的位数",
        +                 "整数:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "split": {
        +      "description": "split() 函数映射到 String.split(),它使用一个字符或字符串为分隔号以将另一个字符串拆分成多个部分。delim 参数定义用于标示各个部分之间边界的字符或字符串。将返回一个含有各个部分的字符串数组。<br><br>splitTokens() 函数也与此函数相似,不过它将使用一系列字符以拆分字符串而不是使用特别定义的单一字符或字符串。",
        +      "params": ["字符串:还拆分的字符串",
        +                 "字符串:用于分隔资料的字符串"],
        +      "returns": "字符串[]:字符串数组"
        +    },
        +    "splitTokens": {
        +      "description": "splitTokens() 函数将在一个或多个字符(或 “tokens”)所标示的地方拆分一个字符串。delim 参数将定义用于标示各个部分之间边界的字符或字符串。<br><br>如果 delim 参数没有被定义,此函数将使用任何空白字符拆分。空白字符包括制表符(\\t)、换行符(\\n)、回车符(\\r)、新页符(\\f)及空格。",
        +      "params": ["字符串:还拆分的字符串",
        +                 "字符串:用于分隔资料的字符串列"],
        +      "returns": "字符串[]:字符串数组"
        +    },
        +    "trim": {
        +      "description": "从一个字符串的前端及后端删除空白字符。除了一般的空白字符如空格、回车及制表符之外,这函数也将删除 Unicode “nbsp” 字符。",
        +      "params": ["字符串:该修剪的字符串",
        +                 "数组:该修剪的字符串数组"],
        +      "returns": "字符串:修剪后的字符串"
        +    },
        +    "camera": {
        +      "description": "定义在一个三维绘图内相机的位置。此函数的行为与 gluLookAt 相似,不过它会覆盖原有的模型视图矩阵而不会在原有的模型视图上添加任何变形。当没有给予任何参数时,此函数将定义默认相机为 camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);",
        +      "params": ["数字:相机在 x 轴的位置",
        +                 "数字:相机在 y 轴的位置",
        +                 "数字:相机在 z 轴的位置",
        +                 "数字:代表绘图中心点的 x 坐标",
        +                 "数字:代表绘图中心点的 y 坐标",
        +                 "数字:代表绘图中心点的 z 坐标",
        +                 "数字:相机向上方向量的 x 分量",
        +                 "数字:相机向上方向量的 y 分量",
        +                 "数字:相机向上方向量的 z 分量"],
        +      "returns": ""
        +    },
        +    "perspective": {
        +      "description": "定义透视相机。当没有给予任何参数时,此函数将定义默认相机为 perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0) 其中 cameraZ 为 ((height/2.0) / tan(PI60.0/360.0));",
        +      "params": ["数字:相机视锥的垂直视野,使用角度模式单位定义视野底部到顶部的角度",
        +                 "数字:相机视锥的长宽比",
        +                 "数字:视锥近平面的长度",
        +                 "数字:视锥远平面的长度"],
        +      "returns": ""
        +    },
        +    "ortho": {
        +      "description": "定义正射相机。",
        +      "params": ["数字:相机视锥的左平面",
        +                 "数字:相机视锥的右平面",
        +                 "数字:相机视锥的底平面",
        +                 "数字:相机视锥的顶平面",
        +                 "数字:相机视锥的近平面",
        +                 "数字:相机视锥的远平面"],
        +      "returns": ""
        +    },
        +    "ambientLight": {
        +      "description": "使用所定义的颜色创造一个环境光。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值,需在被定义的范围内",
        +                 "数字:蓝彩值或亮度值,需在被定义的范围内",
        +                 "数字:",
        +                 "字符串:颜色字符串",
        +                 "数字:灰阶值",
        +                 "数字[]:一个有红、绿、蓝及透明度值的数组",
        +                 "p5.Color:环境光色"],
        +      "returns": ""
        +    },
        +
        +    "directionalLight": {
        +      "description": "使用所定义的颜色及方向创造一个定向光。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值",
        +                 "数字:蓝彩值或亮度值",
        +                 "p5.Vector:光的方向",
        +                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值",
        +                 "数字:x 轴方向",
        +                 "数字:y 轴方向",
        +                 "数字:z 轴方向"],
        +      "returns": ""
        +    },
        +    "pointLight": {
        +      "description": "使用所定义的颜色及灯光位置创造一个点光源。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值",
        +                 "数字:蓝彩值或亮度值",
        +                 "数字:x 轴方向",
        +                 "数字:y 轴方向",
        +                 "数字:z 轴方向",
        +                 "p5.Vector:光的方向",
        +                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "returns": ""
        +    },
        +    "loadShader": {
        +      "description": "从所定义的顶点及片断着色器文件路径加载自定的着色器。着色器是在背景异步加载的,因此此函数应该在 preload() 内使用。<br><br>现在为止有三种主要的着色器种类。只要相对的参数有在着色器内被定义,p5 将会自动提供相对的顶点、法线、颜色及灯光属性。",
        +      "params": ["字符串:存有顶点着色器源代码的文件的路径",
        +                 "字符串:存有片断着色器源代码的文件的路径"],
        +      "returns": "p5.Shader:由所定义的顶点及片断着色器所创造的着色器物件"
        +    },
        +    "createShader": {
        +      "description": "",
        +      "params": ["字符串:顶点着色器的源代码",
        +                 "字符串:片断着色器的源代码"],
        +      "returns": "p5.Shader:由所定义的顶点及片断着色器所创造的着色器物件"
        +    },
        +    "shader": {
        +      "description": "shader() 函数让其使用者提供自定的着色器以用于在 WEBGL 模式下渲染形状。使用这能使用 loadShader() 加载自定义的着色器。",
        +      "params": ["p5.Shader:欲用于渲染形状用的 p5.Shader"]
        +    },
        +    "normalMaterial": {
        +      "description": "形状的法线材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "returns": ""
        +    },
        +    "texture": {
        +      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "returns": ""
        +    },
        +    "ambientMaterial": {
        +      "description": "使用所给予颜色定义形状的环境材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值",
        +                 "数字:蓝彩值或亮度值",
        +                 "数字:透明度",
        +                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "returns": ""
        +    },
        +    "specularMaterial": {
        +      "description": "使用所给予颜色定义形状的镜面材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值",
        +                 "数字:蓝彩值或亮度值",
        +                 "数字:透明度",
        +                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "returns": ""
        +    },
        +    "p5.RendererGL": {
        +      "description": "TODO",
        +      "returns": "p5: 该 p5 物件"
        +    },
        +    "p5.Shader": {
        +      "description": "Clase Shader para el modo WEBGL",
        +      "params": ["p5.RendererGL: una instancia de p5.RendererGL que servirá de contexto GL para este nuevo p5.Shader",
        +      "String: código fuente para el vertex shader (en forma de string)",
        +      "String: código fuente para el fragment shader (en forma de string)"],
        +      "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."]
        +    }
        +  },
        +    "p5.Image": {
             "loadPixels": {
               "description": "blah",
               "params": ["Numero: blah",
        
        From 97d9167b740c235ccb03920c1d85f169478e0115 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 16 May 2020 17:03:11 +0900
        Subject: [PATCH 19/36] first push for korean translation on reference page
        
        ---
         .../ko/22_Advanced_Data/00_Load_Saved_JSON.js |   2 +-
         src/data/reference/ko.json                    | 463 +++++++++---------
         2 files changed, 241 insertions(+), 224 deletions(-)
        
        diff --git a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        index 251a3b0c8a..e6eeba00c9 100644
        --- a/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        +++ b/src/data/examples/ko/22_Advanced_Data/00_Load_Saved_JSON.js
        @@ -4,7 +4,7 @@
          * 그리고, 그 결과물을 화면에 띄웁니다.
          * 웹 브라우저마다 파일 저장 위치가 다르기 때문에,
          * 프로세싱(Processing)의 예제와는 달리 saveJSON을 사용하지 않습니다.<br><br>
        - * 다니엘 쉬프만(Daniel Shiffman)의 프로세싱(Processing)의 <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON 예제</a> 참고
        + * 다니엘 쉬프만(Daniel Shiffman) 제작 프로세싱(Processing)의 <a href="https://processing.org/examples/loadsavejson.html">LoadSaveJSON 예제</a> 참고
          */
         
         // Bubble 클래스
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 4f10b73a86..882c733bbf 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -50,7 +50,7 @@
           "2D Primitives": "2D 기본 조형", 
           "Attributes": "설정 요소",  
           "Curves": "곡선", 
        -  "Vertex": "버텍스", 
        +  "Vertex": "꼭지점", 
           "3D Models": "3D 모델",  
           "3D Primitives": "3D 기본 조형", 
           "Constants": "상수",  
        @@ -72,7 +72,7 @@
           "Image": "이미지",  
           "Loading & Displaying": "불러오기 & 보이기", 
           "Pixels": "픽셀",  
        -  "IO": "IO", 
        +  "IO": "입력 & 출력", 
           "Input": "입력", 
           "Output": "출력", 
           "Table": "테이블", 
        @@ -91,7 +91,7 @@
           "p5": {
            "alpha": {
               "description": "픽셀 배열로부터 알파값을 추출합니다.",
        -      "params": ["p5.Color | 숫자[] | 문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        +      "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
               "returns": "알파값"
             },
             "blue": {
        @@ -122,333 +122,350 @@
             },
             "hue": {
               "description": "색상 또는 픽셀 배열로부터 색조를 추출합니다. 색조는 HSB와 HSL상 모두 존재합니다. 이 함수는 HSB 색상 객체를 사용할 경우(또는 HSB 색상 모드로 지정된 픽셀 배열을 사용할 경우) HSB로 표준화된 색조 값을 반환합니다. 기본값으로는 HSL로 표준화된 색조를 반환합니다. (단, 최대 색조가 별도로 지정되어있을 경우 다른 값을 반환합니다.)",
        -      "params": ["p5.COlor 객체, 색상 요소 또는 CSS 색상"],
        +      "params": ["객체, 색상 요소 또는 CSS 색상"],
               "returns": "색조"
             },
             "lerpColor": {
        -      "description": "두 가지 색상을 혼합하고, 그 사이에 존재하는 제 3의 색상을 찾습니다. amt 매개변수는 선형보간하는 Mezcla dos colores para encontrar un tercer color según la combinación de ambos. El parámetro amt es la cantidad a interpolar entre los dos valores, donde 0.0 es igual al primer color, 0.1 es muy cercano al primer color, 0.5 está a medio camino entre ambos, etc. Un valor menor que 0 será tratado como 0. Del mismo modo, valores sobre 1 serán tratados como 1. Esto es distinto al comportamiento de lerp(), pero necesario porque de otra manera los números fuera de rango producirían colores no esperados y extraños. La manera en que los colores son interpolados depende del modo de color actual.",
        -      "params": ["Arreglo/Número: interpola desde este color",
        -      "Arreglo/Número: interpola hacia este color",
        -      "Número: número entre 0 y 1"],
        -      "returns": "Arreglo/Número: color interpolado"
        -    },
        +      "description": "두 가지 색상을 혼합하고, 그 사이에 존재하는 제 3의 색상을 찾습니다. 여기서 amt 매개변수는 두 개의 값 사이를 선형적으로 보간합니다. 예를 들어, 0.0은 첫 번째 값과 동일한 색상값을, 0.1은 첫 번째 값에 매우 가까운 색상값을, 0.5는 두 값 사이의 중간 색상값을 나타내는 식입니다. 이 때, 0 미만의 값은 0으로, 1이상의 값은 1로 자동 변환됩니다. 이 점에서 lerpColor()는 lerp()와 다르게 작동하는 셈인데, 이처럼 lerpColor()는 색상값을 0과 1사이로 조정하여 지정된 범위를 벗어난 색상 생성을 방지합니다. 또한, 색상이 보간되는 방식은 현재 지정된 색상 모드에 따라 달라집니다.",
        +      "params": ["이 색상으로부터 선형 보간",
        +      "이 색상을 향해 선형 보간",
        +      "숫자: 0과 1 사이의 숫자"],
        +      "returns": "p5.Color: 선형적으로 보간된 색상"},
             "lightness": {
        -      "description": "Extrae el valor de luminosidad HSL de un color o de un arreglo de pixeles.",
        -      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        -      "returns": "el objeto p5"
        +      "description": "색상 또는 픽셀 배열로부터 HSL 명도를 추출합니다.",
        +      "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        +      "returns": "숫자: 명도"
             },
             "red": {
        -      "description": "Extrae el valor de rojo de un color o de un arreglo de pixeles.",
        -      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        -      "returns": "el objeto p5"
        +      "description": "색상 또는 픽셀 배열로부터 빨강색값 추출합니다.",
        +      "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        +      "returns": "숫자: 빨강색값"
             },
             "saturation": {
        -      "description": "Extrae el valor de saturación de un color o de un arreglo de pixeles. La saturación es escalada en HSB y HSL de forma distinta. Esta función retornará la saturación HSB cuando le sea provisto un objeto de color HSB (o cuando le sea provisto un arreglo de pixeles mientras el modo de color es HSB), pero por defecto retornará saturación HSL.",
        -      "params": ["Objeto: objeto p5.Color o arreglo de pixeles"],
        -      "returns": "el objeto p5"
        +      "description": "색상 또는 픽셀 배열로부터 채도값 추출합니다. 채도값은 HSB와 HSL에서 각각 다르게 측정됩니다. 이 함수는 HSL 채도를 기본값으로 제공합니다. 하지만, HSB 색상 객체가 제공 될 때 (또는 색상 모드가 HSB이면서 픽셀 배열이 제공될 때) HSB 채도값을 반환합니다.",
        +      "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        +      "returns": "숫자: 채도값"
             },
             "background": {
        -      "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 초기값은 투명입니다. 이 함수는 주로 각 프레임이 시작될 때 화면을 초기화하기 위한 목적으로 draw() 내에서 사용되는데, 배경색을 일회적으로 설정할 경우 setup() 함수 내에서 애니메이션의 첫 프레임의 배경색을 설정하는데 사용되기도 합니다. 색 지정은 RGB, HSB, HSL 세가지 방법으로 할 수 있는데, 모드를 변경하기 위해서는 colorMode() 함수를 이용합니다. 따로 모드 설정을 하지 않는 경우, 색은 RGB로 정의되며 각 숫자의 범위는 0에서 255까지입니다. background()의 괄호 안에 단 한개의 값만 입력하는 것도 가능한데, RGB, RGBA, HEX CSS 모두 사용할 수 있습니다. 단, 투명도를 설정하기 위해서는 반드시 RGBA를 사용해야합니다. 참고로, p5.Color 오브젝트를 통해 배경색을 설정하는 것도 가능합니다. 배경 이미지를 설정하고 싶다면, 레퍼런스의 p5.Image 항목을 참고하세요.",
        -      "params": ["p5.Color: color() 함수를 통해 만들어진 값",
        -               "문자열: 색상 문자열, 정수 rgb()나 rgba(), 백분율 rgb()나 rgba(), 3자리 숫자 hex, 6자리 숫자 hex",
        -               "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        -               "숫자: 흑백 채도를 설정함",
        -               "숫자: 선택한 컬러모드에 따라, red값 혹은 hue값",
        -               "숫자: 선택한 컬러모드에 따라, green값 혹은 saturation값",
        -               "숫자: 선택한 컬러모드에 따라, blue값 혹은 brightness값",
        -               "숫자 배열[]: red, green blud와 투명도를 포함한 배열",
        -               "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 창과 같은 사이즈여야 함)"],
        -      "returns": "the p5 object"
        +      "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 기본값은 투명입니다. 이 함수는 주로 draw() 함수 안에 위치하며, 매 프레임마다 윈도우 화면을 초기화하기 위해 사용됩니다. 하지만, 애니메이션의 첫 프레임 배경을 지정하거나 배경색을 최초 한번만 지정할 경우, setup() 함수 안에 쓰이기도 합니다. <br> 색상은 현재 색상 모드(colorMode)에 따라 RGB, HSB, 또는 HSL값으로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) 알파값의 기본 제공 범위 역시 0부터 255까지입니다.<br> 단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다. <br> p5.Color 객체를 통해 배경색을 설정할 수 있습니다. <br> p5.Image를 통해 배경 이미지를 설정할 수 있습니다.",
        +      "params": ["p5.Color: color() 함수로 생성된 모든 값",
        +               "문자열, 지원되는 문자열 형식: 색상 문자열, 정수의 rgb()나 rgba(), 백분율의 rgb()나 rgba(), 3자리 숫자의 hex, 6자리 숫자의 hex",
        +               "숫자: 현재 색상 범위에 따른 배경색 투명도 (기본값은 0-255) (선택 사항)",
        +               "숫자: 흑과 백 사이의 값 지정",
        +               "숫자: 빨강색값 또는 색조값 (현재 색상 모드에 따라 상이),
        +               "숫자: 초록색값 또는 채도값 (현재 색상 모드에 따라 상이)",
        +               "숫자: 파랑색값 또는 밝기값 (현재 색상 모드에 따라 상이)",
        +               "숫자 배열[]: 빨강색값, 초록색값, 파랑색값, 알파값을 포함한 배열",
        +               "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 화면과 반드시 동일한 사이즈일 것)"],
        +      "returns": "p5 객체"
             },
             "clear": {
        -      "description": "버퍼 내의 픽셀을 클리어합니다. 본 함수는 createCanvas() 함수로 만들어진 p5.Canvas 오브젝트에만 적용되며, 메인 디스플레이 윈도우에 사용할 수는 없습니다. 메인 그래픽 영역에서와 다르게, createGraphics()를 이용해 생성한 추가 그래픽 영역 내에 있는 픽셀은 완전히 혹은 부분적으로 투명하게 만들 수 있습니다. clear() 함수는 모든 픽셀을 100% 투명하게 만듭니다.",
        -      "returns": "the p5 object"
        +      "description": "버퍼에 있는 픽셀들을 클리어하는 함수로, 오직 캔버스만 클리어하게 됩니다. createVideo()나 createDiv()와 같은, createX()류의 메소드로 지정된 객체들을 제거하진 않습니다. 메인 그래픽이 아닌, createGraphics()로 생성된 부가적인 그래픽의 경우, 그 전체 또는 일부를 투명하게 처리할 수 있습니다. 이 함수는 모든 픽셀을 100% 투명하게 만듭니다.",
        +      "returns": "p5 객체"
             },
             "colorMode": {
        -      "description": "colorMode()는 p5.js가 색 데이터를 해석하는 방식을 결정합니다. fill(), stroke(), background(), color()의 매개변수의 초기값은 RGB 컬러모드이며, 범위는 0에서 255까지, 즉 colorMode(RGB, 255) 입니다. colorMode(HSB)로 설정하는 경우 HSB 컬러 시스템을 사용할 수 있는데, 초기값은 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 컬러모드를 HSL을 설정하는 것도 가능합니다. 참고: 이미 존재하는 컬러 오브젝트들은 자신이 생성되었을 당시의 모드를 기억합니다. 따라서, 이미 존재하는 컬러 오브젝트에 영향을 미치지 않으면서 컬러모드는 바꾸는 것이 가능합니다.",
        -      "params": ["상수(Constante): RGB (Red/Green/Blue), HSB (Hue/Saturation/Brightness), HSL (Hue/Saturation/Lightness) 중 하나",
        -      "숫자: 현재 컬러모드에 따라 red 혹은 hue 범위",
        -      "숫자: 현재 컬러모드에 따라 green 혹은 saturation 범위.",
        -      "숫자: 현재 컬러모드에 따라 blue 혹은 brightness/lightness 범위.",
        -      "숫자: 투명도 범위"],
        -      "returns": "the p5 object"
        +      "description": "colorMode()는 p5.js가 색상 데이터를 해석하는 방식을 결정합니다. 기본값으로, fill(), stroke(), background(), color()의 매개변수는 RGB 색상 모드에서 처리되며, 그 범위는 0부터 255까지입니다. 이 기본값은 colorMode(RGB, 255)와 동일한 효과를 지닙니다. colorMode(HSB)로 설정을 변경하면 HSB 색상 시스템을 사용할 수 있습니다. HSB 색상 시스템은 그 기본값으로 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 색상 모드는 HSL로도 설정가능합니다. <br>참고: 모든 색상 객체들은 생성 당시에 지정된 색상 모드를 반영합니다. 따라서, 이미 생성된 색상 객체 중 일부에만 적용되는 색상 모드를 지정할 수도 있습니다.",
        +      "params": ["상수: RGB(빨강Red/초록Green/파랑색Blue), HSB(색조Hue/채도Saturation/밝기Brightness), HSL(색조Hue/채도Saturation/명도Lightness) 중 하나",
        +      "숫자: 모든 값들의 범위 (선택 사항)",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        +      "숫자: 알파값의 범위 (선택 사항)"],
        +      "returns": "p5 객체"
             },
             "fill": {
        -      "description": "도형을 칠할 색을 선택합니다. 예를 들어 fill(204, 102, 0)을 실행하면 해당되는 모든 도형들의 색이 주황색으로 바뀝니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.",
        -      "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값",
        -      "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값",
        -      "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값",
        -      "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        -      "문자열: 문자열로 된 색상값",
        -      "숫자: 흑백 채도를 설정함",
        -      "숫자 배열[]: red, green blue와 투명도를 포함한 배열",
        -      "p5.Color" ],
        -      "returns": "the p5 object"
        +      "description": "도형의 면을 채울 색상을 지정합니다. 예를 들어, fill(204, 102, 0) 함수를 실행하면, 이 명령어 다음에 그려진 모든 도형들이 주황색으로 칠해집니다. 이 때, 색상값은 colorMode()로 지정된 현재의 색상 모드에 따라 RGB 또는 HSB로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) 알파값의 기본 제공 범위 역시 0부터 255까지입니다. <br>단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다.",
        +      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        +      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑색값 또는 밝기값",
        +      "숫자: (선택 사항)",
        +      "문자열: 색상 문자열",
        +      "숫자: 회색값",
        +      "숫자 배열[]: 색상의 빨강색값, 초록색값, 파랑색값, 그리고 알파값을 포함한 배열",
        +       "p5.Color: 면채우기 색상" ],
        +      "returns": "p5 객체"
             },
             "noFill": {
               "description": "도형에 색을 채우지 않도록 설정합니다. noStroke() 과  noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.",
        -      "returns": "the p5 object"
        +      "returns": "p5 객체"
             },
             "noStroke": {
               "description": "선이나 윤곽선을 그리지 않도록 설정합니다. noStroke() 과  noFill()을 동시에 사용하면, 화면에 아무것도 나타나지 않습니다.",
        -      "returns": "the p5 object"
        +      "returns": "p5 객체"
             },
             "stroke": {
        -      "description": "선을 그리거나 도형 윤곽선 색을 설정합니다. 색 지정은 선택된 colorMode() 값에 따라서 RGB나 HSB로 할 수 있습니다. 초기 컬러모드는 RGB이며 R, G, B 각 값의 범위는 0-255 사이입니다. 투명도 역시 초기값의 범위는 0-255 입니다. RGB, RGBA, Hex CSS 컬러값이나 색 이름과 같이 한개의 문자열을 입력하는 것도 가능합니다. 이러한 경우에는 두번째 변수로 투명도를 입력하는 것이 불가능하므로, RGBA를 사용해야 합니다. 참고로, p5의 Color 오브젝트를 사용해 색을 지정하는 것도 가능합니다.",
        -      "params": ["숫자: 선택한 컬러모드와 색상값 범위에 따라, red값 혹은 hue값",
        -      "숫자: 선택한 컬러모드와 색상값 범위에 따라, green값 혹은 saturation값",
        -      "숫자: 선택한 컬러모드와 색상값 범위에 따라, blue값 혹은 brightness값",
        -      "숫자: 배경색 투명도 (범위 기본값은 0-255이며, 범위는 설정에 따라 다를 수 있음)",
        -      "문자열: 문자열로 된 색상값",
        -      "숫자: 흑백 채도를 설정함",
        -      "숫자 배열[]: red, green blud와 투명도를 포함한 배열",
        -      "p5.Color"],
        -      "returns": "the p5 object"
        +      "description": "그려질 선 또는 도형의 테두리 색상을 설정합니다. 이 때, 색상값은 colorMode()로 지정된 현재의 색상 모드에 따라 RGB 또는 HSB로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) <br>단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다.<br> p5.Color 객체를 통해 선의 색상을 설정할 수 있습니다.",
        +      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        +      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑색값 또는 밝기값",
        +      "숫자: (선택 사항)",
        +      "문자열: 색상 문자열",
        +      "숫자: 회색값",
        +      "숫자 배열[]: 색상의 빨강색값, 초록색값, 파랑색값, 그리고 알파값을 포함한 배열",
        +      "p5.Color: 선의 색상"],
        +      "returns": "p5 객체"
             },
             "arc": {
        -      "description": "화면에 호를 그립니다. 모드 선택 없이 x, y, w, h, 시작, 끝만을 지정하면 호는 열린 파이조각 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫혀진 반원(CHORD), 닫혀진 파이조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 본 함수를 이용해 시작점을 0, 끝점을 TWO_PI로 설정해 원 전체를 그리려 시도하면, 시작점과 끝점이 같기 때문에 아무것도 그려지지 않습니다. 원 전체를 그릴때는 ellipse() 함수를, 원 일부를 그릴 때는 arc() 함수를 이용하세요.",
        -      "params": ["숫자: 호를 포함하는 원의 x 좌표",
        -      "숫자: 호를 포함하는 원의 y 좌표",
        -      "숫자: 호를 포함하는 원의 너비",
        -      "숫자: 호를 포함하는 원의 높이",
        -      "숫자: 시작점의 각도로, 호도(radians)로 설정",
        -      "숫자: 끝점의 각도로, 호도(radians)로 설정",
        -      "상수: 호를 그리는 방식을 설정함. CHORD, PIEC, OPEN 중 선택. 필수 변수는 아니며 필요한 경우에만 사용하면 됨.",
        -      "숫자: WEBGL 모드에서만 사용하며, 호의 윤곽선을 구성하는 점(vertices)의 숫자를 지정한다. 필수 변수는 아니며 필요한 경우에만 사용하면 됨. 초기값은 25이다."],
        -      "returns": "the p5 object"
        +      "description": "화면에 호, 즉 아치형 선을 그립니다. x좌표, y좌표, w(너비), h(높이), 시작점, 끝점을 지정하면 호는 열린 파이 조각의 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫힌 반원(CHORD), 닫힌 파이 조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 만약 원 하나를 그리기 위해 arc()의 시작점을 0으로, 끝점을 TWO_PI으로 설정할 경우, 시작점과 끝점이 동일하여 아무것도 그려지지 않습니다. 원을 그릴 때는 ellipse() 함수를, 원의 일부를 그릴 때는 arc() 함수를 이용하세요.",
        +      "params": ["숫자: 호를 포함하는 원의 x좌표",
        +      "숫자: 호를 포함하는 원의 y좌표값",
        +      "숫자: 호를 포함하는 원의 너비값",
        +      "숫자: 호를 포함하는 원의 높이값",
        +      "숫자: 부채각(radians)에 따른, 호의 시작점 각도값",
        +      "숫자: 부채각(radians)에 따른, 호의 끝점 각도값",
        +      "상수: 호를 그리는 방식들로, CHORD, PIEC, OPEN 중 선택 가능 (선택 사항)",
        +      "숫자: WebGL 모드를 위한 선택적 변수로, 호의 테두리를 구성하는 꼭지점 개수를 지정. 기본값은 25. (선택 사항)"],
        +      "returns": "p5 객체"
             },
             "ellipse": {
        -      "description": "스크린에 타원을 그립니다. 너비와 높이가 같은 경우에는 원이 그려집니다. 첫 두 변수는 위치를, 세번째 네번째 변수는 도형의 너비와 높이를 설정합니다. 높이를 설정하지 않으면 너비 값이 높이로도 사용됩니다. 너비나 높이를 음수로 입력하면, 자동적으로 절대값이 사용됩니다. 원 시작점을 원의 중심으로 둘지의 여부는 ellipseMode() 함수를 이용해 변경할 수 있습니다.",
        -      "params": ["숫자: 원의 x 좌표",
        -      "숫자: 원의 y 좌표",
        -      "숫자: 원의 너비",
        -      "숫자: 원의 높이",
        -      "정수: 원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WEGBL 모드용)"],
        -      "returns": "the p5 object"
        +      "description": "화면에 타원을 그립니다. 너비와 높이가 동일한 값으로 지정될 경우, 원이 그려집니다. 처음 두 변수는 각각 타원의 x좌표와 y좌표를, 3번째와 4번째 변수는 각각 타원의 너비와 높이를 지정합니다. 높이값 입력을 생략할 경우, 너비값이 높이값으로 동일하게 적용됩니다. 너비나 높이에 음수로 입력해도 그 절대값이 반영됩니다. ellipseMode() 함수를 이용하면 타원의 시작점을 원의 중심으로 지정할 지의 여부를 결정할 수 있습니다.",
        +      "params": ["숫자: 타원의 x좌표",
        +      "숫자: 타원의 y좌표값",
        +      "숫자: 타원의 너비값",
        +      "숫자: 타원의 높이값",
        +      "정수: 타원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WebGL 모드용)"],
        +      "returns": "p5 객체"
             },
         
             "line": {
        -      "description": "화면에 선, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하는 경우 이차원 평면에 선을 그립니다. 선의 색을 지정하려면 stroke() 함수를 이용하세요. 선은 면은 가지고 있지 않기 때문에 면 색을 채우는 fill() 함수는 적용되지 않습니다. 선의 굵기 초기값은 1픽셀이며 이를 변경하기 위해서는 strokeWeight() 함수를 이용합니다.",
        -      "params": ["숫자: 첫번째 점의 x 좌표",
        -      "숫자: 첫번째 점의 y 좌표",
        -      "숫자: 두번째 점의 x 좌표",
        -      "숫자: 첫번째 점의 y 좌표",
        -      "숫자: 첫번째 점의 z 좌표",
        -      "숫자: 두번째 점의 z 좌표"],
        -      "returns": "the p5 object"
        +      "description": "화면에 선분, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하여 이차원 평면에 선을 그릴 수 있습니다. stroke() 함수를 사용해 선의 색상을 지정할 수 있습니다. 선은 면을 갖지 않으므로, 면채우기 함수인 fill()은 적용되지 않습니다. 기본값으로 제공되는 선의 두께는 1픽셀이며, 이를 변경하기 위해 strokeWeight() 함수를 사용할 수 있습니다.",
        +      "params": ["숫자: 1번째 점의 x좌표값",
        +      "숫자: 1번째 점의 y좌표값",
        +      "숫자: 2번째 점의 x좌표값",
        +      "숫자: 2번째 점의 y좌표값",
        +      "숫자: 1번째 점의 z좌표값",
        +      "숫자: 2번째 점의 z좌표값"],
        +      "returns": "p5 객체"
             },
             "point": {
        -      "description": "Dibuja un punto, una coordenada en el espacio de un pixel de dimensión. El primer parámetro es la coordenada horizontal del punto, el segundo valor es la coordenada vertical del punto. El color del punto es determinado por el trazado actual con la función stroke().",
        -      "params": ["숫자: x 좌표",
        -      "숫자: y 좌표",
        -      "숫자: z 좌표 (WEBGL 모드 사용시)"],
        -      "returns": "the p5 object"
        +      "description": "화면 좌표에 해당하는, 1픽셀 크기의 점을 그립니다. 첫 번째 매개 변수는 점의 x좌표값을, 두 번째 매개 변수는 점의 y좌표값입니다. 점의 색상은 stroke() 함수로 변경할 수 있습니다. 점의 크기는 strokeWeight() 함수로 변경할 수 있습니다.",
        +      "params": ["숫자: x좌표값",
        +      "숫자: y좌표값",
        +      "숫자: z좌표값 (WebGL 모드용)"],
        +      "returns": "p5 객체"
             },
             "quad": {
        -      "description": "네모꼴을 그립니다. 네모꼴은 4개의 변을 가진 다각형으로, 직사각형과 유사해 보이지만 직사각형과 다르게 변 사이의 각도가 90도로 고정되어 있지 않습니다. 첫 한 쌍의 변수는 첫 꼭지점을 설정하며 뒤따르는 다른 쌍의 변수들은 시계방향이나 반시계방향으로 차례대로 꼭지점을 설정합니다. z 변수는 WEBGL모드에서 quad() 함수를 사용하는 경우에만 적용됩니다.",
        -      "params": ["숫자: 첫번째 꼭지점의 x 좌표",
        -      "숫자: 첫번째 꼭지점의 y 좌표",
        -      "숫자: 두번째 꼭지점의 x 좌표",
        -      "숫자: 두번째 꼭지점의 y 좌표",
        -      "숫자: 세번째 꼭지점의 x 좌표",
        -      "숫자: 세번째 꼭지점의 y 좌표",
        -      "숫자: 네번째 꼭지점의 x 좌표",
        -      "숫자: 네번째 꼭지점의 y 좌표",
        -      "숫자: 첫번째 꼭지점의 z 좌표",
        -      "숫자: 두번째 꼭지점의 z 좌표",
        -      "숫자: 세번째 꼭지점의 z 좌표",
        -      "숫자: 네번째 꼭지점의 z 좌표"],
        -      "returns": "the p5 object"
        +      "description": "사각형을 그립니다. 사각형은 4개의 변을 가진 다각형으로, 얼핏 직사각형과 유사하게 들리나 직사각형과는 달리 변 사이의 각도가 90도로 고정되어 있지 않습니다. 처음 한 쌍의 변수는 최초의 꼭지점을 설정하며, 뒤이은 다른 쌍들은 시계 방향이나 반시계 방향에 따라 나머지 3개의 꼭지점 위치를 설정합니다. z 변수는 WebGL 모드에서 quad() 함수를 사용하는 경우에만 적용됩니다.",
        +      "params": ["숫자: 1번째 꼭지점의 x좌표값",
        +      "숫자: 1번째 꼭지점의 y좌표값",
        +      "숫자: 2번째 꼭지점의 x좌표값",
        +      "숫자: 2번째 꼭지점의 y좌표값",
        +      "숫자: 3번째 꼭지점의 x좌표값",
        +      "숫자: 3번째 꼭지점의 y좌표값",
        +      "숫자: 4번째 꼭지점의 x좌표값",
        +      "숫자: 4번째 꼭지점의 y좌표값",
        +      "숫자: 1번째 꼭지점의 z좌표값",
        +      "숫자: 2번째 꼭지점의 z좌표값",
        +      "숫자: 3번째 꼭지점의 z좌표값",
        +      "숫자: 4번째 꼭지점의 z좌표값"],
        +      "returns": "p5 객체"
             },
             "rect": {
        -      "description": "화면에 직사각형을 그립니다. 직사각형은 변이 네개이면서 모든 각도가 90도인 도형입니다. 첫 두 변수는 왼쪽 위 꼭지점의 좌표를, 세번째 변수는 사각형의 너비를, 네번째 변수는 높이를 설정합니다. rectMode() 함수로 사각형 모드를 변경하는 경우 변수 입력값들은 다르게 해석됩니다. 다섯번째, 여섯번째, 일곱번째, 여덟번째 변수를 입력하는 경우 각각의 숫자는 차계로 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래 모퉁이의 각도를 지정합니다. 각도 변수를 누락하는 경우 앞서 지정한 각도 값이 사용됩니다.",
        -      "params": ["숫자: 직사각형의 x 좌표값",
        -      "숫자: 직사각형의 y 좌표값",
        -      "숫자: 직사각형의 너비",
        -      "숫자: 직사각형의 높이",
        -      "숫자: 왼쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 오른쪽 위 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 오른쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "숫자: 왼쪽 아래 모퉁이 각도 값. 필수 변수가 아니므로 필요한 경우에만 입력.",
        -      "정수: x 방향의 segment 수 (WEBGL 모드에서 사용)",
        -      "정수: y 방향의 segment 수 (WEBGL 모드에서 사용)"],
        -      "returns": "the p5 object"
        +      "description": "화면에 직사각형을 그립니다. 직사각형은 변이 4개이고 모든 변 사이의 각도가 90도인 도형을 뜻합니다. 처음 두 변수는 좌측 상단 꼭지점의 좌표를, 3번째 변수는 사각형의 너비를, 4번째 변수는 그 높이를 설정합니다. rectMode() 함수로 사각형 그리기 모드를 변경하면, 모든 매개 변수값들이 달리 해석됩니다. 5번째, 6번째, 7번째, 8번째 매개 변수를 입력하면, 각각 좌측 상단, 우측 상단, 우측 하단, 좌측 하단 모퉁이들의 각도를 지정하게 됩니다. 이 때 특정 각도 변수가 누락되면, 직전에 입력된 변수와 동일한 값이 적용됩니다.",
        +      "params": ["숫자: 직사각형의 x좌표값",
        +      "숫자: 직사각형의 y좌표값",
        +      "숫자: 직사각형의 너비값",
        +      "숫자: 직사각형의 높이값",
        +      "숫자: 좌측 상단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 우측 상단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 우측 하단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 좌측 하단 모퉁이 각도값. (선택 사항)",
        +      "정수: x축 방향의 선분 수 (WebGL 모드용)",
        +      "정수: y축 방향의 선분 수 (WebGL 모드용)"],
        +      "returns": "p5 객체"
        +    },
        +    "sqaure": {
        +      "description": "화면에 정사각형을 그립니다. 정사각형은 동일한 길이의 네 개의 변을 갖고, 모든 변 사이의 각도가 90도인 도형을 뜻합니다. 이 함수는 rect()함수의 특수한 사례와도 같은데, 너비와 높이가 같고 변의 길이를 "s"라는 매개 변수로 처리하게 됩니다. 기본값으로, 처음 두 변수는 처음 두 변수는 좌측 상단 꼭지점의 좌표를, 3번째 변수는 변의 길이를 지정합니다. rectMode() 함수로 사각형 그리기 모드를 변경하면, 모든 매개 변수값들이 달리 해석됩니다. <br> 5번째, 6번째, 7번째매개 변수를 입력하면, 각각 좌측 상단, 우측 상단, 우측 하단, 좌측 하단 모퉁이들의 각도를 지정하게 됩니다. 이 때 특정 각도 변수가 누락되면, 직전에 입력된 변수와 동일한 값이 적용됩니다.",
        +      "params": ["숫자: 정사각형의 x좌표값",
        +      "숫자: 정사각형의 y좌표값",
        +      "숫자: 정사각형의 너비 및 높이값",
        +      "숫자: 좌측 상단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 우측 상단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 우측 하단 모퉁이 각도값. (선택 사항)",
        +      "숫자: 좌측 하단 모퉁이 각도값. (선택 사항)"],
        +      "returns": "p5 객체"
             },
             "triangle": {
        -      "description": "三角形是个由连接三个点所形成的平面形。前两个参数定义第一个点,中间两个参数定义第二个点而最后两个参数定义第三个点。",
        -      "params": ["数字:第一个点的 x 坐标",
        -                 "数字:第一个点的 y 坐标",
        -                 "数字:第二个点的 x 坐标",
        -                 "数字:第二个点的 y 坐标",
        -                 "数字:第三个点的 x 坐标",
        -                 "数字:第三个点的 y 坐标"],
        +      "description": "삼각형은 세 개의 점을 이어 만들어진 평면을 뜻합니다. 처음 두 인수는 1번째 꼭지점을, 중간의 두 변수는 2번째 꼭지점을, 마지막 두 인수는 3번째 꼭지점을 지정합니다.",
        +      "params": ["숫자:1번째 꼭지점의 x좌표값",
        +                 "숫자:1번째 꼭지점의 y좌표값",
        +                 "숫자:2번째 꼭지점의 x좌표값",
        +                 "숫자:2번째 꼭지점의 y좌표값",
        +                 "숫자:3번째 꼭지점의 x좌표값",
        +                 "숫자:3번째 꼭지점의 y좌표값"],
               "returns": ""
             },
             "ellipseMode": {
        -      "description": "更改 ellipse() 参数被解读的方式,用以更改椭圆形被画在画布上的位置。<br><br>默认模式为 ellipseMode(CENTER),ellipse() 前两个参数将被解读成椭圆形的中心点,而第三和第四个参数为宽度和高度。<br><br>ellipseMode(RADIUS) 将 ellipse() 的前两个参数解读成形状的中心点,但是第三和第四个参数被用于定义形状的半径宽度和半径高度<br><br>ellipseMode(CORNER) 将 ellipse() 的前两个参数解读成形状左上角的位置,而第三和第四个参数为宽度和高度<br><br>ellipseMode(CORNERS) 将 ellipse() 的前两个参数解读成形状其中一个角落的位置,而第三和第四个参数则被解读成对面角落的位置。<br><br>参数必须全是大写因为 Javascript 是个区分大小写的编程语言。",
        -      "params": ["常量:CENTER、RADIUS、CORNER 或 CORNERS"],
        +      "description": "ellipse(), circle(), 그리고 arc() 함수의 매개 변수들이 해석되는 방식을 변경하여, 타원이 그려지는 시작점 위치를 변경합니다.<br><br>기본적으로 제공되는 모드는 ellipseMode(CENTER) 함수와도 같습니다. 이는 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로, 3번째와 4번째 변수를 각각 그 너비와 높이값으로서 해석합니다.<br><br>ellipseMode(RADIUS) 역시 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로 해석하나, 3번째와 4번째 변수를 각각 너비와 높이의 중간 지점값으로 해석합니다.<br><br>ellipseMode(CORNER)는 ellipse() 함수의 처음 두 매개 변수를 도형의 좌측 상단을 기준으로 해석하고, 3번째와 4번째 변수를 각각 그 너비와 높이로 해석합니다. <br><br>ellipseMode(CORNERS)는 ellipse() 함수의 처음 두 매개 변수를 도형의 바운딩 박스 중 한 모퉁이의 위치값으로서 해석합니다. 그리고, 3번째와 4번째 변수는 그 정반대 모퉁이의 위치값으로 해석합니다.<br><br>이 함수의 모든 매개 변수(CENTER, RADIUS, CORNER, CORNERS)들은 반드시 대문자로 작성되어야 합니다. 자바스크립트에서는 대소문자 구분이 매우 중요하답니다.",
        +      "params": ["상수:CENTER, RADIUS, CORNER, 또는 CORNERS"],
               "returns": ""
             },
             "noSmooth": {
        -      "description": "所有形状的边缘都为锯齿状。注意 smooth() 为默认模式所以您必须调用 noSmooth() 以禁用平滑形状、图像及字体。",
        +      "description": "모든 그래픽의 가장자리를 울퉁불퉁하게 처리합니다. smooth() 함수는 2D 모드상 언제나 기본값으로 활성화되며, 그래픽을 부드럽게 처리합니다. 따라서, noSmooth() 함수를 호출해야만 기하, 이미지, 폰트 등의 부드러운 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 처리가 가능합니다.",
               "returns": ""
             },
             "rectMode": {
        -      "description": "更改 rect() 参数被解读的方式,用以更改方形被画在画布上的位置。<br><br>默认模式为 rectMode(CORNER), rect() 前两个参数将被解读成形状的左上角的位置,而第三和第四个参数为宽度和高度。<br><br>rectMode(CORNERS) 将 rect() 的前两个参数解读成形状其中一个角落的位置,而第三和第四个参数则被解读成对面角落的位置。<br><br>rectMode(CENTER) 将 rect() 的前两个参数解读成形状的中心点,而第三和第四个参数为宽度和高度。<br><br>rectMode(RADIUS) 也将的前两个参数解读成形状的中心点,但第三和第四个参数被用来定义形状一半的宽度和一半的高度。<br><br>参数必须全是大写因为 Javascript 是个区分大小写的编程语言。",
        -      "params": ["常量:CORNER、CORNERS、CENTER 或 RADIUS"],
        +      "description": "rect() 함수의 매개 변수들이 해석되는 방식을 변경하여, 직사각형이 그려지는 시작점 위치를 변경합니다.<br><br>기본적으로 제공되는 모드는 rectMode(CORNER) 함수와도 같습니다. 이는 rect() 함수의 처음 두 매개 변수를도형의 좌측 상단을 기준으로 해석하고, 3번째와 4번째 변수를 각각 그 너비와 높이값로서 해석합니다. <br><br>rectMode(CORNERS)는 rect() 함수의 처음 두 매개 변수를 한 모퉁이의 위치값으로 서 해석합니다. 그리고, 3번째와 4번째 변수는 그 정반대 모퉁이의 위치값으로 해석합니다.<br><br>ellipseMode(CENTER)는 rect() 함수의 처음 두 매개 변수를 타원의 중심점으로, 3번째와 4번째 변수를 각각 그 너비와 높이값으로서 해석합니다. <br><br>rectMode(RADIUS) 역시 rect() 함수의 처음 두 매개 변수를 타원의 중심점으로 해석하나, 3번째와 4번째 변수를 각각 너비와 높이의 중간 지점값으로 해석합니다.<br><br>이 함수의 모든 매개 변수(CORNER, CORNERS, CENTER, RADIUS)들은 반드시 대문자로 작성되어야 합니다. 자바스크립트에서는 대소문자 구분이 매우 중요하답니다.",
        +      "params": ["상수:CORNER, CORNERS, CENTER 또는 RADIUS"],
               "returns": ""
             },
             "smooth": {
        -      "description": "所有形状的边缘都为非锯齿(平滑)状。smooth() 也将提高调整过大小的图像的素质。注意 smooth() 为默认模式;noSmooth() 也能用来禁用平滑形状、图像及字体。",
        +      "description": "모든 그래픽을 부드럽게 처리하며, 불러온 이미지 또는 크기가 재조정된 이미지의 화질을 향상합니다. smooth()는 2D 모드상 언제나 기본값으로 활성화되며. 따라서, noSmooth() 함수를 호출해야만 기하, 이미지, 폰트 등의 부드러운 그래픽 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 그래픽 처리가 가능합니다.",
               "returns": ""
             },
             "strokeCap": {
        -      "description": "定义线条顶点的风格。顶点风格可以是方形、扩展式或圆形,它们个别参数为:SQUARE、PROJECT 及 ROUND。默认模式为 ROUND。",
        -      "params": ["常量:SQUARE、PROJECT 或 ROUND"],
        +      "description": "선의 양끝에 대한 렌더링 스타일을 설정합니다. 선의 양끝은 매개 변수 SQAURE로 각지게, PROJECT로 조금 더 길게, 그리고 ROUND로 둥글게 처리될 수 있습니다. 이 중에서 ROUND는 기본값으로 적용됩니다.",
        +      "params": ["상수:SQUARE, PROJECT 또는 ROUND"],
               "returns": ""
             },
             "strokeJoin": {
        -      "description": "定义线条连接的风格。这些链接可以是尖角、斜角或圆角,它们个别参数为:MITER、BEVEL 及 ROUND。默认模式为 MITER。",
        -      "params": ["常量:MITER、BEVEL 或 ROUND"],
        +      "description": "두 선분 간의 이음새에 대한 스타일을 설정합니다. 이음새는 매개 변수 MITER로 각지게, BEVEL로 베벨 처리되듯 비스듬히 깎인 형태로, ROUND로 둥글게 처리될 수 있습니다. 이 중에서 MITER는 기본값으로 적용됩니다.",
        +      "params": ["상수:MITER, BEVEL 또는 ROUND"],
               "returns": ""
             },
             "strokeWeight": {
        -      "description": "定义线条、点及形状边线的宽度(粗度)。所有宽度单位都是像素。",
        -      "params": ["数字:线条的粗度(像素单位)"],
        +      "description": "선, 점, 그리고 도형 테두리를 그릴 때 쓰이는 함수인 stroke()의 결과값 두께를 설정합니다. 모든 두께는 픽셀 단위로 지정됩니다.",
        +      "params": ["숫자:선의 두께 (픽셀 단위)"],
               "returns": ""
             },
             "bezier": {
        -      "description": "在荧幕上画个三次贝塞尔曲线。这些曲线是由一系列锚点和控制点所定义的。前两个参数定义第一个锚点而最后两个参数定义另一个锚点,这也是曲线的第一和最后一个点。中间的参数是用来定义控制点的位置并将决定曲线的形状。一般来说,控制点会将曲线“拉”向它们的方向。",
        -      "params": ["数字:第一个锚点的 x 坐标",
        -                 "数字:第一个锚点的 y 坐标",
        -                 "数字:第一个控制点的 x 坐标",
        -                 "数字:第一个控制点的 y 坐标",
        -                 "数字:第二个控制点的 x 坐标",
        -                 "数字:第二个控制点的 y 坐标",
        -                 "数字:第二个锚点的 x 坐标",
        -                 "数字:第二个锚点的 y 坐标",
        -                 "数字:第一个锚点的 z 坐标",
        -                 "数字:第一个控制点的 z 坐标",
        -                 "数字:第二个锚点的 z 坐标",
        -                 "数字:第二个控制点的 z 坐标"],
        +      "description": "화면에 3차 베지어 곡선을 그립니다. 베지어 곡선은 일련의 고정점 및 제어점들로 정의됩니다. 처음 두 매개 변수는 1번째 고정점을, 마지막 두 매개 변수는 마지막 고정점을 지정합니다. 중간의 두 매개 변수는 두 개의 제어점을 지정하며, 이는 곧 곡선의 모양을 정의하게 됩니다. 여기서 제어점은 그 자신을 향해 곡선을 당기는 역할을 합니다. <br><br> 베지어 곡선은 프랑스 출신 자동차 엔지니어인 피에르 베지어(Pierre Bezier)가 개발하였으며, 컴퓨터 그래픽상 부드럽게 경사진 곡선을 정의하는 데에 주로 사용됩니다. curve()도 참고하세요.",
        +      "params": ["숫자: 1번째 고정점의 x좌표값",
        +                 "숫자: 1번째 고정점의 y좌표값",
        +                 "숫자: 1번째 제어점의 x좌표값",
        +                 "숫자: 1번째 제어점의 y좌표값",
        +                 "숫자: 2번째 제어점의 x좌표값",
        +                 "숫자: 2번째 제어점의 y좌표값",
        +                 "숫자: 2번째 고정점의 x좌표값",
        +                 "숫자: 2번째 고정점의 y좌표값",
        +                 "숫자: 1번째 고정점의 z좌표값",
        +                 "숫자: 1번째 제어점의 z좌표값",
        +                 "숫자: 2번째 제어점의 z좌표값",
        +                 "숫자: 2번째 고정점의 z좌표값"],
               "returns": ""
             },
             "bezierDetail": {
        -      "description": "定义贝塞尔曲线的解析度<br><br>默认值为 20。<br><br>这函数只有在 WEBGL 模式下有效果因为默认画布渲染模式并不会使用这设定。",
        -      "params": ["数字:曲线的解析度"],
        +      "description": "베지어 곡선들의 해상도를 설정합니다. <br>기본값은 20입니다.<br>이 함수는 WebGL 렌더러용으로만 사용되며, 기본 캔버스 렌더러에서는 이 함수를 사용하지 않습니다.",
        +      "params": ["숫자: 곡선들의 해상도값"],
               "returns": ""
             },
             "bezierPoint": {
        -      "description": "计算在 a、b、c、d 点定义的贝塞尔曲线上 t 位置的坐标。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。这函数可以先调用 x 坐标然后在调用 y 坐标已找到曲线上 t 位置的点坐标。",
        -      "params": ["数字:曲线上第一个点的坐标",
        -                 "数字:第一个控制点的坐标",
        -                 "数字:第二个控制点的坐标",
        -                 "数字:曲线上第二个点的坐标",
        -                 "数字:介于 0 和 1 之间的值"],
        -      "returns": "数字:贝塞尔曲线上 t 位置的值"
        +      "description": "점 a, b, c, d로 정의된 베지어 곡선에서 위치 t를 계산합니다. 매개 변수 a와 d는 각각 곡선의 1번째 점과 마지막 점에, b와 c는 제어점에 해당합니다. 마지막 매개 변수인 t는 0과 1사이에서 표현됩니다. 함수는 먼저 x좌표를 호출한 다음, y좌표를 호출하여 위치 t를 찾게됩니다.",
        +      "params": ["숫자: 곡선의 1번째 점 좌표값",
        +                 "숫자: 1번째 제어점 좌표값",
        +                 "숫자: 2번째 제어점 좌표값",
        +                 "숫자: 곡선의 2번째 점 좌표값",
        +                 "숫자: 0과 1 사이의 값"],
        +      "returns": "숫자: 위치 t에 해당하는 베지어 곡선의 값"
             },
             "bezierTangent": {
        -      "description": "计算在 a、b、c、d 点定义的贝塞尔曲线上 t 位置的切线值。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。",
        -      "params": ["数字:曲线上第一个点的坐标",
        -                 "数字:第一个控制点的坐标",
        -                 "数字:第二个控制点的坐标",
        -                 "数字:曲线上第二个点的坐标",
        -                 "数字:介于 0 和 1 之间的值"],
        -      "returns": "数字:贝塞尔曲线上 t 位置的切线值"
        +      "description": "위치 t에서 곡선의 점 a, b, c, d에 대한 탄젠트를 계산합니다. 매개 변수 a와 d는 각각 곡선의 1번째 점과 마지막 점에, b와 c는 제어점에 해당합니다. 마지막 매개 변수인 t는 0과 1사이에서 표현됩니다.",
        +      "params": ["숫자: 곡선의 1번째 점 좌표값",
        +                 "숫자: 1번째 제어점 좌표값",
        +                 "숫자: 2번째 제어점 좌표값",
        +                 "숫자: 곡선의 2번째 점 좌표값",
        +                 "숫자: 0과 1 사이의 값"],
        +      "returns": "숫자: 위치 t에 해당하는 탄젠트"
             },
             "curve": {
        -      "description": "在荧幕上的两点之间画一个曲线,两点由中间四个参数定义。前两个参数为控制点,可以当作曲线是从这个点开始的虽然它并不会被画出来。最后两个参数同样也是用来定义另外一个控制点。<br><br>更长的曲线能使用一系列 curve() 函数创造或使用 curveVertex()。另外一个叫 curveTightness() 的函数提供曲线视觉质量的控制。curve() 函数使用的是 Catmull-Rom 样条函数。",
        -      "params": ["数字:起点控制点的 x 坐标",
        -                 "数字:起点控制点的 y 坐标",
        -                 "数字:第一个点的 x 坐标",
        -                 "数字:第一个点的 y 坐标",
        -                 "数字:第二个点的 x 坐标",
        -                 "数字:第二个点的 y 坐标",
        -                 "数字:终点控制点的 x 坐标",
        -                 "数字:终点控制点的 y 坐标",
        -                 "数字:起点控制点的 z 坐标",
        -                 "数字:第一个点的 z 坐标",
        -                 "数字:第二个点的 z 坐标",
        -                 "数字:终点控制点的 z 坐标"],
        +      "description": "화면에 두 점 사이에 위치한 곡선을 그립니다. 이 때, 곡선의 형태는 함수의 매개 변수들 중 가운데 네 개를 통해 정의됩니다. 처음 두 매개 변수는 1번째 제어점의 좌표값을 지정하는데, 마치 이 제어점에서 곡선이 비롯된 것처럼 보이게 됩니다. 마지막 두 매개 변수들은 마찬가지 원리로 또다른 제어점의 좌표를 지정합니다.<br><br>curve() 함수를 조합하거나 curveVertex()를 사용하여 좀 더 긴 곡선을 만들 수 있습니다. 부가적으로, curveTightness()을 통해 곡선의 화질을 조절할 수 있습니다. curve() 함수는 캣멀롬 스플라인(Catmull-Rom Spline)을 구현합니다.",
        +      "params": ["숫자: 최초 제어점의 x좌표값",
        +                 "숫자: 최초 제어점의 y좌표값",
        +                 "숫자: 1번째 점의 x좌표값",
        +                 "숫자: 1번째 점의 y좌표값",
        +                 "숫자: 2번째 점의 x좌표값",
        +                 "숫자: 2번째 점의 y좌표값",
        +                 "숫자: 마지막 제어점의 x좌표값",
        +                 "숫자: 마지막 제어점의 y좌표값",
        +                 "숫자: 최초 제어점의 z좌표값",
        +                 "숫자: 1번째 점의 z좌표값",
        +                 "숫자: 2번째 점의 z좌표값",
        +                 "숫자: 마지막 제어점의 z좌표값"],
               "returns": ""
             },
             "curveDetail": {
        -      "description": "定义曲线的解析度<br><br>默认值为 20。<br><br>这函数只有在 WEBGL 模式下有效果因为默认画布渲染模式并不会使用这设定。",
        -      "params": ["数字:曲线的解析度"],
        +      "description": "곡선들의 해상도를 설정합니다. <br>기본값은 20이고, 최소값은 3입니다.<br>이 함수는 WebGL 렌더러용으로만 사용되며, 기본 캔버스 렌더러에서는 이 함수를 사용하지 않습니다.",
        +      "params": ["숫자: 곡선들의 해상도값"],
               "returns": ""
             },
             "curveTightness": {
        -      "description": "更改由 curve() 及 curveVertex() 所创造的曲线的质量。所提供的参数将决定曲线如何切合顶点。0.0 是紧实度的默认值(这值表示曲线为 Catmull-Rom 样条)而 1.0 将使用直线连接所有点。在 -5.0 及 5.0 之间的值会是曲线变形不过他们仍然能被识别而当值越来越大时,曲线也会跟着变形。",
        -      "params": ["数字:从原顶点的变形量"],
        +      "description": "curve()와 curveVertex() 함수를 사용하여 모양을 변경합니다. 곡선의 팽팽함(tightness)을 지정하는 매개변수 t는, 두 꼭지점 사이에 곡선이 들어맞는 정도를 결정합니다. 값 0.0은 곡선의 팽팽함에 대한 기본값이며(이 값을 통해 곡선을 캣멀롬 스플라인으로 정의), 값 1.0은 모든 점을 직선 상태로 연결하게 됩니다. -5.0와 5.0 사이의 값들은 화면상 인식 가능한 범위 내에서 값의 크기에 비례하여 곡선을 변형합니다.",
        +      "params": ["숫자: 원래 꼭지점으로부터 변형된 정도의 양"],
               "returns": ""
             },
             "curvePoint": {
        -      "description": "计算在 a、b、c、d 点定义的曲线上 t 位置的坐标。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。这函数可以先调用 x 坐标然后在调用 y 坐标已找到曲线上 t 位置的点坐标。",
        -      "params": ["数字:曲线上第一个点的坐标",
        -                 "数字:第一个控制点的坐标",
        -                 "数字:第二个控制点的坐标",
        -                 "数字:曲线上第二个点的坐标",
        -                 "数字:介于 0 和 1 之间的值"],
        -      "returns": "数字:贝塞尔曲线上 t 位置的值"
        +      "description": "점 a, b, c, d로 정의된 곡선에서 위치 t를 계산합니다. 매개 변수 a와 d는 곡선의 제어점에, b와 c는 각각 곡선의 시작점과 끝점에 해당합니다. 마지막 매개 변수인 t는 0과 1사이에서 표현됩니다. 함수는 먼저 x좌표를 호출한 다음, y좌표를 호출하여 위치 t를 찾게됩니다.",
        +      "params": ["숫자: 곡선의 1번째 제어점 좌표값",
        +                 "숫자: 1번째 점 좌표값",
        +                 "숫자: 2번째 점 좌표값",
        +                 "숫자: 곡선의 2번째 제어점 좌표값",
        +                 "숫자: 0과 1 사이의 값"],
        +      "returns": "숫자: 위치 t에 해당하는 베지어값"
             },
             "curveTangent": {
        -      "description": "计算在 a、b、c、d 点定义的曲线上 t 位置的切线值。a 和 d 参数分别为曲线上第一和最后一个点,而 b 和 c 为控制点。最后一个 t 参数可在 0 和 1 的范围内。",
        -      "params": ["数字:曲线上第一个点的坐标",
        -                 "数字:第一个控制点的坐标",
        -                 "数字:第二个控制点的坐标",
        -                 "数字:曲线上第二个点的坐标",
        -                 "数字:介于 0 和 1 之间的值"],
        -      "returns": "数字:贝塞尔曲线上 t 位置的切线值"
        +      "description": "위치 t에서 곡선의 점 a, b, c, d에 대한 탄젠트를 계산합니다. 매개 변수 a와 d는 각각 곡선 위 점에, b와 c는 제어점에 해당합니다. 마지막 매개 변수인 t는 0과 1사이에서 표현됩니다.",
        +      "params": ["숫자: 곡선의 1번째 점 좌표값",
        +                 "숫자: 1번째 제어점 좌표값",
        +                 "숫자: 2번째 제어점 좌표값",
        +                 "숫자: 곡선의 2번째 점 좌표값",
        +                 "숫자: 0과 1 사이의 값"],
        +      "returns": "숫자: 위치 t에 해당하는 탄젠트"
        +    },
             },
             "beginContour": {
        -      "description": "使用 beginContour() 及 endContour() 函数以在其他形状内创造剪影形状,比如说 “O” 字母内的空间。beginContour() 将开始记录形状的顶点而 endContour() 则停止记录。定义剪影形状的顶点定义的方向(顺时或逆时针)必须和包含它的形状不同。如果外形的顶点是顺时针方向定义的,那么它里面的形状的顶点需是逆时针方向定义。<br><br>这些函数只能在一对 beginShape()/endShape() 函数之间使用而变形函数如 translate()、rotate() 及 scale() 在一对 beginContour()/endContour() 内并不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在里面使用。",
        +      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 테두리를 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
             },
             "beginShape": {
        -      "description": "使用 beginShape() 及 endShape() 函数可让您创造更复杂的形状。beginShape() 将开始记录形状的顶点而 endShape() 则停止记录。所提供的参数将决定由所提供的顶点该画出怎样的形状。如果模式没有被提供,所定义的形状可以是任何不规则的多边形。<br><br>可提供给 beginShape() 的参数包括 POINTS、LINES、TRIANGLES、TRIANGLE_FAN、TRIANGLE_STRIP、QUADS 及 QUAD_STRIP。在调用 beginShape() 函数之后,一系列 vertex() 函数必须接着调用。调用 endShape() 以停止绘制形状。每个形状都将会有由当时外线色所定义的外线色及当时的填充色。<br><br>变形函数如 translate()、rotate() 及 scale() 在 beginShape() 内不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在beginShape()里面使用。",
        -      "params": ["常量:POINTS、LINES、TRIANGLES、TRIANGLE_FAN、TRIANGLE_STRIP、QUADS 或 QUAD_STRIP"],
        +      "description": "beginShape()과 endShape()를 사용하여 좀 더 복잡한 모양을 만들 수 있습니다. beingShape()은 도형의 꼭지점을 기록하기 시작하고, endShape()은 그 기록을 중지합니다. 함수의 매개 변수를 통해 꼭지점으로 어떤 도형을 그릴지 결정할 수 있습니다. 별도의 매개 변수가 지정되지 않으면, 비정형의 다각형이 그려집니다. <br><br>beginShape()에 쓰이는 매개 변수로는 POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP, 그리고 TESS(WebGL 전용)가 있습니다. beginShape() 함수를 호출한 다음, 꼭지점 지정을 위해 vertex() 명령문을 반드시 작성해야 합니다. 도형그리기를 멈추려면 endShape() 함수를 호출하면 됩니다. 각 도형은 현재 지정된 선그리기(stroke) 및 면채우기(fill) 색상으로 그려집니다.",
        +      "params": ["상수: POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS 또는 QUAD_STRIP (선택 사항)"],
               "returns": ""
             },
             "bezierVertex": {
        -      "description": "定义贝塞尔曲线的顶点坐标。每次调用 bezierVertex() 将定义贝塞尔曲线的两个控制点和一个锚点,以在线或形状上增加一个新部分。<br><br>在 beginShape() 内第一次调用 bezierVertex() 之前必须先调用一次 vertex() 以定义第一个锚点。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。",
        -      "params": ["数字:第一个控制点的 x 坐标",
        -                 "数字:第一个控制点的 y 坐标",
        -                 "数字:第二个控制点的 x 坐标",
        -                 "数字:第二个控制点的 y 坐标",
        -                 "数字:第一个锚点的 x 坐标",
        -                 "数字:第二个锚点的 x 坐标"],
        +      "description": "베지어 곡선의 꼭지점 좌표를 지정합니다. bezierVertex()은 매 호출마다 베지어 곡선의 제어점 2개와 고정점 1개의 위치를 정의하고, 이 새로운 선분을 선 또는 도형에 더합니다. bezierVertex()는 WebGL상 2D 및 3D 모드 모두에 적용될 수 있습니다. 2D 모드에서는 6개의 매개 변수가, 3D 모드에서는 9개의 매개 변수(z좌표값 포함)가 필요합니다.<br><br>beginShape() 함수 안에 작성된 bezierVertex()를 호출하기에 앞서, vertex() 함수를 bezierVertex() 윗줄에 작성하여 곡선의 1번째 고정점을 설정해야 합니다. bezierVertex() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야하며, beginShape() 함수에 MODE나 POINTS 매개 변수가 지정되지 않은 경우에만 사용가능 합니다.",
        +      "params": ["숫자: 1번째 제어점의 x좌표값",
        +                 "숫자: 1번째 제어점의 y좌표값",
        +                 "숫자: 2번째 제어점의 x좌표값",
        +                 "숫자: 2번째 제어점의 y좌표값",
        +                 "숫자: 고정점의 x좌표값",
        +                 "숫자: 고정점의 y좌표값",
        +                 "숫자: 1번째 제어점의 z좌표값 (WebGL 모드용)",
        +                 "숫자: 2번째 제어점의 z좌표값 (WebGL 모드용)",
        +                 "숫자: 고정점의 z좌표값 (WebGL 모드용)"],
               "returns": ""
             },
             "curveVertex": {
        -      "description": "定义曲线顶点的坐标。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。<br><br>在一系列 curveVertex() 线条中第一个和最后一个点将被用来引导曲线的起点和终点。至少必须提供四个点以画一个介于第二和第三个点的小曲线。增加第五个点将会在第二、第三及第四个点之间画个曲线。curveVertex() 函数使用的是 Catmull-Rom 样条函数。",
        -      "params": ["数字:顶点的 x 坐标",
        -                 "数字:顶点的 y 坐标"],
        +      "description": "곡선의 꼭지점 좌표를 지정합니다. 이 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야하며, beginShape() 함수에 MODE나 POINTS 매개 변수가 지정되지 않은 경우에만 사용가능 합니다. 또한, 이 함수는 WebGL상 2D 및 3D 모드 모두에 적용될 수 있습니다. 2D 모드에서는 2개의 매개 변수가, 3D 모드에서는 3개의 매개 변수가 필요합니다.<br><br>curveVertex()로 그려진 일련의 선들 중 1번째 점과 마지막 점을 통해 각각 전체 곡선의 시작점과 끝점을 알 수 있습니다. 2번째와 3번째 사이에도 작은 곡선을 만들기 위해선 최소 4개의 점들이 필요합니다. curveVertex() 함수로 5번째 점을 추가하면 함수는 2번째, 3번째, 4번째 점들 사이에 곡선을 그립니다. curveVertex() 함수는 캣멀롬 스플라인(Catmull-Rom Spline)을 구현합니다. ",
        +      "params": ["숫자: 꼭지점의 x좌표값",
        +                 "숫자: 꼭지점의 y좌표값",
        +                 "숫자: 꼭지점의 z좌표값 (WebGL 모드용)(선택 사항)"],
               "returns": ""
             },
             "endContour": {
        -      "description": "使用 beginContour() 及 endContour() 函数以在其他形状内创造剪影形状,比如说 “O” 字母内的空间。beginContour() 将开始记录形状的顶点而 endContour() 则停止记录。定义剪影形状的顶点定义的方向(顺时或逆时针)必须和包含它的形状不同。如果外形的顶点是顺时针方向定义的,那么它里面的形状的顶点需是逆时针方向定义。<br><br>这些函数只能在一对 beginShape()/endShape() 函数之间使用而变形函数如 translate()、rotate() 及 scale() 在一对 beginContour()/endContour() 内并不会有任何效果。其他形状如 ellipse() 或 rect() 也不能在里面使用。",
        +      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 테두리를 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
             },
             "endShape": {
        -      "description": "endShape() 函数和 beginShape() 是一对的而且它只能在 beginShape() 后使用。当 endshape() 被调用时,自上一次 beginShape() 调用后的所有被定义的图像资料将被写进图像缓冲区。定义常量 CLOSE 给 MODE 参数将会关闭该形状(连接起点和终点)。",
        -      "params": ["常量:使用 CLOSE 以关闭形状"],
        +      "description": "endShape()은 beginShape()과 한 쌍을 이루는 함수로, 반드시 beginShape() 다음에 호출될 수 있습니다. endShape() 함수가 호출되면, beginShape() 함수가 호출된 이래로 정의된 모든 이미지 데이터가이미지 버퍼로서 처리됩니다. endShape()의 MODE 매개 변수로는 상수 CLOSE를 씁니다.",
        +      "params": ["상수: CLOSE로 도형 닫기(선택 사항)"],
               "returns": ""
             },
             "quadraticVertex": {
        -      "description": "定义二次贝塞尔曲线顶点的坐标。每次调用 quadraticVertex() 将定义贝塞尔曲线的一个控制点和一个锚点,以在线或形状上增加一个新部分。在 beginShape() 内第一次调用 quadraticVertex() 之前必须先调用一次 vertex() 以定义第一个锚点。这函数只能在 beginShape() 和 endShape() 之间使用并且也只能在 beginShape() 没有任何 MODE(模式)参数的情况下使用。",
        -      "params": ["数字:控制点的 x 坐标",
        -                 "数字:控制点的 y 坐标",
        -                 "数字:锚点的 x 坐标",
        -                 "数字:锚点的 y 坐标"],
        +      "description": "2차 베지어 곡선의 꼭지점 좌표를 지정합니다. quadraticVertex()은 매 호출마다 베지어 곡선의 제어점 1개와 고정점 1개의 위치를 정의하고, 이 새로운 선분을 선 또는 도형에 더합니다. beginShape() 함수 안에 작성된 quadraticVertex()를 호출하기에 앞서, vertex() 함수를 quadraticVertex() 윗줄에 작성하여 곡선의 1번째 고정점을 설정해야 합니다. quadraticVertex()는 WebGL상 2D 및 3D 모드 모두에 적용될 수 있습니다. 2D 모드에서는 6개의 매개 변수가, 3D 모드에서는 9개의 매개 변수(z좌표값 포함)가 필요합니다.<br><br>quadraticVertex() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야하며, beginShape() 함수에 MODE나 POINTS 매개 변수가 지정되지 않은 경우에만 사용가능 합니다.",
        +      "params": ["숫자: 제어점의 x좌표값",
        +                 "숫자: 제어점의 y좌표값",
        +                 "숫자: 고정점의 x좌표값",
        +                 "숫자: 고정점의 y좌표값",
        +                 "숫자: 제어점의 z좌표값 (WebGL 모드용)",
        +                 "숫자: 고정점의 z좌표값 (WebGL 모드용)"],
               "returns": ""
             },
             "vertex": {
        -      "description": "所有形状都是由连接一系列顶点形成的。vertex() 可用于定义点、线、三角形、四角形及多边形的顶点坐标。它只能在 beginShape() 和 endShape() 函数之间使用。",
        -      "params": ["数字:顶点的 x 坐标",
        -                 "数字:顶点的 y 坐标",
        -                 "数字:顶点的 z 坐标",
        -                 "数字:顶点的纹理 u 坐标",
        -                 "数字:顶点的纹理 v 坐标"],
        +      "description": "모든 도형들은 꼭지점 연결을 통해 구축됩니다. vertex() 함수를 사용하여 점, 선, 삼각형, 사각형, 그리고 다각형의 꼭지점 좌표를 지정할 수 있습니다.는 데에 쓰입니다. 이 때, vertex() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야합니다.",
        +      "params": ["숫자: 꼭지점의 x좌표값",
        +                 "숫자: 꼭지점의 y좌표값",
        +                 "숫자: 꼭지점의 z좌표값",
        +                 "숫자: 꼭지점의 u좌표값(선택 사항)",
        +                 "숫자: 꼭지점의 v좌표값(선택 사항)"],
               "returns": ""
             },
             "loadModel": {
        
        From 19138676b96e50df5fec58cbf274c0bc873b2b07 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 16 May 2020 20:48:28 +0900
        Subject: [PATCH 20/36] second push for reflecting reference updates for
         additional korean translation
        
        ---
         src/data/reference/ko.json | 404 +++++++++++++++++++++++++++----------
         1 file changed, 293 insertions(+), 111 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 882c733bbf..71628077d9 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -468,229 +468,409 @@
                          "숫자: 꼭지점의 v좌표값(선택 사항)"],
               "returns": ""
             },
        -    "loadModel": {
        -      "description": "从一个 OBJ 档案加载一个三维模型。<br><br>OBJ 格式的其中一个限制是它没有内建的大小值。这表示不同程式输出的模型可能有非常不同的大小。如果您的模型没被展示的话,请试着调用 loadModel() 并给予 normalized 参数“真”(true)值。这会将模型缩放成适合 p5 的大小。您也可以使用 scale() 函数对您的模型最后大小做与更多的调整。",
        -      "params": ["字符串:要加载的模型的路径",
        -                 "布尔值:如果为真,在加载时将模型缩放成标准大小。",
        -                 "函数(p5.Geometry):此函数将在模型完成加载后被调用,将被给予该三维模型为参数。",
        -                 "函数(Event):如果模型加载失败,此函数将被调用并给予错误事件(event)为参数。"],
        -      "returns": "p5.Geometry:p5.Geometry 物件"
        -    },
        -    "model": {
        -      "description": "将一个三维模型渲染在荧幕上。",
        -      "params": ["p5.Geometry:要渲染的已加载的模型"],
        -      "returns": ""
        -    },
        +   
             "plane": {
        -      "description": "用给予的宽度和高度画一个平面。",
        -      "params": ["数字:平面的宽度",
        -                 "数字:平面的高度",
        -                 "整数:(可选)在 x 轴的三角形细分数",
        -                 "整数:(可选)在 y 轴的三角形细分数"],
        +      "description": "주어진 너비와 높이로 평면을 그립니다.",
        +      "params": ["숫자: 평면의 너비값 (선택 사항)",
        +                 "숫자: 평면의 높이값 (선택 사항)",
        +                 "정수: x-차원상의 삼각 세분면 개수 (선택 사항)",
        +                 "정수: y-차원상의 삼각 세분면 개수 (선택 사항)"],
               "returns": ""
             },
             "box": {
        -      "description": "用给予的宽度、高度及深度画一个立方体。",
        -      "params": ["数字:立方体的宽度",
        -                 "数字:立方体的高度",
        -                 "数字:立方体的深度",
        -                 "整数:(可选)在 x 轴的三角形细分数",
        -                 "整数:(可选)在 y 轴的三角形细分数"],
        +      "description": "주어진 너비, 높이, 깊이로 상자를 그립니다.",
        +      "params": ["숫자: 상자의 너비값 (선택 사항)",
        +                 "숫자: 상자의 높이값 (선택 사항)",
        +                 "숫자: 상자의 깊이값 (선택 사항)",
        +                 "정수: x-차원상의 삼각 세분면 개수 (선택 사항)"
        +                 "정수: y-차원상의 삼각 세분면 개수 (선택 사항)"],
               "returns": ""
             },
             "sphere": {
        -      "description": "用给予的半径画一个球形。",
        -      "params": ["数字:球形的半径",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 16"],
        +      "description": "주어진 반지름으로 구를 그립니다.<br>detailX와 detailY는 각각 구에 대한 x-차원과 y-차원상의 삼각 세분면 개수를 정합니다. 세분면이 많아질수록 구가 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "params": ["숫자: 원의 반지름 (선택 사항)",
        +                 "정수: x-차원상의 삼각 세분면 (선택 사항)
        +                 "정수: y-차원상의 삼각 세분면 (선택 사항)
        +                ],
               "returns": ""
             },
             "cylinder": {
        -      "description": "用给予的半径和高度画一个圆筒形。",
        -      "params": ["数字:表面的半径",
        -                 "数字:圆筒形的高度",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        -                 "整数:y 轴分割的数量,越多分割几何形越平滑,默认值为 1",
        -                 "布尔值:是否该画圆筒形的底部",
        -                 "布尔值:是否该画圆筒形的顶部"],
        +      "description": "주어진 반지름과 높이로 원기둥을 그립니다.<br>detailX와 detailY는 각각 원기둥에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원기둥이 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "params": ["숫자: 표면의 반지름 (선택 사항)",
        +      "params": ["숫자: 원기둥의 높이 (선택 사항)",
        +                 "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
        +                 "정수: y-차원상의 세분면 개수, 기본값은 1 (선택 사항)",
        +                 "불리언: 원기둥의 밑바닥면을 그릴 지의 여부 (선택 사항)",
        +                 "불리언: 원기둥의 윗면을 그릴 지의 여부 (선택 사항)"],
               "returns": ""
             },
             "cone": {
        -      "description": "用给予的半径和高度画一个锥体形。",
        -      "params": ["数字:底部表面的半径",
        -                 "数字:锥体形的高度",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 1",
        -                 "布尔值:是否该画锥体形的底部"],
        +      "description": "주어진 반지름과 높이로 원뿔을 그립니다. <br>detailX와 detailY는 각각 원뿔에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원뿔이 매끄러워집니다. detailX의 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "params": ["숫자: 밑표면의 반지름 (선택 사항)",
        +                 "숫자: 원뿔의 높이 (선택 사항)",
        +                 "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
        +                 "정수: y-차원상의 세분면 개수, 기본값은 1 (선택 사항)",
        +                 "불리언: 원뿔의 밑바닥면을 그릴 지의 여부 (선택 사항)"],
               "returns": ""
             },
             "ellipsoid": {
        -      "description": "用给予的半径画一个椭球形。",
        -      "params": ["数字:椭球形 x 轴的半径",
        -                 "数字:椭球形 y 轴的半径",
        -                 "数字:椭球形 z 轴的半径",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 24。避免多于 150 的细节数量,因为它可能是浏览器停止运作。",
        -                 "整数:分割的数量,越多分割几何形越平滑,默认值为 16。避免多于 150 的细节数量,因为它可能是浏览器停止运作。"],
        +      "description": "주어진 반지름으로 타원면을 그립니다.<br>detailX와 detailY는 각각 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 타원면이 매끄러워집니다. 가급적 detailX와 detailY의 값이 150을 넘어가면 브라우저가 중단될 수 있습니다.",
        +      "params": ["숫자: 타원면의 x-반지름값 (선택 사항)",
        +                 "숫자: 타원면의 y-반지름값 (선택 사항)",
        +                 "숫자: 타원면의 z-반지름값 (선택 사항)",
        +                 "정수: 세분면의 개수, 기본값은 24(선택 사항)"],
               "returns": ""
             },
             "torus": {
        -      "description": "用给予的半径和管半径画一个圆环形。",
        -      "params": ["数字:整个圆环形的半径",
        -                 "数字:圆管的半径",
        -                 "整数:x 轴分割的数量,越多分割几何形越平滑,默认值为 24。",
        -                 "整数:y 轴分割的数量,越多分割几何形越平滑,默认值为 16。"],
        +      "description": "주어진 반지름과 튜브 반지름으로 원환을 그립니다. <br>detailX와 detailY는 각각 원환에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원환이 매끄러워집니다. detailX과 detailY의 권장 최대값은 각각 24와 16입니다. 4나 6처럼 조금 더 적은 값으로 설정하면, 원환이 아닌 새로운 모양을 만들 수 있습니다.",
        +      "params": ["숫자: 전체 원환의 반지름 (선택 사항)",
        +                 "숫자: 튜브의 반지름 (선택 사항)",
        +                 "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항),
        +                 "정수: y-차원상의 세분면 개수, 기본값은 16 (선택 사항)"],
        +      "returns": ""
        +    },
        +     "loadModel": {
        +      "description": "OBJ 또는 STL 파일로부터 3D 모델을 불러옵니다. <br><br> loadModel() 함수는 반드시 preload() 함수 안에 작성되어야 하며, 이로써 3D 모델을 코드 실행에 앞서 온전히 불러올 수 있습니다. <br><br>OBJ와 STL 파일 형식의 한계 중 하나는 빌트인 스케일 기능이 제공되지 않는다는 것입니다. 즉, 파일을 불러오는 소프트웨어 프로그램에 따라 3D 모델의 크기가 상이해집니다. 3D 모델이 보이지 않는다면 loadModel() 함수에 표준화된 매개 변수인 true를 입력해 보세요. 또한 불러온 3D 모델의 크기는 scale() 함수로 변경할 수 있습니다. <br>색상이 지정된 STL 파일은 현재 지원하지 않아, 색상 요소가 제거된 상태로 렌더링될 수 있습니다.",
        +      "params": ["문자열: 불러올 3D 모델의 파일 경로",
        +                 "불리언: 참(true)이면, 3D 모델을 표준화된 크기로 불러오기",
        +                 "함수(p5.Geometry): 3D 모델을 불러온 뒤 일회적으로 호출되는 함수로, 3D 모델 객체를 전달. (선택 사항)",
        +                 "함수(Event):3D 모델 불러오기를 실패할 경우 이벤트 에러와 함께 호출 (선택 사항)"],
        +      "returns": "p5.Geometry: p5.Geometry 객체"
        +    },
        +    "model": {
        +      "description": "화면에 3D 모델을 렌더링합니다.",
        +      "params": ["p5.Geometry: 렌더링할, 불러온 3D 모델"],
               "returns": ""
             },
             "HALF_PI": {
        -      "description": "HALF_PI 是个值为 1.57079632679489661923 的数学常量。它是圆形周长与直径的比例的一半。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "description": "HALF_PI는 1.57079632679489661923 값을 갖는 상수입니다. 지름에 대한 원주율의 절반에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
             },
             "PI": {
        -      "description": "PI 是个值为 3.14159265358979323846 的数学常量。它是圆形周长与直径的比例。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "description": "PI는 3.14159265358979323846 값을 갖는 상수입니다. 지름에 대한 원주율을 의미하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
             },
             "QUARTER_PI": {
        -      "description": "QUARTER_PI 是个值为 0.7853982 的数学常量。它是圆形周长与直径的比例的四分之一。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "description": "QUARTER_PI는 0.7853982 값을 갖는 상수입니다. 지름에 대한 원주율의 1/4에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
             },
             "TAU": {
        -      "description": "TAU 是 TWO_PI 的别名,是个值为 6.28318530717958647693 的数学常量。它是圆形周长与直径的比例的两倍。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "description": "TAU는 TWO_PI의 약어로, 이는 6.28318530717958647693 값을 갖는 상수입니다. 지름에 대한 원주율의 2배에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
             },
             "TWO_PI": {
        -      "description": "TWO_PI 是个值为 6.28318530717958647693 的数学常量。它是圆形周长与直径的比例的两倍。它能有效的与三角函数如 sin() 及 cos() 一起使用。",
        +      "description": "TWO_PI는6.28318530717958647693 값을 갖는 상수입니다. 지름에 대한 원주율의 2배에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
             },
             "DEGREES": {
        -      "description": "与 angleMode() 函数一起使用的常量,用于设定 p5.js 如何解读及计算角度(可以是 DEGREES 或 RADIANS)。",
        +      "description": "p5.js가 각도를 해석하고 계산하는 방법을 설정하기 위해, angleMode() 함수와 그 매개 변수(DEGREES 또는 RADIANS)를 사용합니다.",
               "returns": ""
             },
             "RADIANS": {
        -      "description": "与 angleMode() 函数一起使用的常量,用于设定 p5.js 如何解读及计算角度(可以是 DEGREES 或 RADIANS)。",
        +      "description": "p5.js가 각도를 해석하고 계산하는 방법을 설정하기 위해, angleMode() 함수와 그 매개 변수(DEGREES 또는 RADIANS)를 사용합니다.",
               "returns": ""
             },
             "preload": {
        -      "description": "在 setup() 之前被调用,preload() 函数可用来以阻断的方式处理异步加载外来文件。如果 preload 函数有被定义,setup() 将等到其中的加载工作都完成后才开始执行。preload 函数只能含有加载函数(如 loadImage、loadJSON、loadFont、loadStrings 等)。如果您想使用异步加载,加载函数可在 setup() 内或任何其他地方调用,您只需使用其回调函数参数。<br><br>在默认情况下 “loading...” 字眼将会被显示。如果您想只做您自己的加载页面,只需在您也页面上加个 id 为 “p5_loading” 的 HTML 元素。更多详情请查看<a href='http://bit.ly/2kQ6Nio'>这里</a>。",
        +      "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일의 비동기 불러오기를 차단하기 위해 사용됩니다. preload() 함수로 외부 파일 사전 불러오기가 설정되면, setup() 함수는 불러오기 호출이 완료될 때까지 대기합니다. 불러오기 호출 이외의 다른 함수(loadImage, loadJOSN, loadFont, loadString)는 preload() 함수 안에 포함되지 않아야 합니다. 만약 비동기 불러오기를 선호한다면, 불러오기 메소드를 setup() 함수 안에 포함시키거나, 그 외의 영역에서 callback 매개 변수를 사용하여 호출하면 됩니다.<br> 기본값으로 'loading..'이라는 텍스트가 화면에 나타납니다. 나만의 로딩 페이지를 만들려면 id가 p5_loading으로 지정된 HTML 요소를 추가하면 됩니다. 자세한 정보는 <a href='http://bit.ly/2kQ6Nio'>여기</a>서 확인하세요.",
               "returns": ""
             },
             "setup": {
        -      "description": "setup() 函数将在程式开始时被调用一次。它可在程序开始时被用来定义初始的环境属性如荧幕大小、背景颜色及媒体加载如图像及字体。每个程序只能有一个 setup() 函数并且他不能在一开始执行后再次被调用。<br><br>请注意:在 setup() 内定义的变量并不能在其他函数内使用,这包括 draw() 。",
        +      "description": "setup() 함수는 프로그램 실행시 단 한번 호출됩니다. 함수는 화면 크기나 배경색 등의 초기 환경 요소를 정의하고, 또 이미지나 폰트같은 미디어 파일을 불러오는 데에 쓰입니다. setup() 함수는 프로그램당 한 개씩만 존재할 수 있으며, 최초 한 번 실행된 이후에는 재호출되지 않아야 합니다.<br><br>참고: setup() 함수 안에 선언된 변수는, draw() 함수를 비롯한 여타 함수들이 접근할 수 없습니다.",
               "returns": ""
             },
             "draw": {
        -      "description": "在 setup() 之后被调用,draw() 函数将持续地重复执行其中的代码直到该程式终止或当 noLoop() 被调用。注意如果 noLoop() 在 setup() 内被调用,draw() 仍然会被执行一个然后才停止。draw() 将会自动被调用并不应该被直接调用。<br><br>您应该使用 noLoop()、redraw() 及 loop() 来控制它。当 noLoop() 停止执行 draw() 内的代码,redraw() 会使 draw() 内的代码执行一次,而 loop() 将会使 draw() 内的代码继续重复执行。<br><br>每一秒 draw() 执行的次数可使用 frameRate() 函数来控制。<br><br>每个绘图只能有一个 draw() 函数,而如果您想持续重复执行代码或处理事件如 mousePressed(),draw() 必须存在。有时候您的程式可能会有空白的 draw() 函数,如以上的范例所示。<br><br>请特别注意绘图坐标系统将在每次 draw() 在开始被调用时重置。任何在 draw() 内执行的变形指令(如 scale、rotate、translate)将会在下一个 draw() 开始时复原,所以变形指令并不会随着时间积累。另一方面,样式(如 fill、stroke等)将会持续同样的效果。",
        +      "description": "draw() 함수는 setup() 함수 직후에 호출되며, 프로그램 실행이 중단되거나 noLoop() 함수가 호출되기 전까지 블록 내에 포함된 코드들을 계속 실행합니다. 만약 setup() 함수에서 noLoop()가 호출된다면, draw() 함수는 단 한 번 실행됩니다. draw() 함수는 자동으로 호출되며, 명시적으로 호출하면 안됩니다.<br><br>draw() 함수는 항상 noLoop(), redraw(), 그리고 loop() 함수로 제어됩니다. noLoop()함수가 draw() 함수에 포함된 코드 실행을 멈추면, redraw() 함수가 draw() 함수 안에 포함된 코드들을 한 번만 실행하게 됩니다. loop() 함수의 경우, draw() 함수 안에 있는 코드를 계속해서 반복적으로 실행되게 합니다.<br><br>draw() 함수가 초당 호출되는 횟수는 frameRate() 함수를 통해 조정할 수 있습니다.<br><br>draw() 함수는 한 스케치당 한 번만 작성되어야 하며, 코드를 계속 실행하거나 mousePressed()와 같은 이벤트를 처리할 때 반드시 필요합니다. 때로는 위의 예제처럼 비어있는 draw() 함수를 호출하기도 합니다.<br><br>드로잉의 좌표계가 매 draw() 함수가 호출될 때마다 리셋되는 점에 유의하세요. draw() 함수 안에서 변형 함수(scale, rotate, translate)가 실행될 경우, draw() 함수가 재호출되는 시점에 그 효과들은 무효화되고, 따라서 시간이 지나도 변형 내용이 누적되지 않습니다. 반면, 한 번 선언된 스타일(fill, stroke 등)은 계속해서 적용됩니다.",
               "returns": ""
             },
             "remove": {
        -      "description": "移除整个 p5 绘图。这函数将移除画布及任何由 p5.js 创造的元素。它也会终止绘图循环及解除任何被绑定在窗口对象的属性或函数。它会留下一个 p5 变量以防您还想创造一个新的 p5 绘图。您也可以舍去 p5 = null 以完全删除它。虽然所有由 p5 程式库所创造的函数、变量和物件将会被移除,任何其他由您的代码所定义的公共变量将会被保留。",
        +      "description": "전체 p5 스케치를 제거합니다. 이 함수는 캔버스와 p5.js로 생성한 모든 요소들을 제거합니다. 또한, 그리기 반복(draw loop)를 중지하고, 윈도우 전역 범위에서 선언된 속성이나 메소드의 구속력을 해제합니다. 새로운 p5 스케치를 만들고자 할 경우에는 변수 p5를 남겨둡니다. 원한다면 p5 = null로 처리하여 이를 제거할 수 있습니다. p5 라이브러리로 생성한 모든 함수, 변수, 그리고 객체가 제거되지만, 사용자가 코드로 생성한 여타 전역 변수들은 그대로 유지됩니다.",
        +      "returns": ""
        +    },
        +    "disableFriendlyErrors": {
        +      "description": "스케치를 만드는 동안 '친근한 에러 시스템(Friendly Error System, FES)'을 필요시 비활성화하여 성능을 향상시킵니다. <a href='https://github.com/processing/p5.js/wiki/Optimizing-p5.js-Code-for-Performance#disable-the-friendly-error-system-fes'>친근한 에러 시스템 비활성화하기</a>를 참고하세요.",
               "returns": ""
             },
             "noLoop": {
        -      "description": "停止 p5.js 持续重复执行 draw() 内的代码。如果 loop() 被调用,draw() 内的代码将开始继续重复执行。如果 noLoop() 在 setup() 被调用,它应该是代码块的最后一行代码。<br><br>在使用 noLoop() 时,您并不能在事件处理函数如 mousePressed() 或 keyPressed() 内操纵或存取荧幕。不过您可以使用哪些函数调用 redraw() 或 loop(),从而执行 draw(),以正确的更新荧幕。这表示当 noLoop() 被调用后,您不能绘制任何东西,同时某些函数如 saveFrame() 或 loadPixels() 也不能使用。<br><br>注意如果绘图的大小改变,redraw() 将会被调用以更新绘图,即使 noLoop() 已经被调用,不然绘图将会处于一个奇怪的状态直到 loop() 再次被调用。",
        +      "description": "p5.js가 draw() 함수 안에 포함된 코드를 계속 실행하지 않도록 합니다. loop() 함수가 호출될 경우, draw() 함수 안의 코드가 다시 계속 실행 됩니다. setup() 함수 안에 noLoop() 함수를 사용할 경우, setup() 함수 블록의 가장 마지막 줄에 작성합니다.<br><br>noLoop()을 사용하면, mousePressed()나 keyPressed()와 같은 이벤트 처리 함수를 통해 화면에 접근하거나 조정할 수 없습니다. 대신,  redraw()나 loop() 함수들을 이용하여, 화면 업데이트 함수인 draw()를 재실행시켜 이벤트 처리 함수를 실행할 수 있습니다. 다시 말해, noLoop() 함수가 호출된다는 것은 draw()가 실행되지 않으며, saveFrame()이나 loadPixels()와 같은 함수 역시 사용할 수 없음을 뜻합니다.<br><br>스케치 크기를 재조정하면, noLoop() 함수가 호출되지 않더라도 redraw()가 호출되어 스케치를 업데이트하는 점에 유의하세요. 그렇지 않으면, 스케치는 loop()가 호출될 때까지 요상한 상태에 놓이게 됩니다.",
               "returns": ""
             },
             "loop": {
        -      "description": "在默认下,p5.js 将会循环执行 draw() 内的代码。不过 draw() 循环能使用 noLoop() 停止。在这情况下 draw() 循环可使用 loop() 函数恢复执行。",
        +      "description": "기본값으로, p5.js는 draw() 함수 안에 포함된 코드를 계속해서 반복 실행(loop)합니다. 하지만, draw() 함수의 반복 실행 기능은 noLoop() 함수를 통해 중단될 수 있습니다. 그 경우, draw()의 반복 실행 기능은 loop() 함수를 통해 재개할 수 있습니다.",
               "returns": ""
             },
             "push": {
        -      "description": "push() 函数将储存当时的绘画样式设置及变形,而 pop() 将恢复这些设置。注意这两个函数需要一起使用。它们让您改变样式及变形设置然后再回到您之前的设置。当使用 push() 开始一个新的状态时,它将继续建立在当时的样式和变形上。push() 和 pop() 函数可被重复嵌入以提供更复杂的控制。(请参考第二个范例)<br><br>push() 将现有的变形及样式设置资料储存上来,这包括以下的函数:fill()、stroke()、tint()、strokeWeight()、strokeCap()、strokeJoin()、imageMode()、rectMode()、ellipseMode()、colorMode()、textAlign()、textFont()、textMode()、textSize()、textLeading()。",
        +      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()",
               "returns": ""
             },
             "pop": {
        -      "description": "push() 函数将储存当时的绘画样式设置及变形,而 pop() 将恢复这些设置。注意这两个函数需要一起使用。它们让您改变样式及变形设置然后再回到您之前的设置。当使用 push() 开始一个新的状态时,它将继续建立在当时的样式和变形上。push() 和 pop() 函数可被重复嵌入以提供更复杂的控制。(请参考第二个范例)<br><br>push() 将现有的变形及样式设置资料储存上来,这包括以下的函数:fill()、stroke()、tint()、strokeWeight()、strokeCap()、strokeJoin()、imageMode()、rectMode()、ellipseMode()、colorMode()、textAlign()、textFont()、textMode()、textSize()、textLeading()。"
        +      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()""
             },
             "redraw": {
        -      "description": "执行在 draw() 内的代码一次。这函数让该程序只在需要的时候更新显示窗口,比如说当 mousePressed() 或 keyPressed()事件被触发时。<br><br>再构造程式时,只有在如 mousePressed() 之类的时间内调用 redraw() 才有意义,因为 redraw() 并不会直接调用 draw() (它只会表示绘图有需要更新)。<br><br>redraw() 函数并不会在 draw() 内正常运作。以启用/禁用动画,请使用 loop() 及 noLoop()。<br><br>此外您也能定义每次调用 redraw() 将使 draw() 被调用几次。您这需给予一个整数参数已表示执行的次数。",
        -      "params": ["整数:重绘 n 次。默认值为 1"],
        +      "description": "draw() 함수 안에 포함된 코드를 한 번 재실행합니다. 이 함수를 통해 필요시에만 화면을 업데이트할 수 있습니다. mousePressed()나 keyPressed()가 지정한 이벤트를 발생시킬 때가 그 예입니다.<br><br>프로그램의 구조를 고려하면, mousePressed()와 같은 이벤트 함수에 redraw()를 호출하는 것이 좋습니다. 이는 redraw()가 draw()함수를 즉각적으로 실행시키지 않기 때문입니다. redraw()는 화면 업데이트가 필요함을 알리는 표식 설정만합니다.",
        +      "params": ["정수: n번 간 redraw() 함수 실행. 기본값은 1 (선택 사항)"],
        +      "returns": ""
        +    },
        +    "p5": {
        +      "description": "p5() 생성자로 전역 모드 대신 인스턴스 모드를 활성화할 수 있습니다. 이는 고급 활용 사례에 해당합니다. 간단한 설명과 예제가 아래에 포함되어 있습니다. 자세한 내용은 다니엘 쉬프만(Dan Shiffman)의 Coding Train 비디오 튜토리얼 또는 이 페이지를 참조하세요. <br><br> 기본값으로, 모든 p5.js 함수들은 전역 네임스페이스에 속합니다. (즉, 화면창 객체에 구속됩니다.) 이는, p5.js 함수들을 ellipse(), fill()과 같은 이름으로 불러올 수 있음을 뜻합니다. 하지만, 이러한 방식은 자바스크립트의 여타 (동기식 또는 비동기식) 라이브러리를 사용하거나 긴 코딩을 작성할 때 다소 불편할 수 있습니다. 따라서, p5.js는 인스턴스 모드를 통해 이 문제를 해결할 수 있는 방법을 지원합니다. 인스턴스 모드에서는 모든 p5 함수의 전역 네임 스페이스를 오염시키는 대신, 이를 단일 변수에 구속되게 만듭니다.<br><br>선택적으로, 캔버스나 다른 요소에 추가할 두 번째 인수로서 기본 컨테이너를 지정할 수 있습니다. HTML상 요소의 id나 노드 자체를 추가(append)할 수 있습니다.<br><br>이처럼 인스턴스를 만들면, 단일 웹페이지에 두 개 이상의 p5 스케치를 사용할 수 있게 됩니다. 각각의 고유한 설정 변수에 의거하기 때문입니다. 물론, 전역 모드에서도 iframe 기능을 이용하면 복수의 스케치를 웹페이지에 사용할 수 있습니다.",
        +      "params": ["객체: p5.js 스케치를 포함하는 함수", 
        +                 "문자열|객체: 스케치를 포함할 HTML DOM 노드 ID 또는 포인터"],
               "returns": ""
             },
             "print": {
        -      "description": "print() 函数将写入浏览器的控制台区。这函数适用于查看程式生成的资料。这函数每一次被调用将创造新的一行字串。个别元素可使用引号(\"\")分隔并使用加号(+)连接在一起。",
        -      "params": ["任何:任何要写进控制台的数字、字符串、物件、布尔值或数组的组合"],
        +      "description": "print() 함수는 브라우저 콘솔창에 출력할 때 사용됩니다. 프로그램이 생성하는 데이터를 확인할 때 주로 도움됩니다. 함수는 매번 호출될 때마다 콘솔창에 새로운 텍스트 줄을 만듭니다. 개별 요소는 큰따옴표로 분리하고, 더하기 연산자(+)로 두 요소를 결합할 수 있습니다.<br><br>인수없이 print()를 호출하면, window.print()와 동일하게 브라우저상 인쇄 기능을 켭니다. 콘솔창에 빈 줄을 출력하려면 print('\n')을 작성하면 됩니다.",
        +      "params": ["전부: 출력할 숫자, 문자열, 객체, 불리언, 배열의 조합"],
               "returns": ""
             },
             "frameCount": {
        -      "description": "系统变量 frameCount 存着自程序开始已被展示的影格数量。在 setup() 这值为 0,在第一次执行 draw() 后为 1 等等。",
        +      "description": "시스템 변수 frameCount는 프로그램 시작 이후 화면에 나타난 프레임의 개수를 측정합니다. setup() 함수의 기본값은 0이고, draw() 함수의 첫번째 반복 실행이 마치면 1씩 증가하는 식입니다.",
               "returns": ""
             },
             "focused": {
        -      "description": "确定 p5.js 程式正在运行的窗口是否获得“焦点”,这表示绘图可接受滑鼠或键盘输入。如果窗口获得焦点,次变量为 “true” 否则为 “false”。",
        +      "description": "p5.js 프로그램이 등장하는 화면창의 초점이 맞는지 여부를 확인하며, 이는 곧 스케치가 마우스나 키보드 입력을 허용한다는 것을 의미합니다. 화면창의 초점이 맞으면 변수는 true이고, 그렇지 않으면 false입니다.",
               "returns": ""
             },
             "cursor": {
        -      "description" : "设置鼠标成预定的符号或一个图像,或者如果鼠标被隐藏显示鼠标。如果你想要设置一个图像为鼠标,建议的图像大小为 16x16 或 32x32 像素。 It is not possible to load an image as the cursor if you are exporting your program for the Web, and not all MODES work with all browsers. 参数 x 及 y 必须低于图像的大小。",
        -      "params": ["字符串|常量:ARROW、CROSS、HAND、MOVE、TEXT 或图像的路径",
        -                 "数字:鼠标的横向活跃点",
        -                 "数字:鼠标的直向活跃点"],
        +      "description" : "마우스 커서를 사전에 정의된 기호나 이미지로 설정하거나, 숨김 상태일 경우 이를 해제합니다. 특정 이미지를 커서로 설정할 경우, 권장 사이즈는 16x16 또는 32x32 입니다. 매개 변수 x와 y의 값은 이미지의 실제 크기보다 훨씬 더 작아야 합니다.",
        +      "params": ["문자열|상수: ARROW, CROSS, HAND, MOVE, TEXT, WAIT. CSS 요소인 'grab', 'progress', 'cell' 등. 외부: 커서 이미지의 경로(허용 파일 확장자:.cur, .gif, .jpg, .jpeg, .png, url 주소. 참고: <ah ref='https://developer.mozilla.org/en-US/docs/Web/CSS/cursor'>https://developer.mozilla.org/en-US/docs/Web/CSS/cursor</a>",
        +                 "숫자: 커서의 수평 활성 지점 (32미만으로 지정) (선택 사항)",
        +                 "숫자: 커서의 수직 활성 지점 (32미만으로 지정) (선택 사항)"],
               "returns": ""
             },
             "frameRate": {
        -      "description": "定义每一秒应该显示的影格数。比如说,调用 frameRate(30) 将使绘图每秒刷新 30 次。如果处理器没法跟上所定义的速率,该帧率将不会被达到。建议在 setup() 内设置帧率。默认的帧率值为每秒 60 影格。这和调用 setFrameRate(val) 的效果一样。<br><br>调用 frameRate() 但不给予任何参数将会返回当时的帧率。draw() 函数必须至少执行一次它才会返回帧率。这和调用 getFrameRate() 的效果一样。<br><br>调用 frameRate() 并给予任何不是数字或正数的参数也将会返回当时的帧率。",
        -      "params": ["数字:每一秒该显示的影格数"],
        +      "description": "화면에 나타날 프레임 수를 매 초단위로 지정합니다. 예를 들어, frameRate(30)은 초당 30회씩 새로 고침을 시도합니다. 프로세서가 지정된 속도를 유지할만큼 빠르지 않다면, 프레임 속도에 달성되지 않습니다. setup() 함수 내에서 프레임 속도를 설정하는 것을 권장합니다. 기본값으로 제공되는 프레임 속도는 디스플레이의 프레임 속도(즉, '새로 고침 빈도')를 기준으로 합니다. 초당 24 프레임 정도면 애니메이션을 부드럽게 재생할 수 있습니다. 이 함수는 setFrameRate(val)와 동일한 효과를 갖습니다.<br><br>별도의 인수없이 frameRate() 함수를 호출하면 현재 프레임 속도가 반환됩니다. 프레임 속도를 반환하기 위해서는 draw() 함수를 한 번 이상 실행해야 합니다. 이는 getFrameRate() 함수와도 동일합니다.<br><br>숫자형이 아니거나 양수가 아닌 숫자형의 인수로 frameRate() 함수를 호출하면 마찬가지로 현재 프레임 속도를 반환합니다.",
        +      "params": ["숫자:매 초당 화면에 나타날 프레임 수"],
               "returns": ""
             },
             "noCursor": {
        -      "description": "隐藏鼠标。",
        +      "description": "화면상 커서를 숨깁니다.",
               "returns": ""
             },
         
             "displayWidth": {
        -      "description": "储存整个荧幕宽度的系统变量。这可用来在任何大小的荧幕制作任何大小的全屏程序。",
        +      "description": "pixelDensity() 함수의 기본값에 따라 화면의 너비값을 저장하는 시스템 변수입니다. 모든 디스플레이에서 프로그램을 전체 화면으로 실행시킬 때 사용합니다. 실제 화면 크기값을 반환하려면 여기에 pixelDensity를 곱하면 됩니다.",
               "returns": ""
             },
             "displayHeight": {
        -      "description": "储存整个荧幕高度的系统变量。这可用来在任何大小的荧幕制作任何大小的全屏程序。",
        +      "description": "pixelDensity() 함수의 기본값에 따라 화면의 높이값을 저장하는 시스템 변수입니다. 모든 디스플레이에서 프로그램을 전체 화면으로 실행시킬 때 사용합니다. 실제 화면 크기값을 반환하려면 여기에 pixelDensity를 곱하면 됩니다.",
               "returns": ""
             },
             "windowWidth": {
        -      "description": "储存窗口内部宽度的系统变量, 此函数映射 window.innerWidth。",
        +      "description": "사용자의 윈도우 화면 너비값을 저장해주는 시스템 변수로, window.innerWidth에 매핑됩니다.",
               "returns": ""
             },
             "windowHeight": {
        -      "description": "储存窗口内部高度的系统变量, 此函数映射 window.innerHeight。",
        +      "description": "사용자의 윈도우 화면 높이값을 저장해주는 시스템 변수로, window.innerHeight에 매핑됩니다.",
               "returns": ""
             },
             "windowResized": {
        -      "description": "windowResized() 函数将在每次浏览器窗口缩放时被调用。这是个适合缩放画布及或任何其他调整以符合新的窗口大小的地方。",
        +      "description": "windowResized() 함수는 브라우저 창의 크기가 조정될 때마다 한 번씩 호출됩니다. 캔버스 크기를 재조정하거나 새 윈도우 화면의 크기에 맞춰 조정할 때 유용합니다.",
               "returns": ""
             },
             "width": {
        -      "description": "储存画布宽度的系统变量。这值是由 createCanvas() 函数的第一个参数所定义。比如说,调用函数 createCanvas(320, 240) 将定义此宽度变量为 320。如果一个程式没有使用 createCanvas() 宽度值将默认为 100。",
        +      "description": "생성된 캔버스의 너비값을 저장하는 시스템 변수입니다. 이 값은 createCanvas() 함수의 1번째 매개 변수로서 지정됩니다. createCanvas(320, 240)는 너비 변수를 320으로 설정한 사례입니다. 프로그램에 createCanvase()를 사용하지 않을 경우, 너비는 기본값인 100으로 설정됩니다.",
               "returns": ""
             },
             "height": {
        -      "description": "储存画布高度的系统变量。这值是由 createCanvas() 函数的第二个参数所定义。比如说,调用函数 createCanvas(320, 240) 将定义此高度变量为 240。如果一个程式没有使用 createCanvas() 高度值将默认为 100。",
        +      "description": "생성된 캔버스의 높이값을 저장하는 시스템 변수입니다. 이 값은 createCanvas() 함수의 2번째 매개 변수로서 지정됩니다. createCanvas(320, 240)는 높이 변수를 240으로 설정한 사례입니다. 프로그램에 createCanvase()를 사용하지 않을 경우, 높이는 기본값인 100으로 설정됩니다.",
               "returns": ""
             },
             "fullscreen": {
        -      "description": "如果提供一个参数,依该参数而定该绘图是否是全屏。如果没有给予任何参数,将返回当时的全屏状态。注意因为浏览器限制,此函数只能在使用者输入时调用,比如说在滑鼠点击时如以上范例。",
        -      "params": ["布尔值:该绘图是否应该是全屏"],
        -      "returns": "布尔值:当时的全屏状态"
        +      "description": "주어진 인수값을 기준으로 스케치를 전체 화면으로 설정합니다. 인수를 지정하지 않으면 현재 전체 화면 모드를 반환합니다. 위의 예제는 브라우저 제한으로 인해 마우스 입력과같은 사용자 입력이 있을 때 이 함수를 호출합니다.",
        +      "params": ["불리언: 스케치를 전체 화면 모드로 실행할 지의 여부 (선택 사항)"],
        +      "returns": "불리언: 현재 전체 화면 상태"
             },
             "pixelDensity": {
        -      "description": "定义像素缩放值,用于高像素密度显示器。默认像素密度为显示器的像素密度,可调用 pixelDensity(1) 以关闭此功能。调用 pixelDensity() 并不给予任何参数将返回该绘图的像素密度。",
        -      "params": ["数字:绘图是否应该缩放及缩放多少"],
        -      "returns": "数字:该绘图的像素密度"
        +      "description": "픽셀 밀도가 높은 디스플레이의 픽셀 크기를 조정합니다. pixelDensity()는 그 기본값으로 화면의 픽셀 밀도와 일치하도록 설정되어 있으며, pixelDensity(1)를 호출하여 이를 해제할 수 있습니다. 별도의 인수없이 pixelDensity() 함수를 호출하면, 스케치의 현재 픽셀 밀도가 반환됩니다.",
        +      "params": ["숫자: 스케치의 픽셀 크기를 조정할 지 여부 또는 조정값"],
        +      "returns": ""
             },
             "displayDensity": {
        -      "description": "返回正在运行该绘图的显示器的像素密度。",
        -      "returns": "数字:该显示器的像素密度"
        +      "description": "스케치가 실행 중인 현재 디스플레이의 픽셀 밀도를 반환합니다.",
        +      "returns": "숫자: 디스플레이의 현재 픽셀 밀도"
             },
             "getURL": {
        -      "description": "返回当下的网址。",
        -      "returns": "字符串:网址"
        +      "description": "현재 URL을 받아옵니다.",
        +      "returns": "문자열: url"
             },
             "getURLPath": {
        -      "description": "返回当下的网址的路径数组",
        -      "returns": "字符串[]:路径组"
        +      "description": "현재 URL 경로를 배열로 받아옵니다.",
        +      "returns": "문자 배열[]:경로 요소들"
             },
             "getURLParams": {
        -      "description": "返回当下网址的参数物件",
        -      "returns": "物件:网址参数"
        +      "description": "현재 URL 매개 변수들을 객체로 받아옵니다.",
        +      "returns": "객체: URL 매개 변수들"
             },
        +  "p5.Element": {
        +    "description": "Clase base para todos los elementos añadidos al bosuqejo, incluyendo lienzo, buffers de gráficas, y otros elementos HTML. Los métodos en azul están incluidos en la funcionalidad base, los métodos en marrón son añadidos con la biblioteca p5.dom. No se ejecutan directamente, pero los objetos p5.Element son creados llamando a las funciones createCanvas(), createGraphics(), o en la biblioteca p5.dom, createDiv, createImg, createInput, etc.",
        +    "params": ["String: node DOM envolvente.",
        +    "Objeto: puntero a instancia p5."],
        +    "returns": "TODO"
        +  },
         
        -    "createCanvas": {
        +  "select": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "selectAll": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "removeElements": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "changed": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "input": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createDiv": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createP": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createSpan": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createImg": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createA": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createSlider": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createButton": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createCheckbox": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createSelect": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createRadio": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createColorPicker": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createInput": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createFileInput": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createVideo": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createAudio": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "VIDEO": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "AUDIO": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createCapture": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "createElement": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "p5.MediaElement": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +  "p5.File": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +    
        +  "p5.Graphics": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": "TODO"
        +  },
        +        "createCanvas": {
               "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를  참고하세요.",
               "params": ["숫자: 캔버스의 너비",
               "숫자: 캔버스의 높이",
        @@ -718,8 +898,16 @@
             "blendMode": {
               "description": "根据所设定的模式在显示窗口内混合像素。以下模式选择可用来混合源像素(A)与已经在显示窗口的像素(B):<ul><li><code>BLEND</code> - 颜色线性插值:C = A*系数 + B。这是默认混合模式。</li><li><code>ADD</code> - A 与 B 的总和</li><li><code>DARKEST</code> - 将显示当中最深的颜色:C = min(A*系数, B)。</li><li><code>LIGHTEST </code> - 将显示当中最浅的颜色:C = max(A*系数, B)。</li><li><code>DIFFERENCE</code> - 从底下的图像中减去颜色。</li><li><code>EXCLUSION</code> - 与 DIFFERENCE 相似但不那么强烈。</li><li><code>MULTIPLY</code> - 将颜色相乘,效果一定会更暗。</li><li><code>SCREEN</code> - 与 MULTIPLY 相反,使用颜色的反值。</li><li><code>REPLACE</code> - 像素将完全盖过其他像素并将不会使用透明度值。</li><li><code>OVERLAY</code> - MULTIPLY 及 SCREEN 和混合。暗值将相乘,亮值将相乘反值。</li><li><code>HARD_LIGHT</code> - 当高于 50% 灰时 SCREEN,低于时 MULTIPLY。</li><li><code>SOFT_LIGHT</code> - DARKEST 及 LIGHTEST 的混合。与 OVERLAY 的效果相似,但不那么强烈。</li><li><code>DODGE</code> - 使浅色更浅及增加对比度,忽略暗色。</li><li><code>BURN</code> - 是深色更深及增加对比度,忽略浅色。</li></ul>",
               "params": ["常量:画布的混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL"],
        +      "params": ["常量:画布的混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCdREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL"],
               "returns": ""
             },
        +    "drawingContext": {
        +        "description": "",
        +        "params": ["",
        +        ""],
        +        "returns": "TODO"
        +      },
        +
             "setAttributes": {
               "description": "设置 WebGL 绘图环境的属性。这是调整 WebGL 渲染器的一个方法,可用于微调显示及性能。这函数应该在 setup() 内使用。可使用的属性为:<br>alpha - 表示画布是否有透明度缓冲,默认为 true<br><br>depth - 表示绘图缓冲是否有至少 16 bits 的深度缓冲 - 默认为 true<br><br>stencil - 表示绘图缓冲是否有至少 8 bits 的模版缓冲<br><br>antialias - 表示是否应该执行抗锯齿,默认为 false<br><br>premultipliedAlpha - 表示页面合成器将假设绘图缓冲存在着预乘透明值的颜色,默认为 false<br><br>preserveDrawingBuffer - 如果为真缓冲区将不会被清空并将会保留现有的值直到它们被清空或被作者覆盖(注意 p5 在绘图循环将自动清空),默认为 true<br><br>perPixelLighting - 如果为真,照明着色器将使用个别像素照明。默认为 false",
               "params": ["字符串:属性名",
        @@ -1017,8 +1205,7 @@
               "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표",
               "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비",
               "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"]
        -    }
        -  },
        +    },
             "tint": {
               "description": "定义显示图像的填色值。图像能着色成所定义的颜色或提供透明度值以使其透明化。<br><br>如想是图像透明化但不想影响其颜色,可使用白色为着色值并定义透明度值。比如说,tint(255, 128) 将会使一个图像成为 50% 透明(假设为默认透明度范围 0-255,可使用 colorMode() 调整)。<br><br>灰阶值参数必须低于或等于当时 colorMode() 所定义的最高值。默认最高值为 255。",
               "params": ["数字:红彩值或色调值,需在被定义的范围内",
        @@ -1824,11 +2011,6 @@
                          "Numero: blah"],
               "returns": "TODO"
             }
        -  },
        -  "p5.Element": {
        -    "description": "Clase base para todos los elementos añadidos al bosuqejo, incluyendo lienzo, buffers de gráficas, y otros elementos HTML. Los métodos en azul están incluidos en la funcionalidad base, los métodos en marrón son añadidos con la biblioteca p5.dom. No se ejecutan directamente, pero los objetos p5.Element son creados llamando a las funciones createCanvas(), createGraphics(), o en la biblioteca p5.dom, createDiv, createImg, createInput, etc.",
        -    "params": ["String: node DOM envolvente.",
        -    "Objeto: puntero a instancia p5."],
        -    "returns": "TODO"
           }
        -}
        +  
        +}
        \ No newline at end of file
        
        From b26c50bedf952bb4600a700f1e9b4af2595c061b Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 16 May 2020 22:37:48 +0900
        Subject: [PATCH 21/36] reference page layout updates for additional korean
         translation
        
        ---
         src/data/reference/ko.json | 330 ++++++++++++++++++++++++++++---------
         1 file changed, 253 insertions(+), 77 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 71628077d9..4b27d7b7d1 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -48,14 +48,14 @@
           "Creating & Reading": "만들기 & 읽기", 
           "Setting": "설정하기", 
           "2D Primitives": "2D 기본 조형", 
        -  "Attributes": "설정 요소",  
        +  "Attributes": "설정 속성",  
           "Curves": "곡선", 
           "Vertex": "꼭지점", 
           "3D Models": "3D 모델",  
           "3D Primitives": "3D 기본 조형", 
           "Constants": "상수",  
           "Structure": "구조",  
        -  "Environment": "환경",  
        +  "Environment": "환경 설정",  
           "DOM": "DOM", 
           "Rendering": "렌더링",  
           "Transform": "변형", 
        @@ -86,9 +86,13 @@
           "Font": "폰트", 
           "Lights, Camera": "조명, 카메라",  
           "Camera": "카메라",  
        -  "Lights": "조명",  
        +  "Lights": "라이트",  
           "Material": "재질(Material)", 
           "p5": {
        +      
        +      
        +//Color > Creating & Reading
        +      
            "alpha": {
               "description": "픽셀 배열로부터 알파값을 추출합니다.",
               "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        @@ -146,6 +150,11 @@
               "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
               "returns": "숫자: 채도값"
             },
        +          
        +      
        +//Color > Setting
        +      
        +      
             "background": {
               "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 기본값은 투명입니다. 이 함수는 주로 draw() 함수 안에 위치하며, 매 프레임마다 윈도우 화면을 초기화하기 위해 사용됩니다. 하지만, 애니메이션의 첫 프레임 배경을 지정하거나 배경색을 최초 한번만 지정할 경우, setup() 함수 안에 쓰이기도 합니다. <br> 색상은 현재 색상 모드(colorMode)에 따라 RGB, HSB, 또는 HSL값으로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) 알파값의 기본 제공 범위 역시 0부터 255까지입니다.<br> 단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다. <br> p5.Color 객체를 통해 배경색을 설정할 수 있습니다. <br> p5.Image를 통해 배경 이미지를 설정할 수 있습니다.",
               "params": ["p5.Color: color() 함수로 생성된 모든 값",
        @@ -204,6 +213,11 @@
               "p5.Color: 선의 색상"],
               "returns": "p5 객체"
             },
        +      
        +      
        +//2D Primitives
        +      
        +      
             "arc": {
               "description": "화면에 호, 즉 아치형 선을 그립니다. x좌표, y좌표, w(너비), h(높이), 시작점, 끝점을 지정하면 호는 열린 파이 조각의 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫힌 반원(CHORD), 닫힌 파이 조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 만약 원 하나를 그리기 위해 arc()의 시작점을 0으로, 끝점을 TWO_PI으로 설정할 경우, 시작점과 끝점이 동일하여 아무것도 그려지지 않습니다. 원을 그릴 때는 ellipse() 함수를, 원의 일부를 그릴 때는 arc() 함수를 이용하세요.",
               "params": ["숫자: 호를 포함하는 원의 x좌표",
        @@ -294,6 +308,11 @@
                          "숫자:3번째 꼭지점의 y좌표값"],
               "returns": ""
             },
        +      
        +      
        +//Attributes
        +      
        +      
             "ellipseMode": {
               "description": "ellipse(), circle(), 그리고 arc() 함수의 매개 변수들이 해석되는 방식을 변경하여, 타원이 그려지는 시작점 위치를 변경합니다.<br><br>기본적으로 제공되는 모드는 ellipseMode(CENTER) 함수와도 같습니다. 이는 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로, 3번째와 4번째 변수를 각각 그 너비와 높이값으로서 해석합니다.<br><br>ellipseMode(RADIUS) 역시 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로 해석하나, 3번째와 4번째 변수를 각각 너비와 높이의 중간 지점값으로 해석합니다.<br><br>ellipseMode(CORNER)는 ellipse() 함수의 처음 두 매개 변수를 도형의 좌측 상단을 기준으로 해석하고, 3번째와 4번째 변수를 각각 그 너비와 높이로 해석합니다. <br><br>ellipseMode(CORNERS)는 ellipse() 함수의 처음 두 매개 변수를 도형의 바운딩 박스 중 한 모퉁이의 위치값으로서 해석합니다. 그리고, 3번째와 4번째 변수는 그 정반대 모퉁이의 위치값으로 해석합니다.<br><br>이 함수의 모든 매개 변수(CENTER, RADIUS, CORNER, CORNERS)들은 반드시 대문자로 작성되어야 합니다. 자바스크립트에서는 대소문자 구분이 매우 중요하답니다.",
               "params": ["상수:CENTER, RADIUS, CORNER, 또는 CORNERS"],
        @@ -327,6 +346,11 @@
               "params": ["숫자:선의 두께 (픽셀 단위)"],
               "returns": ""
             },
        +      
        +      
        +//Curves
        +      
        +      
             "bezier": {
               "description": "화면에 3차 베지어 곡선을 그립니다. 베지어 곡선은 일련의 고정점 및 제어점들로 정의됩니다. 처음 두 매개 변수는 1번째 고정점을, 마지막 두 매개 변수는 마지막 고정점을 지정합니다. 중간의 두 매개 변수는 두 개의 제어점을 지정하며, 이는 곧 곡선의 모양을 정의하게 됩니다. 여기서 제어점은 그 자신을 향해 곡선을 당기는 역할을 합니다. <br><br> 베지어 곡선은 프랑스 출신 자동차 엔지니어인 피에르 베지어(Pierre Bezier)가 개발하였으며, 컴퓨터 그래픽상 부드럽게 경사진 곡선을 정의하는 데에 주로 사용됩니다. curve()도 참고하세요.",
               "params": ["숫자: 1번째 고정점의 x좌표값",
        @@ -410,7 +434,11 @@
                          "숫자: 0과 1 사이의 값"],
               "returns": "숫자: 위치 t에 해당하는 탄젠트"
             },
        -    },
        +
        +      
        +//Vertex
        +      
        +      
             "beginContour": {
               "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 테두리를 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
        @@ -469,6 +497,10 @@
               "returns": ""
             },
            
        +    
        +//3D Primitives
        +    
        +    
             "plane": {
               "description": "주어진 너비와 높이로 평면을 그립니다.",
               "params": ["숫자: 평면의 너비값 (선택 사항)",
        @@ -529,6 +561,9 @@
                          "정수: y-차원상의 세분면 개수, 기본값은 16 (선택 사항)"],
               "returns": ""
             },
        +    
        +//3D Models
        +    
              "loadModel": {
               "description": "OBJ 또는 STL 파일로부터 3D 모델을 불러옵니다. <br><br> loadModel() 함수는 반드시 preload() 함수 안에 작성되어야 하며, 이로써 3D 모델을 코드 실행에 앞서 온전히 불러올 수 있습니다. <br><br>OBJ와 STL 파일 형식의 한계 중 하나는 빌트인 스케일 기능이 제공되지 않는다는 것입니다. 즉, 파일을 불러오는 소프트웨어 프로그램에 따라 3D 모델의 크기가 상이해집니다. 3D 모델이 보이지 않는다면 loadModel() 함수에 표준화된 매개 변수인 true를 입력해 보세요. 또한 불러온 3D 모델의 크기는 scale() 함수로 변경할 수 있습니다. <br>색상이 지정된 STL 파일은 현재 지원하지 않아, 색상 요소가 제거된 상태로 렌더링될 수 있습니다.",
               "params": ["문자열: 불러올 3D 모델의 파일 경로",
        @@ -542,6 +577,9 @@
               "params": ["p5.Geometry: 렌더링할, 불러온 3D 모델"],
               "returns": ""
             },
        +    
        +//Constants
        +    
             "HALF_PI": {
               "description": "HALF_PI는 1.57079632679489661923 값을 갖는 상수입니다. 지름에 대한 원주율의 절반에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
        @@ -570,52 +608,9 @@
               "description": "p5.js가 각도를 해석하고 계산하는 방법을 설정하기 위해, angleMode() 함수와 그 매개 변수(DEGREES 또는 RADIANS)를 사용합니다.",
               "returns": ""
             },
        -    "preload": {
        -      "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일의 비동기 불러오기를 차단하기 위해 사용됩니다. preload() 함수로 외부 파일 사전 불러오기가 설정되면, setup() 함수는 불러오기 호출이 완료될 때까지 대기합니다. 불러오기 호출 이외의 다른 함수(loadImage, loadJOSN, loadFont, loadString)는 preload() 함수 안에 포함되지 않아야 합니다. 만약 비동기 불러오기를 선호한다면, 불러오기 메소드를 setup() 함수 안에 포함시키거나, 그 외의 영역에서 callback 매개 변수를 사용하여 호출하면 됩니다.<br> 기본값으로 'loading..'이라는 텍스트가 화면에 나타납니다. 나만의 로딩 페이지를 만들려면 id가 p5_loading으로 지정된 HTML 요소를 추가하면 됩니다. 자세한 정보는 <a href='http://bit.ly/2kQ6Nio'>여기</a>서 확인하세요.",
        -      "returns": ""
        -    },
        -    "setup": {
        -      "description": "setup() 함수는 프로그램 실행시 단 한번 호출됩니다. 함수는 화면 크기나 배경색 등의 초기 환경 요소를 정의하고, 또 이미지나 폰트같은 미디어 파일을 불러오는 데에 쓰입니다. setup() 함수는 프로그램당 한 개씩만 존재할 수 있으며, 최초 한 번 실행된 이후에는 재호출되지 않아야 합니다.<br><br>참고: setup() 함수 안에 선언된 변수는, draw() 함수를 비롯한 여타 함수들이 접근할 수 없습니다.",
        -      "returns": ""
        -    },
        -    "draw": {
        -      "description": "draw() 함수는 setup() 함수 직후에 호출되며, 프로그램 실행이 중단되거나 noLoop() 함수가 호출되기 전까지 블록 내에 포함된 코드들을 계속 실행합니다. 만약 setup() 함수에서 noLoop()가 호출된다면, draw() 함수는 단 한 번 실행됩니다. draw() 함수는 자동으로 호출되며, 명시적으로 호출하면 안됩니다.<br><br>draw() 함수는 항상 noLoop(), redraw(), 그리고 loop() 함수로 제어됩니다. noLoop()함수가 draw() 함수에 포함된 코드 실행을 멈추면, redraw() 함수가 draw() 함수 안에 포함된 코드들을 한 번만 실행하게 됩니다. loop() 함수의 경우, draw() 함수 안에 있는 코드를 계속해서 반복적으로 실행되게 합니다.<br><br>draw() 함수가 초당 호출되는 횟수는 frameRate() 함수를 통해 조정할 수 있습니다.<br><br>draw() 함수는 한 스케치당 한 번만 작성되어야 하며, 코드를 계속 실행하거나 mousePressed()와 같은 이벤트를 처리할 때 반드시 필요합니다. 때로는 위의 예제처럼 비어있는 draw() 함수를 호출하기도 합니다.<br><br>드로잉의 좌표계가 매 draw() 함수가 호출될 때마다 리셋되는 점에 유의하세요. draw() 함수 안에서 변형 함수(scale, rotate, translate)가 실행될 경우, draw() 함수가 재호출되는 시점에 그 효과들은 무효화되고, 따라서 시간이 지나도 변형 내용이 누적되지 않습니다. 반면, 한 번 선언된 스타일(fill, stroke 등)은 계속해서 적용됩니다.",
        -      "returns": ""
        -    },
        -    "remove": {
        -      "description": "전체 p5 스케치를 제거합니다. 이 함수는 캔버스와 p5.js로 생성한 모든 요소들을 제거합니다. 또한, 그리기 반복(draw loop)를 중지하고, 윈도우 전역 범위에서 선언된 속성이나 메소드의 구속력을 해제합니다. 새로운 p5 스케치를 만들고자 할 경우에는 변수 p5를 남겨둡니다. 원한다면 p5 = null로 처리하여 이를 제거할 수 있습니다. p5 라이브러리로 생성한 모든 함수, 변수, 그리고 객체가 제거되지만, 사용자가 코드로 생성한 여타 전역 변수들은 그대로 유지됩니다.",
        -      "returns": ""
        -    },
        -    "disableFriendlyErrors": {
        -      "description": "스케치를 만드는 동안 '친근한 에러 시스템(Friendly Error System, FES)'을 필요시 비활성화하여 성능을 향상시킵니다. <a href='https://github.com/processing/p5.js/wiki/Optimizing-p5.js-Code-for-Performance#disable-the-friendly-error-system-fes'>친근한 에러 시스템 비활성화하기</a>를 참고하세요.",
        -      "returns": ""
        -    },
        -    "noLoop": {
        -      "description": "p5.js가 draw() 함수 안에 포함된 코드를 계속 실행하지 않도록 합니다. loop() 함수가 호출될 경우, draw() 함수 안의 코드가 다시 계속 실행 됩니다. setup() 함수 안에 noLoop() 함수를 사용할 경우, setup() 함수 블록의 가장 마지막 줄에 작성합니다.<br><br>noLoop()을 사용하면, mousePressed()나 keyPressed()와 같은 이벤트 처리 함수를 통해 화면에 접근하거나 조정할 수 없습니다. 대신,  redraw()나 loop() 함수들을 이용하여, 화면 업데이트 함수인 draw()를 재실행시켜 이벤트 처리 함수를 실행할 수 있습니다. 다시 말해, noLoop() 함수가 호출된다는 것은 draw()가 실행되지 않으며, saveFrame()이나 loadPixels()와 같은 함수 역시 사용할 수 없음을 뜻합니다.<br><br>스케치 크기를 재조정하면, noLoop() 함수가 호출되지 않더라도 redraw()가 호출되어 스케치를 업데이트하는 점에 유의하세요. 그렇지 않으면, 스케치는 loop()가 호출될 때까지 요상한 상태에 놓이게 됩니다.",
        -      "returns": ""
        -    },
        -    "loop": {
        -      "description": "기본값으로, p5.js는 draw() 함수 안에 포함된 코드를 계속해서 반복 실행(loop)합니다. 하지만, draw() 함수의 반복 실행 기능은 noLoop() 함수를 통해 중단될 수 있습니다. 그 경우, draw()의 반복 실행 기능은 loop() 함수를 통해 재개할 수 있습니다.",
        -      "returns": ""
        -    },
        -    "push": {
        -      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()",
        -      "returns": ""
        -    },
        -    "pop": {
        -      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()""
        -    },
        -    "redraw": {
        -      "description": "draw() 함수 안에 포함된 코드를 한 번 재실행합니다. 이 함수를 통해 필요시에만 화면을 업데이트할 수 있습니다. mousePressed()나 keyPressed()가 지정한 이벤트를 발생시킬 때가 그 예입니다.<br><br>프로그램의 구조를 고려하면, mousePressed()와 같은 이벤트 함수에 redraw()를 호출하는 것이 좋습니다. 이는 redraw()가 draw()함수를 즉각적으로 실행시키지 않기 때문입니다. redraw()는 화면 업데이트가 필요함을 알리는 표식 설정만합니다.",
        -      "params": ["정수: n번 간 redraw() 함수 실행. 기본값은 1 (선택 사항)"],
        -      "returns": ""
        -    },
        -    "p5": {
        -      "description": "p5() 생성자로 전역 모드 대신 인스턴스 모드를 활성화할 수 있습니다. 이는 고급 활용 사례에 해당합니다. 간단한 설명과 예제가 아래에 포함되어 있습니다. 자세한 내용은 다니엘 쉬프만(Dan Shiffman)의 Coding Train 비디오 튜토리얼 또는 이 페이지를 참조하세요. <br><br> 기본값으로, 모든 p5.js 함수들은 전역 네임스페이스에 속합니다. (즉, 화면창 객체에 구속됩니다.) 이는, p5.js 함수들을 ellipse(), fill()과 같은 이름으로 불러올 수 있음을 뜻합니다. 하지만, 이러한 방식은 자바스크립트의 여타 (동기식 또는 비동기식) 라이브러리를 사용하거나 긴 코딩을 작성할 때 다소 불편할 수 있습니다. 따라서, p5.js는 인스턴스 모드를 통해 이 문제를 해결할 수 있는 방법을 지원합니다. 인스턴스 모드에서는 모든 p5 함수의 전역 네임 스페이스를 오염시키는 대신, 이를 단일 변수에 구속되게 만듭니다.<br><br>선택적으로, 캔버스나 다른 요소에 추가할 두 번째 인수로서 기본 컨테이너를 지정할 수 있습니다. HTML상 요소의 id나 노드 자체를 추가(append)할 수 있습니다.<br><br>이처럼 인스턴스를 만들면, 단일 웹페이지에 두 개 이상의 p5 스케치를 사용할 수 있게 됩니다. 각각의 고유한 설정 변수에 의거하기 때문입니다. 물론, 전역 모드에서도 iframe 기능을 이용하면 복수의 스케치를 웹페이지에 사용할 수 있습니다.",
        -      "params": ["객체: p5.js 스케치를 포함하는 함수", 
        -                 "문자열|객체: 스케치를 포함할 HTML DOM 노드 ID 또는 포인터"],
        -      "returns": ""
        -    },
        +
        +//Environment
        +    
             "print": {
               "description": "print() 함수는 브라우저 콘솔창에 출력할 때 사용됩니다. 프로그램이 생성하는 데이터를 확인할 때 주로 도움됩니다. 함수는 매번 호출될 때마다 콘솔창에 새로운 텍스트 줄을 만듭니다. 개별 요소는 큰따옴표로 분리하고, 더하기 연산자(+)로 두 요소를 결합할 수 있습니다.<br><br>인수없이 print()를 호출하면, window.print()와 동일하게 브라우저상 인쇄 기능을 켭니다. 콘솔창에 빈 줄을 출력하려면 print('\n')을 작성하면 됩니다.",
               "params": ["전부: 출력할 숫자, 문자열, 객체, 불리언, 배열의 조합"],
        @@ -700,8 +695,61 @@
               "description": "현재 URL 매개 변수들을 객체로 받아옵니다.",
               "returns": "객체: URL 매개 변수들"
             },
        +    
        +    
        +//Structure
        +    
        +    "preload": {
        +      "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일의 비동기 불러오기를 차단하기 위해 사용됩니다. preload() 함수로 외부 파일 사전 불러오기가 설정되면, setup() 함수는 불러오기 호출이 완료될 때까지 대기합니다. 불러오기 호출 이외의 다른 함수(loadImage, loadJOSN, loadFont, loadString)는 preload() 함수 안에 포함되지 않아야 합니다. 만약 비동기 불러오기를 선호한다면, 불러오기 메소드를 setup() 함수 안에 포함시키거나, 그 외의 영역에서 callback 매개 변수를 사용하여 호출하면 됩니다.<br> 기본값으로 'loading..'이라는 텍스트가 화면에 나타납니다. 나만의 로딩 페이지를 만들려면 id가 p5_loading으로 지정된 HTML 요소를 추가하면 됩니다. 자세한 정보는 <a href='http://bit.ly/2kQ6Nio'>여기</a>서 확인하세요.",
        +      "returns": ""
        +    },
        +    "setup": {
        +      "description": "setup() 함수는 프로그램 실행시 단 한번 호출됩니다. 함수는 화면 크기나 배경색 등의 초기 환경 요소를 정의하고, 또 이미지나 폰트같은 미디어 파일을 불러오는 데에 쓰입니다. setup() 함수는 프로그램당 한 개씩만 존재할 수 있으며, 최초 한 번 실행된 이후에는 재호출되지 않아야 합니다.<br><br>참고: setup() 함수 안에 선언된 변수는, draw() 함수를 비롯한 여타 함수들이 접근할 수 없습니다.",
        +      "returns": ""
        +    },
        +    "draw": {
        +      "description": "draw() 함수는 setup() 함수 직후에 호출되며, 프로그램 실행이 중단되거나 noLoop() 함수가 호출되기 전까지 블록 내에 포함된 코드들을 계속 실행합니다. 만약 setup() 함수에서 noLoop()가 호출된다면, draw() 함수는 단 한 번 실행됩니다. draw() 함수는 자동으로 호출되며, 명시적으로 호출하면 안됩니다.<br><br>draw() 함수는 항상 noLoop(), redraw(), 그리고 loop() 함수로 제어됩니다. noLoop()함수가 draw() 함수에 포함된 코드 실행을 멈추면, redraw() 함수가 draw() 함수 안에 포함된 코드들을 한 번만 실행하게 됩니다. loop() 함수의 경우, draw() 함수 안에 있는 코드를 계속해서 반복적으로 실행되게 합니다.<br><br>draw() 함수가 초당 호출되는 횟수는 frameRate() 함수를 통해 조정할 수 있습니다.<br><br>draw() 함수는 한 스케치당 한 번만 작성되어야 하며, 코드를 계속 실행하거나 mousePressed()와 같은 이벤트를 처리할 때 반드시 필요합니다. 때로는 위의 예제처럼 비어있는 draw() 함수를 호출하기도 합니다.<br><br>드로잉의 좌표계가 매 draw() 함수가 호출될 때마다 리셋되는 점에 유의하세요. draw() 함수 안에서 변형 함수(scale, rotate, translate)가 실행될 경우, draw() 함수가 재호출되는 시점에 그 효과들은 무효화되고, 따라서 시간이 지나도 변형 내용이 누적되지 않습니다. 반면, 한 번 선언된 스타일(fill, stroke 등)은 계속해서 적용됩니다.",
        +      "returns": ""
        +    },
        +    "remove": {
        +      "description": "전체 p5 스케치를 제거합니다. 이 함수는 캔버스와 p5.js로 생성한 모든 요소들을 제거합니다. 또한, 그리기 반복(draw loop)를 중지하고, 윈도우 전역 범위에서 선언된 속성이나 메소드의 구속력을 해제합니다. 새로운 p5 스케치를 만들고자 할 경우에는 변수 p5를 남겨둡니다. 원한다면 p5 = null로 처리하여 이를 제거할 수 있습니다. p5 라이브러리로 생성한 모든 함수, 변수, 그리고 객체가 제거되지만, 사용자가 코드로 생성한 여타 전역 변수들은 그대로 유지됩니다.",
        +      "returns": ""
        +    },
        +    "disableFriendlyErrors": {
        +      "description": "스케치를 만드는 동안 '친근한 에러 시스템(Friendly Error System, FES)'을 필요시 비활성화하여 성능을 향상시킵니다. <a href='https://github.com/processing/p5.js/wiki/Optimizing-p5.js-Code-for-Performance#disable-the-friendly-error-system-fes'>친근한 에러 시스템 비활성화하기</a>를 참고하세요.",
        +      "returns": ""
        +    },
        +    "noLoop": {
        +      "description": "p5.js가 draw() 함수 안에 포함된 코드를 계속 실행하지 않도록 합니다. loop() 함수가 호출될 경우, draw() 함수 안의 코드가 다시 계속 실행 됩니다. setup() 함수 안에 noLoop() 함수를 사용할 경우, setup() 함수 블록의 가장 마지막 줄에 작성합니다.<br><br>noLoop()을 사용하면, mousePressed()나 keyPressed()와 같은 이벤트 처리 함수를 통해 화면에 접근하거나 조정할 수 없습니다. 대신,  redraw()나 loop() 함수들을 이용하여, 화면 업데이트 함수인 draw()를 재실행시켜 이벤트 처리 함수를 실행할 수 있습니다. 다시 말해, noLoop() 함수가 호출된다는 것은 draw()가 실행되지 않으며, saveFrame()이나 loadPixels()와 같은 함수 역시 사용할 수 없음을 뜻합니다.<br><br>스케치 크기를 재조정하면, noLoop() 함수가 호출되지 않더라도 redraw()가 호출되어 스케치를 업데이트하는 점에 유의하세요. 그렇지 않으면, 스케치는 loop()가 호출될 때까지 예기치 못한 반응을 보일 수 있습니다.",
        +      "returns": ""
        +    },
        +    "loop": {
        +      "description": "기본값으로, p5.js는 draw() 함수 안에 포함된 코드를 계속해서 반복 실행(loop)합니다. 하지만, draw() 함수의 반복 실행 기능은 noLoop() 함수를 통해 중단될 수 있습니다. 그 경우, draw()의 반복 실행 기능은 loop() 함수를 통해 재개할 수 있습니다.",
        +      "returns": ""
        +    },
        +    "push": {
        +      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()",
        +      "returns": ""
        +    },
        +    "pop": {
        +      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()""
        +    },
        +    "redraw": {
        +      "description": "draw() 함수 안에 포함된 코드를 한 번 재실행합니다. 이 함수를 통해 필요시에만 화면을 업데이트할 수 있습니다. mousePressed()나 keyPressed()가 지정한 이벤트를 발생시킬 때가 그 예입니다.<br><br>프로그램의 구조를 고려하면, mousePressed()와 같은 이벤트 함수에 redraw()를 호출하는 것이 좋습니다. 이는 redraw()가 draw()함수를 즉각적으로 실행시키지 않기 때문입니다. redraw()는 화면 업데이트가 필요함을 알리는 표식 설정만합니다.",
        +      "params": ["정수: n번 간 redraw() 함수 실행. 기본값은 1 (선택 사항)"],
        +      "returns": ""
        +    },
        +    "p5": {
        +      "description": "p5() 생성자로 전역 모드 대신 인스턴스 모드를 활성화할 수 있습니다. 이는 고급 활용 사례에 해당합니다. 간단한 설명과 예제가 아래에 포함되어 있습니다. 자세한 내용은 다니엘 쉬프만(Dan Shiffman)의 Coding Train 비디오 튜토리얼 또는 이 페이지를 참조하세요. <br><br> 기본값으로, 모든 p5.js 함수들은 전역 네임스페이스에 속합니다. (즉, 화면창 객체에 구속됩니다.) 이는, p5.js 함수들을 ellipse(), fill()과 같은 이름으로 불러올 수 있음을 뜻합니다. 하지만, 이러한 방식은 자바스크립트의 여타 (동기식 또는 비동기식) 라이브러리를 사용하거나 긴 코딩을 작성할 때 다소 불편할 수 있습니다. 따라서, p5.js는 인스턴스 모드를 통해 이 문제를 해결할 수 있는 방법을 지원합니다. 인스턴스 모드에서는 모든 p5 함수의 전역 네임 스페이스를 오염시키는 대신, 이를 단일 변수에 구속되게 만듭니다.<br><br>선택적으로, 캔버스나 다른 요소에 추가할 두 번째 인수로서 기본 컨테이너를 지정할 수 있습니다. HTML상 요소의 id나 노드 자체를 추가(append)할 수 있습니다.<br><br>이처럼 인스턴스를 만들면, 단일 웹페이지에 두 개 이상의 p5 스케치를 사용할 수 있게 됩니다. 각각의 고유한 설정 변수에 의거하기 때문입니다. 물론, 전역 모드에서도 iframe 기능을 이용하면 복수의 스케치를 웹페이지에 사용할 수 있습니다.",
        +      "params": ["객체: p5.js 스케치를 포함하는 함수", 
        +                 "문자열|객체: 스케치를 포함할 HTML DOM 노드 ID 또는 포인터"],
        +      "returns": ""
        +    },
        +    
        +//DOM
        +    
           "p5.Element": {
        -    "description": "Clase base para todos los elementos añadidos al bosuqejo, incluyendo lienzo, buffers de gráficas, y otros elementos HTML. Los métodos en azul están incluidos en la funcionalidad base, los métodos en marrón son añadidos con la biblioteca p5.dom. No se ejecutan directamente, pero los objetos p5.Element son creados llamando a las funciones createCanvas(), createGraphics(), o en la biblioteca p5.dom, createDiv, createImg, createInput, etc.",
        +    "description": "",
             "params": ["String: node DOM envolvente.",
             "Objeto: puntero a instancia p5."],
             "returns": "TODO"
        @@ -864,56 +912,184 @@
             "returns": "TODO"
           },
             
        +//Rendering
        +    
           "p5.Graphics": {
        -    "description": "",
        -    "params": ["",
        +    "description": "렌더러을 둘러싼 얇은 래퍼(wrapper)로, 그래픽 버퍼 객체를 생성하는 데에 사용합니다. 화면 밖 그래픽 버퍼에 그리려면 이 클래스를 사용하세요. 2개의 매개 변수는 너비와 높이를 픽셀 단위로 지정합니다. 이 클래스의 필드와 메소드는 확장성이 있으나, p5를 위한 일반적인 드로잉 API를 반영합니다.<br>p5.Element를 확장합니다.",
        +    "params": ["숫자: 너비값",
        +               "숫자: 높이값",
        +               "상수: 사용할 렌더러, P2D 또는 WEBGL",
        +               "P5: p5 인스턴스를 가리키는 포인터 (선택 사항)",
             ""],
        -    "returns": "TODO"
        +    "methods": ["그래픽 버퍼 객체로 자동 재설정되지 않은 특정값들(예: 레퍼런스 중 변형(Transform) 또는 라이트(Light) 항목에 해당하는 함수들로서 지정된 값들). 이 메소드를 draw() 함수 안에서 호출하면, 기본 캔버스의 행위를 복제합니다.",
        +               "페이지에서 그래픽 객체를 제거하고 이 객체에 연결된 모든 소스들을 연결 해제합니다."]
           },
        -        "createCanvas": {
        -      "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 시작시에 한번만 실행되어야 합니다. createCanvas()를 1번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 2개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요. 설정한 캔버스 사이즈는 시스템 변수인 width와 height에 각각 저장됩니다. createCanvas() 자체를 생략하면 스케치는 디폴트 사이즈인 100x100픽셀이 됩니다. 캔버스의 위치를 정하는 다른 방식들을 알고싶다면, 위키 페이지의 'positioning the canvas'를  참고하세요.",
        -      "params": ["숫자: 캔버스의 너비",
        -      "숫자: 캔버스의 높이",
        -      "상수: P2D 또는 WEBGL"]
        +  "createCanvas": {
        +      "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 함수 시작시 단 한 번만 실행되어야 합니다. createCanvas()를 한 번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 두 개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요.<br><br>설정된 캔버스 사이즈는 시스템 변수인 너비(width)와 높이(height)에 각각 저장됩니다. createCanvas() 함수를 생략하면, 스케치의 크기는 기본값인 100x100 픽셀로 지정됩니다.<br><br>캔버스의 위치 지정 방법을 알고싶다면, <a href = 'https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>캔버스 위치 지정하기</a> 위키 페이지를 참고하세요.",
        +      "params": ["숫자: 캔버스의 너비값",
        +      "숫자: 캔버스의 높이값",
        +      "상수: P2D 또는 WEBGL (선택 사항)"],
        +      "returns": "p5.Renderer"
             },
               
             "resizeCanvas": {
        -      "description": "缩放画布至给予的宽度和高度。该画布将会马上被清空及调用 draw(),使得画布能在缩放后重新渲染。",
        -      "params": ["数字:画布的宽度",
        -                 "数字:画布的高度",
        -                 "布尔值:不要马上更新画布"],
        +      "description": "주어진 너비와 높이로 캔버스 크기를 재조정합니다. 이 함수를 사용하면 캔버스는 클리어되며, draw() 함수가 곧바로 호출되어 스케치를 재조정된 크기의 캔버스로 다시 렌더링되게 합니다.",
        +      "params": ["숫자: 캔버스의 너비값",
        +                 "숫자: 캔버스의 높이값",
        +                 "불리언: 캔버스를 곧바로 다시 그리지 않도록 처리할지의 여부 (선택 사항)"],
               "returns": ""
             },
             "noCanvas": {
        -      "description": "如果该 p5 绘图不需要画布,此函数将移除默认画布。",
        +      "description": "캔버스가 불필요한 p5 스케치를 위해 기본적으로 제공되는 캔버스를 제거합니다.",
               "returns": ""
             },
             "createGraphics": {
        -      "description": "创造及返回一个新的 p5.Renderer 物件。如果您需要在一个画面外的图形缓冲区作画,您可以使用这个函数。前两个参数将定义宽度和高度像素。",
        -      "params": ["数字:画面外图形缓冲区的宽度",
        -                 "数字:画面外图形缓冲区的高度",
        -                 "常量:P2D 或 WEBGL,默认为 P2D"],
        -      "returns": "buffer gráfico fuera de pantalla"
        +      "description": "새로운 p5.Renderer 객체를 생성하고 반환합니다. 화면 밖 그래픽 버퍼(off-screen graphic buffer)에 그리려면 이 클래스를 사용하세요. 2개의 매개 변수는 너비와 높이를 픽셀 단위로 지정합니다.",
        +      "params": ["숫자: 화면 밖 그래픽 버퍼의 너비값",
        +                 "숫자: 화면 밖 그래픽 버퍼의 높이값",
        +                 "상수:P2D 또는 WEBGL, 기본값은 P2D"],
        +      "returns": "p5.Graphics: 화면 밖 그래픽 버퍼"
             },
             "blendMode": {
        -      "description": "根据所设定的模式在显示窗口内混合像素。以下模式选择可用来混合源像素(A)与已经在显示窗口的像素(B):<ul><li><code>BLEND</code> - 颜色线性插值:C = A*系数 + B。这是默认混合模式。</li><li><code>ADD</code> - A 与 B 的总和</li><li><code>DARKEST</code> - 将显示当中最深的颜色:C = min(A*系数, B)。</li><li><code>LIGHTEST </code> - 将显示当中最浅的颜色:C = max(A*系数, B)。</li><li><code>DIFFERENCE</code> - 从底下的图像中减去颜色。</li><li><code>EXCLUSION</code> - 与 DIFFERENCE 相似但不那么强烈。</li><li><code>MULTIPLY</code> - 将颜色相乘,效果一定会更暗。</li><li><code>SCREEN</code> - 与 MULTIPLY 相反,使用颜色的反值。</li><li><code>REPLACE</code> - 像素将完全盖过其他像素并将不会使用透明度值。</li><li><code>OVERLAY</code> - MULTIPLY 及 SCREEN 和混合。暗值将相乘,亮值将相乘反值。</li><li><code>HARD_LIGHT</code> - 当高于 50% 灰时 SCREEN,低于时 MULTIPLY。</li><li><code>SOFT_LIGHT</code> - DARKEST 及 LIGHTEST 的混合。与 OVERLAY 的效果相似,但不那么强烈。</li><li><code>DODGE</code> - 使浅色更浅及增加对比度,忽略暗色。</li><li><code>BURN</code> - 是深色更深及增加对比度,忽略浅色。</li></ul>",
        -      "params": ["常量:画布的混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL"],
        -      "params": ["常量:画布的混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCdREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL"],
        +      "description": "지정된 모드에 따라 디스플레이 화면상의 픽셀들을 혼합합니다. 소스 픽셀 (A)를 디스플레이 화면 (B)상에 있는 픽셀과 혼합하기 위해 다음 모드를 선택할 수 있습니다:<br><ul><li><code>BLEND</code> - 색상 선형 보간:C = (A)\*계수 + (B). 기본 혼합 모드입니다.</li><li><code>ADD</code> - (A)와 (B)의 합</li><li><code>DARKEST</code> - 가장 어두운 색상만 혼합됩니다:C = min(A*계수, B).</li><li><code>LIGHTEST </code> - 가장 밝은 색상만 혼합됩니다.:C = max(A*계수, B).</li><li><code>DIFFERENCE</code> - 기본 이미지에서 색상값을 뺄셈합니다.</li><li><code>EXCLUSION</code> - DIFFERENCE와 유사하지만 덜 극적입니다.</li><li><code>MULTIPLY</code> - 색상을 곱하는 것으로, 결과값은 좀 더 어둡습니다.</li><li><code>SCREEN</code> - MULTIPLY와 반대로 색상의 반전된 값을 사용합니다.</li><li><code>REPLACE</code> - 픽셀이 다른 픽셀을 완전히 대체하며 알파값(투명도)를 사용하지 않습니다.</li><li><code>OVERLAY</code> - MULTIPLY와 SCREEN의 혼합으로, 어두운 값을 곱하고 밝은 값의 반전된 값을 사용합니다. (2D)</li><li><code>HARD_LIGHT</code> - 회색값이 50%보다 높으면 SCREEN로, 낮으면 MULTIPLY로 처리합니다. (2D)</li><li><code>SOFT_LIGHT</code> - DARKEST와 LIGHTEST 혼합으로, OVERLAY처럼 작동하나 덜 강합니다. (2D)</li><li><code>DODGE</code> - 밝은 색조를 더 밝게 처리하고 대비를 높이며, 어두운 영역은 무시합니다. (2D)</li><li><code>BURN</code> - 어두운 영역이 적용되어 대비가 증가하고 밝기는 무시됩니다. (2D)</li><li><code>SUBTRACT</code> - (A)와 (B)의 나머지(3D)</li></ul><br><br>(2D)는 2D 렌더러에서만 작동하는 혼합 모드를 뜻합니다.<br>(3D)는 WEBGL 렌더러에서만 작동하는 혼합 모드를 뜻합니다.",
        +      "params": ["상수:캔버스에 설정되는 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD, REMOVE 또는 SUBTRACT 중 하나"]
               "returns": ""
             },
             "drawingContext": {
        -        "description": "",
        +        "description": "p5.js API는 다양한 그래픽 제작 기능들을 제공하지만, p5에 노출되지 않는 HTML5 고유의 캔버스 기능이 있습니다. 그러한 기능들은 예제처럼 drawingContext 변수를 사용하여 직접 호출할 수 있습니다. 이는 canvas.getContext('2d') 또는 canvas.getContext('webgl') 함수를 호출하는 것과도 같습니다. 호출 가능한 함수를 확인하려면 <a href ='https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D'>기본 캔버스 API 레퍼런스</a>를 참고하세요.",
                 "params": ["",
                 ""],
                 "returns": "TODO"
               },
         
             "setAttributes": {
        -      "description": "设置 WebGL 绘图环境的属性。这是调整 WebGL 渲染器的一个方法,可用于微调显示及性能。这函数应该在 setup() 内使用。可使用的属性为:<br>alpha - 表示画布是否有透明度缓冲,默认为 true<br><br>depth - 表示绘图缓冲是否有至少 16 bits 的深度缓冲 - 默认为 true<br><br>stencil - 表示绘图缓冲是否有至少 8 bits 的模版缓冲<br><br>antialias - 表示是否应该执行抗锯齿,默认为 false<br><br>premultipliedAlpha - 表示页面合成器将假设绘图缓冲存在着预乘透明值的颜色,默认为 false<br><br>preserveDrawingBuffer - 如果为真缓冲区将不会被清空并将会保留现有的值直到它们被清空或被作者覆盖(注意 p5 在绘图循环将自动清空),默认为 true<br><br>perPixelLighting - 如果为真,照明着色器将使用个别像素照明。默认为 false",
        -      "params": ["字符串:属性名",
        -                 "布尔值:属性的新值",
        -                 "物件:有键值对的物件"]
        +      "description": "WebGL 드로잉 컨텍스트의 속성을 설정하여 WebGL 렌더러가 화면과 성능을 미세 조정할 수 있도록 합니다.<br><br> WebGL 캔버스를 생성한 후에 이 함수를 호출하면 드로잉 컨텍스트가 다시 초기화되는 점에 유의하세요. <br><br>객체가 매개 변수로 전달될 경우, 객체에 선언되지 않은 모든 속성은 기본값으로 처리됩니다.<br><br>사용한 가능한 속성은 다음과 같습니다:<br>alpha - 캔버스에 알파 버퍼가 있는지의 여부를 나타냅니다. 기본값은 참(true)입니다.<br>stencil - 드로잉 버퍼에 8비트 이상의 스텐실 버퍼가 있는지 여부를 나타냅니다.<br>antialias - 안티앨리어싱 기본값을 수행할지 여부를 나타냅니다. (Safari에서는 참)<br>premultipliedAlpha -   드로잉 버퍼에 포함된 색상이 미리 곱해진 알파 기본값을 포함하는 지의 여부에 대해, 페이지 컴포지터가 거짓(false)으로 가정하고 있음을 나타냅니다.<br>perPixelLighting - 참(true)이라면, 픽셀당 라이팅(per-pixel Lighting)이 라이팅 셰이더에 사용됩니다. 그렇지 않다면, 꼭지점당 라이팅(per-vertex lighting)이 사용됩니다. 기본값은 참입니다.",
        +      "params": ["문자열: 속성명",
        +                 "불리언: 명명된 속성의 새로운 값",
        +                 "객체: 주요값들의 쌍을 갖는 객체"]
             },
        +
        +      
        +
        +//Foundation
        +
        +      
        +  "let": {
        +    "description": "새로운 변수를 생성하고 그 이름을 지정합니다. 변수는 값을 담는 컨테이너입니다.<br>let으로 선언된 변수는 블록 단위의 적용 범위를 갖습니다. 즉, 변수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let'>MDN Entry</a>에서 발췌: 블록 범위의 지역 변수를 선언하고, 선택적으로 그 값을 초기화합니다.",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +    
        +  "const": {
        +    "description": "새로운 상수를 생성하고 그 이름을 지정합니다. 마치 let으로 생성된 변수처럼, const로 생성된 상수는 값을 담는 컨테이너입니다. 하지만, 상수는 한 번 산언된 다음 변경할 수 없습니다.<br>const로 선언된 상수는 블록 단위의 적용 범위를 갖습니다. 즉, 상수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다. 상수는 자신이 존재하고 있는 범위 내에서 재선언될 수 없습니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const'>MDN Entry</a>에서 발췌: 읽어오기만 가능한 상수를 선언합니다. const는 블록 단위로 적용되며, let으로 선언된 변수들과 유사합니다. 상수값은 재지정을 통해 변경될 수 없으며, 재선언될 수 없습니다.",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "===": {
        +    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 평가됩니다.",
        +    "params": ["여기까지하다가맒",
        +    ""],
        +    "returns": ""
        +  },
        +  ">": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  ">=": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "<": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "<=": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "if-else": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "function": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "return": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "boolean": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "string": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "number": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "object": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "class": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "for": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "while": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "JSON": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +  "console": {
        +    "description": "",
        +    "params": ["",
        +    ""],
        +    "returns": ""
        +  },
        +    
             "applyMatrix": {
               "description": "将现有的矩阵乘于由参数所定义的矩阵。这是个强大的功能并能够同时执行平移、缩放、切变及旋转。您能在<a href='https://zh.wikipedia.org/wiki/%E5%8F%98%E6%8D%A2%E7%9F%A9%E9%98%B5'>维基百科</a>了解更多关于变形矩阵的资讯。<br><br>这里的参数命名跟着 <a href='https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform'>WHATWG 规范</a>(英文页面)的命名方式并代表着一个如下的变形矩阵:<blockquote><p><img style='max-width: 150px' src='assets/transformation-matrix.png' alt='当 applyMatrix 被调用时所使用的变形矩阵'></p></blockquote>",
               "params": ["数字:定义该乘于的 2x3 矩阵",
        
        From 28321d6b0c97727377a0c3d683737b184603a85e Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sat, 16 May 2020 22:44:08 +0900
        Subject: [PATCH 22/36] quick update on === description
        
        ---
         src/data/reference/ko.json | 8 ++++----
         1 file changed, 4 insertions(+), 4 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 4b27d7b7d1..9c1984693b 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -982,19 +982,19 @@
           },
             
           "const": {
        -    "description": "새로운 상수를 생성하고 그 이름을 지정합니다. 마치 let으로 생성된 변수처럼, const로 생성된 상수는 값을 담는 컨테이너입니다. 하지만, 상수는 한 번 산언된 다음 변경할 수 없습니다.<br>const로 선언된 상수는 블록 단위의 적용 범위를 갖습니다. 즉, 상수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다. 상수는 자신이 존재하고 있는 범위 내에서 재선언될 수 없습니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const'>MDN Entry</a>에서 발췌: 읽어오기만 가능한 상수를 선언합니다. const는 블록 단위로 적용되며, let으로 선언된 변수들과 유사합니다. 상수값은 재지정을 통해 변경될 수 없으며, 재선언될 수 없습니다.",
        +    "description": "새로운 상수를 생성하고 그 이름을 지정합니다. 마치 let으로 생성된 변수처럼, const로 생성된 상수는 값을 담는 컨테이너입니다. 하지만, 상수는 한 번 산언된 다음 변경할 수 없습니다.<br>const로 선언된 상수는 블록 단위의 적용 범위를 갖습니다. 즉, 상수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다. 상수는 자신이 존재하고 있는 범위 내에서 재선언될 수 없습니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const'>MDN Entry</a>에서 발췌: 읽기만 가능한 상수를 선언합니다. const는 블록 단위로 적용되며, let으로 선언된 변수들과 유사합니다. 상수값은 재지정을 통해 변경될 수 없으며, 재선언될 수 없습니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "===": {
        -    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 평가됩니다.",
        -    "params": ["여기까지하다가맒",
        +    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 평가됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN Entry</a>에서 발췌: 이 연산자는 피연산자들이 동일한 값이 아니고/또는 동일한 유형이 아닐 때 참(true)을 반환합니다.<br>웹상의 몇몇 예제에서 피연산자 간의 비교를 위해 이중 등호 기호(==)를 사용하는 것을 볼 수 있습니다. 이는 자바스크립트상의 완전 항등 연산자(===)에 해당하지 않으며, 두 피연산자들의 값들을 비교하기에 앞서, 그 유형이 동일한지의 여부를 비교하게 됩니다.",
        +    "params": ["",
             ""],
             "returns": ""
           },
           ">": {
        -    "description": "",
        +    "description": "여기까지하다가맒",
             "params": ["",
             ""],
             "returns": ""
        
        From 1c48d2ef97be42d5743dc6f3543fe3664a1f8f8f Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sun, 17 May 2020 14:33:44 +0900
        Subject: [PATCH 23/36] 2nd update for reference page layout in ko
        
        ---
         .../examples/ko/18_Transform/00_Translate.js  |   8 +-
         src/data/reference/ko.json                    | 676 ++++++++++--------
         2 files changed, 394 insertions(+), 290 deletions(-)
        
        diff --git a/src/data/examples/ko/18_Transform/00_Translate.js b/src/data/examples/ko/18_Transform/00_Translate.js
        index 69f5a29aa1..12e6657c7b 100644
        --- a/src/data/examples/ko/18_Transform/00_Translate.js
        +++ b/src/data/examples/ko/18_Transform/00_Translate.js
        @@ -1,9 +1,9 @@
         /*
        - * @name 변환(Translate)
        + * @name 이동(Translate)
          * @description translate() 함수는 객체를 화면 내 어떤 위치로든 이동하게 합니다.
          * 그 첫 번째 매개변수는 x축의 오프셋(offset)을,
          * 두 번째 매개변수는 y축의 오프셋을 지정합니다.
        - * 이 예제는 이러한 변환들이 축적되는 것을 보여줍니다.
        + * 이 예제는 이러한 이동들이 축적되는 것을 보여줍니다.
          */
         
         let x = 0;
        @@ -25,12 +25,12 @@ function draw() {
           }
         
           // rect 명령어는 원점을 중심점으로 삼는 도형을 그리지만,
        -  // translate은 이를 새로운 x와 y 위치로 옮깁니다.
        +  // translate(이동)은 이를 새로운 x와 y 위치로 옮깁니다.
           translate(x, height / 2 - dim / 2);
           fill(255);
           rect(-dim / 2, -dim / 2, dim, dim);
         
        -  // translate(변환)은 축적됩니다. 이 rect가 다른 rect와
        +  // translate(이동)은 축적됩니다. 이 rect가 다른 rect와
           // 동일한 x축값 매개변수를 가졌음에도
           // 두 배로 빠르게 움직이는 걸 볼 수 있습니다.
           translate(x, dim);
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 9c1984693b..e5d557d9d0 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -84,7 +84,7 @@
           "Trigonometry": "삼각법",  
           "Typography": "타이포그래피", 
           "Font": "폰트", 
        -  "Lights, Camera": "조명, 카메라",  
        +  "Lights, Camera": "라이트, 카메라",  
           "Camera": "카메라",  
           "Lights": "라이트",  
           "Material": "재질(Material)", 
        @@ -215,7 +215,7 @@
             },
               
               
        -//2D Primitives
        +// Shape > 2D Primitives
               
               
             "arc": {
        @@ -310,7 +310,7 @@
             },
               
               
        -//Attributes
        +// Shape > Attributes
               
               
             "ellipseMode": {
        @@ -348,7 +348,7 @@
             },
               
               
        -//Curves
        +// Shape > Curves
               
               
             "bezier": {
        @@ -436,7 +436,7 @@
             },
         
               
        -//Vertex
        +// Shape > Vertex
               
               
             "beginContour": {
        @@ -498,11 +498,11 @@
             },
            
             
        -//3D Primitives
        +// Shape > 3D Primitives
             
             
             "plane": {
        -      "description": "주어진 너비와 높이로 평면을 그립니다.",
        +      "description": "사용자가 지정한 너비와 높이로 평면을 그립니다.",
               "params": ["숫자: 평면의 너비값 (선택 사항)",
                          "숫자: 평면의 높이값 (선택 사항)",
                          "정수: x-차원상의 삼각 세분면 개수 (선택 사항)",
        @@ -510,7 +510,7 @@
               "returns": ""
             },
             "box": {
        -      "description": "주어진 너비, 높이, 깊이로 상자를 그립니다.",
        +      "description": "사용자가 지정한 너비, 높이, 깊이로 상자를 그립니다.",
               "params": ["숫자: 상자의 너비값 (선택 사항)",
                          "숫자: 상자의 높이값 (선택 사항)",
                          "숫자: 상자의 깊이값 (선택 사항)",
        @@ -519,7 +519,7 @@
               "returns": ""
             },
             "sphere": {
        -      "description": "주어진 반지름으로 구를 그립니다.<br>detailX와 detailY는 각각 구에 대한 x-차원과 y-차원상의 삼각 세분면 개수를 정합니다. 세분면이 많아질수록 구가 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "description": "사용자가 지정한 반지름으로 구를 그립니다.<br>detailX와 detailY는 각각 구에 대한 x-차원과 y-차원상의 삼각 세분면 개수를 정합니다. 세분면이 많아질수록 구가 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
               "params": ["숫자: 원의 반지름 (선택 사항)",
                          "정수: x-차원상의 삼각 세분면 (선택 사항)
                          "정수: y-차원상의 삼각 세분면 (선택 사항)
        @@ -527,7 +527,7 @@
               "returns": ""
             },
             "cylinder": {
        -      "description": "주어진 반지름과 높이로 원기둥을 그립니다.<br>detailX와 detailY는 각각 원기둥에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원기둥이 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "description": "사용자가 지정한 반지름과 높이로 원기둥을 그립니다.<br>detailX와 detailY는 각각 원기둥에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원기둥이 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
               "params": ["숫자: 표면의 반지름 (선택 사항)",
               "params": ["숫자: 원기둥의 높이 (선택 사항)",
                          "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
        @@ -537,7 +537,7 @@
               "returns": ""
             },
             "cone": {
        -      "description": "주어진 반지름과 높이로 원뿔을 그립니다. <br>detailX와 detailY는 각각 원뿔에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원뿔이 매끄러워집니다. detailX의 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        +      "description": "사용자가 지정한 반지름과 높이로 원뿔을 그립니다. <br>detailX와 detailY는 각각 원뿔에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원뿔이 매끄러워집니다. detailX의 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
               "params": ["숫자: 밑표면의 반지름 (선택 사항)",
                          "숫자: 원뿔의 높이 (선택 사항)",
                          "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
        @@ -546,7 +546,7 @@
               "returns": ""
             },
             "ellipsoid": {
        -      "description": "주어진 반지름으로 타원면을 그립니다.<br>detailX와 detailY는 각각 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 타원면이 매끄러워집니다. 가급적 detailX와 detailY의 값이 150을 넘어가면 브라우저가 중단될 수 있습니다.",
        +      "description": "사용자가 지정한 반지름으로 타원면을 그립니다.<br>detailX와 detailY는 각각 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 타원면이 매끄러워집니다. 가급적 detailX와 detailY의 값이 150을 넘어가면 브라우저가 중단될 수 있습니다.",
               "params": ["숫자: 타원면의 x-반지름값 (선택 사항)",
                          "숫자: 타원면의 y-반지름값 (선택 사항)",
                          "숫자: 타원면의 z-반지름값 (선택 사항)",
        @@ -554,7 +554,7 @@
               "returns": ""
             },
             "torus": {
        -      "description": "주어진 반지름과 튜브 반지름으로 원환을 그립니다. <br>detailX와 detailY는 각각 원환에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원환이 매끄러워집니다. detailX과 detailY의 권장 최대값은 각각 24와 16입니다. 4나 6처럼 조금 더 적은 값으로 설정하면, 원환이 아닌 새로운 모양을 만들 수 있습니다.",
        +      "description": "사용자가 지정한 반지름과 튜브 반지름으로 원환을 그립니다. <br>detailX와 detailY는 각각 원환에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원환이 매끄러워집니다. detailX과 detailY의 권장 최대값은 각각 24와 16입니다. 4나 6처럼 조금 더 적은 값으로 설정하면, 원환이 아닌 새로운 모양을 만들 수 있습니다.",
               "params": ["숫자: 전체 원환의 반지름 (선택 사항)",
                          "숫자: 튜브의 반지름 (선택 사항)",
                          "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항),
        @@ -562,7 +562,7 @@
               "returns": ""
             },
             
        -//3D Models
        +// Shape > 3D Models
             
              "loadModel": {
               "description": "OBJ 또는 STL 파일로부터 3D 모델을 불러옵니다. <br><br> loadModel() 함수는 반드시 preload() 함수 안에 작성되어야 하며, 이로써 3D 모델을 코드 실행에 앞서 온전히 불러올 수 있습니다. <br><br>OBJ와 STL 파일 형식의 한계 중 하나는 빌트인 스케일 기능이 제공되지 않는다는 것입니다. 즉, 파일을 불러오는 소프트웨어 프로그램에 따라 3D 모델의 크기가 상이해집니다. 3D 모델이 보이지 않는다면 loadModel() 함수에 표준화된 매개 변수인 true를 입력해 보세요. 또한 불러온 3D 모델의 크기는 scale() 함수로 변경할 수 있습니다. <br>색상이 지정된 STL 파일은 현재 지원하지 않아, 색상 요소가 제거된 상태로 렌더링될 수 있습니다.",
        @@ -670,7 +670,7 @@
               "returns": ""
             },
             "fullscreen": {
        -      "description": "주어진 인수값을 기준으로 스케치를 전체 화면으로 설정합니다. 인수를 지정하지 않으면 현재 전체 화면 모드를 반환합니다. 위의 예제는 브라우저 제한으로 인해 마우스 입력과같은 사용자 입력이 있을 때 이 함수를 호출합니다.",
        +      "description": "사용자가 지정한 인수값을 기준으로 스케치를 전체 화면으로 설정합니다. 인수를 지정하지 않으면 현재 전체 화면 모드를 반환합니다. 위의 예제는 브라우저 제한으로 인해 마우스 입력과같은 사용자 입력이 있을 때 이 함수를 호출합니다.",
               "params": ["불리언: 스케치를 전체 화면 모드로 실행할 지의 여부 (선택 사항)"],
               "returns": "불리언: 현재 전체 화면 상태"
             },
        @@ -689,7 +689,7 @@
             },
             "getURLPath": {
               "description": "현재 URL 경로를 배열로 받아옵니다.",
        -      "returns": "문자 배열[]:경로 요소들"
        +      "returns": "문자열 배열[]:경로 요소들"
             },
             "getURLParams": {
               "description": "현재 URL 매개 변수들을 객체로 받아옵니다.",
        @@ -933,7 +933,7 @@
             },
               
             "resizeCanvas": {
        -      "description": "주어진 너비와 높이로 캔버스 크기를 재조정합니다. 이 함수를 사용하면 캔버스는 클리어되며, draw() 함수가 곧바로 호출되어 스케치를 재조정된 크기의 캔버스로 다시 렌더링되게 합니다.",
        +      "description": "사용자가 지정한 너비와 높이로 캔버스 크기를 재조정합니다. 이 함수를 사용하면 캔버스는 클리어되며, draw() 함수가 곧바로 호출되어 스케치를 재조정된 크기의 캔버스로 다시 렌더링되게 합니다.",
               "params": ["숫자: 캔버스의 너비값",
                          "숫자: 캔버스의 높이값",
                          "불리언: 캔버스를 곧바로 다시 그리지 않도록 처리할지의 여부 (선택 사항)"],
        @@ -988,170 +988,354 @@
             "returns": ""
           },
           "===": {
        -    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 평가됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN Entry</a>에서 발췌: 이 연산자는 피연산자들이 동일한 값이 아니고/또는 동일한 유형이 아닐 때 참(true)을 반환합니다.<br>웹상의 몇몇 예제에서 피연산자 간의 비교를 위해 이중 등호 기호(==)를 사용하는 것을 볼 수 있습니다. 이는 자바스크립트상의 완전 항등 연산자(===)에 해당하지 않으며, 두 피연산자들의 값들을 비교하기에 앞서, 그 유형이 동일한지의 여부를 비교하게 됩니다.",
        +    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 연산됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN Entry</a>에서 발췌: 이 연산자는 피연산자들이 동일한 값이 아니고/또는 동일한 유형이 아닐 때 참(true)을 반환합니다.<br>웹상의 몇몇 예제에서 피연산자 간의 비교를 위해 이중 등호(==)를 사용하는 것을 볼 수 있습니다. 이는 자바스크립트상의 완전 항등 연산자(===)에 해당하지 않으며, 두 피연산자의 값들을 비교하기에 앞서, 그 유형이 동일한지의 여부를 비교하게 됩니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           ">": {
        -    "description": "여기까지하다가맒",
        +    "description": "비교 연산자 > 는 왼쪽 값이 오른쪽 값보다 큰 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           ">=": {
        -    "description": "",
        +    "description": "비교 연산자 >= 는 왼쪽 값이 오른쪽 값보다 크거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           "<": {
        -    "description": "",
        +    "description": "비교 연산자 < 는 왼쪽 값이 오른쪽 값보다 작은 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           "<=": {
        -    "description": "",
        +    "description": "비교 연산자 <= 는 왼쪽 값이 오른쪽 값보다 작거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           "if-else": {
        -    "description": "",
        +    "description": "if-else문으로 코드의 흐름을 제어할 수 있습니다.<br>'if' 바로 다음 괄호 안에 조건을 지정할 수 있으며, 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/truthy'>참(truthy)</a>으로 연산되면 뒤따른 중괄호 사이의 코드가 실행됩니다. 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Falsy'>거짓(falsy)</a>으로 연산되면 'else' 뒤에 오는 중괄호 사이의 코드가 대신 실행됩니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else'>MDN Entry</a>에서 발췌: 지정된 조건이 참일 경우, if문은 명령문을 실행합니다. 조건이 거짓이면 다른 명령문을 실행할 수 잇습니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "function": {
        -    "description": "",
        +    "description": "새로운 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions'>함수(function)</a>를 생성하고 그 이름을 지정합니다. 함수란, 작업을 수행하는 일련의 명령문을 뜻합니다.<br> 선택적으로, 함수는 매개 변수를 가질 수 있습니다.<a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Parameter'>매개 변수(parameter)</a>란, 특정 함수에만 그 사용 범위가 지정된 변수를 뜻하며 함수 호출시 그 값을 지정할 수 있습니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function'>MDN Entry</a>에서 발췌: 사용자가 지정한 매개 변수를 사용하여 함수를 선언합니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "return": {
        -    "description": "",
        +    "description": "함수가 반환할 값을 지정합니다. <br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return'>MDN Entry 발췌 함수(function) 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           "boolean": {
        -    "description": "",
        +    "description": "불리언(boolean)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 불리언은 참(true) 또는 거짓(false)으로 값을 나타냅니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type'>MDN Entry</a>에서 발췌: 불리언은 논리적 개체를 나타내며 참(true) 또는 거짓(false)이라는 두 개의 값만 갖습니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "string": {
        -    "description": "",
        +    "description": "문자열(string)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 문자열은 일련의 텍스트 문자들을 뜻하며, 자바스크립트에서 문자열 값은 작은 따옴표나 큰따옴표로 묶여 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/string'>MDN Entry</a>에서 발췌: 문자열은 텍스트를 나타낼 때 사용하는 일련의 문자들입니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "number": {
        -    "description": "",
        +    "description": "숫자(number)는 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 숫자는 정수 또는 10진수로 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry 발췌 숫자(number) 상세 설명</a>",
             "params": ["",
             ""],
             "returns": ""
           },
           "object": {
        -    "description": "",
        +    "description": "<a href = 'https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics'>MDN Entry 발췌 객체(object) 기초 설명</a>: 객체(object)는 데이터 그리고/또는 함수의 모음을 뜻합니다. 일반적으로 여러 개의 변수와 함수로 구성됩니다. 변수와 함수가 객체 안에 포함된 경우, 각각을 속성(property)과 메소드(method)라 부릅니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "class": {
        -    "description": "",
        +    "description": "클래스(class)를 생성하고 그 이름을 지정합니다. 클래스는 객체(object) 생성을 위한 하나의 템플릿입니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry</a>에서 발췌: 클래스 선언을 통해 새로운 Class를 생성합니다. 이 때, 새로운 Class의 이름은 프로토타입 기반 상속을 통해 지정됩니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "for": {
        -    "description": "",
        +    "description": "for문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'for 반복문(for loop)'은 괄호 속 3개의 다른 표현식들로 구성되며, 각각의 표현식은 모두 선택 사항입니다. 이 표현식들은 반복 실행(loop)의 횟수를 제어합니다. 1번째 표현식은 반복문의 초기 상태를 설정하는 명령문입니다. 2번째 표현식은 매 반복 실행에 앞서 조건 충족 여부를 확인합니다. 이 표현식이 거짓(false)를 반환하면 반복 실행이 종료됩니다. 3번째 표현식은 반복문의 가장 마지막 단계에 실행됩니다.<br><br>for 반복문의 본문(중괄호 사이의 영역)에 포함된 코드는 2번째와 3번째 표현식의 연산과정 사이에 실행됩니다.<br><br>여타 반복문과 마찬가지로, for 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. 앞서 설명된 2번째 표현식을 통해, for 반복문의 조건이 거짓으로 연산되는 시점을 정할 수 있습니다. for반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않으면, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for'>MDN Entry</a>에서 발췌: for 반복문은 조건이 거짓(false)으로 연산될 때까지 지정된 명령문을 실행합니다. 명령문을 실행한 후에는 조건 충족 여부를 다시 평가하여, 명령문이 최소 1번 실행되도록 합니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "while": {
        -    "description": "",
        +    "description": "while문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'while 반복문(while loop)'을 사용하면, 소괄호 속 조건이 거짓(false)이 될 때까지 중괄호 속 본문의 코드가 반복적으로 실행됩니다. for 반복문과 달리, while 반복문은 그 본문 속 코드를 실행하기 앞서 조건 충족 여부를 먼저 확인합니다. 따라서, 최초 실행시 조건이 거짓일 경우, while문 속 본문과 명령문은 절대 실행되지 않습니다.<br><br>여타 반복문과 마찬가지로, while 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. while 반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않을 경우, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while'>MDN Entry</a>에서 발췌: while 반복문은 조건이 참(true)인 경우에 한해 지정된 명령문을 실행합니다. 명령문 실행에 앞서 조건 충족 여부가 평가됩니다.",
             "params": ["",
             ""],
             "returns": ""
           },
           "JSON": {
             "description": "",
        -    "params": ["",
        +    "methods": ["<a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify'>MDN Entry</a>에서 발췌: JSON.stringify() 메소드는 자바스크립트 객체나 값을 JSON 문자열로 변환합니다.",
             ""],
             "returns": ""
           },
           "console": {
             "description": "",
        -    "params": ["",
        +    "methods": ["브라우저의 웹 콘솔창에 메시지를 인쇄합니다. p5의 경우, print()와 console.log()를 모두 사용할 수 있습니다. 콘솔은 사용자의 브라우저에 따라 달라집니다. <a href = 'https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console'>Firefox</a>, <a href = 'https://developers.google.com/web/tools/chrome-devtools/open'>Chrome</a>, <a href = 'https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console'>Edge</a>, <a href = 'https://support.apple.com/en-ca/guide/safari/sfri20948/mac'>Safari</a>에서 콘솔을 여는 방법에 대한 링크는 다음과 같습니다. <a href ='https://editor.p5js.org/'>온라인 p5 에디터</a>의 경우, 콘솔창이 코드 에디터 하단에 임베드 되어있습니다. <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/Console/log'>MDN Entry</a>에서 발췌: 콘솔 메소드 log()는 웹 콘솔에 메시지를 출력합니다. 메시지는 단일 문열(선택적으로, 대체값과 함께)이거나 한 개 이상의 자바스크립트 객체일 수 있습니다.",
             ""],
             "returns": ""
           },
             
             "applyMatrix": {
        -      "description": "将现有的矩阵乘于由参数所定义的矩阵。这是个强大的功能并能够同时执行平移、缩放、切变及旋转。您能在<a href='https://zh.wikipedia.org/wiki/%E5%8F%98%E6%8D%A2%E7%9F%A9%E9%98%B5'>维基百科</a>了解更多关于变形矩阵的资讯。<br><br>这里的参数命名跟着 <a href='https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform'>WHATWG 规范</a>(英文页面)的命名方式并代表着一个如下的变形矩阵:<blockquote><p><img style='max-width: 150px' src='assets/transformation-matrix.png' alt='当 applyMatrix 被调用时所使用的变形矩阵'></p></blockquote>",
        -      "params": ["数字:定义该乘于的 2x3 矩阵",
        -                 "数字:定义该乘于的 2x3 矩阵",
        -                 "数字:定义该乘于的 2x3 矩阵",
        -                 "数字:定义该乘于的 2x3 矩阵",
        -                 "数字:定义该乘于的 2x3 矩阵",
        -                 "数字:定义该乘于的 2x3 矩阵"],
        +      "description": "현재 행렬(matrix)에 매개 변수로 지정된 행렬을 곱합니다. 평행 이동과 같은 연속 이동(translate), 크기 조정(scale), 전단(shear), 회전(rotate)을 한 번에 수행할 수 있습니다. <a href='https://ko.wikipedia.org/wiki/%EB%B3%80%ED%99%98%ED%96%89%EB%A0%AC'>변환행렬 위키피디아</a>에서 더 많은 정보를 확인할 수 있습니다.<br><br>이 때, 인수들은 <a href='https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform'>WHATWG 사양</a>에 따라 그 이름이 지정되며, 다음과 같은 형식의 변환 행렬에 상응합니다:<blockquote><p><img style='max-width: 150px' src='assets/transformation-matrix.png' alt='applyMatrix() 함수 호출시 사용되는 변환 행렬'></p></blockquote>",
        +      "params": ["숫자: 곱할 2x3 행렬 정의",
        +                 "숫자: 곱할 2x3 행렬 정의",
        +                 "숫자: 곱할 2x3 행렬 정의",
        +                 "숫자: 곱할 2x3 행렬 정의",
        +                 "숫자: 곱할 2x3 행렬 정의",
        +                 "숫자: 곱할 2x3 행렬 정의"],
               "returns": ""
             },
             "resetMatrix": {
        -      "description": "将现有的矩阵替换成单位矩阵。",
        +      "description": "현재 행렬을 항등 행렬로 바꿉니다.",
               "returns": ""
             },
             "rotate": {
        -      "description": "将一个形状根据参数所定义的角度旋转。这函数将考虑角度模式,所以角度可以是弧度或角度定义。<br><br>所有物件都会绕着原点旋转而正数将使物件在顺时针方向旋转。此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 rotate(HALF_PI) 然后 rotate(HALF_PI) 效果会与 rotate(PI) 相同。所有变形将会在 draw() 重新开始时恢复。",
        -      "params": ["数字:旋转的角度,根据当时的角度模式,以弧度或角度定义",
        -                 "p5.Vector|数字[]:(3D 模式下)旋转轴"],
        +      "description": "사용자가 지정한 각도 매개 변수에 따라 도형을 회전합니다. 이 함수는 angleMode() 함수의 영향을 받으며, 괄호 안에 RADIANS 또는 DEGREES를 입력하여  각도가 해석되는 방식을 지정할 수 있습니다.<br><br>객체는 항상 원점에 대한 상대적 위치를 중심으로 회전하며, 양수를 입력할 경우 시계 방향으로 객체를 회전합니다. 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용됩니다. 예를 들어, rotate(HALF_PI)를 호출한 뒤 rotate(HALF_PI)를 호출하면, 결과적으로 rotate(PI)와 동일한 효과를 갖습니다. 모든 변형은 draw() 함수가 다시 시작하는 시점에 리셋됩니다.<br><br>좀 더 기술적으로 설명하자면, rotate() 함수는 현재 변환 행렬에 회전 행렬을 곱하는 셈입니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
        +      "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 회전각",
        +                 "p5.Vector|숫자 배열[]: (3D의 경우,) 회전축 (선택 사항)"],
               "returns": ""
             },
             "rotateX": {
        -      "description": "绕着 x 轴旋转。",
        -      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "description": "x축을 따라 회전합니다.",
        +      "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 회전각"],
               "returns": ""
             },
             "rotateY": {
        -      "description": "绕着 y 轴旋转。",
        -      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "description": "y축을 따라 회전합니다.",
        +      "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 회전각"],
               "returns": ""
             },
             "rotateZ": {
        -      "description": "绕着 x 轴旋转。只适用于 WEBGL 模式。",
        -      "params": ["数字:旋转角度,根据当时的角度模式,以弧度或角度定义"],
        +      "description": "z축을 따라 회전합니다. (WebGL 모드 전용)",
        +      "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 회전각"],
               "returns": ""
             },
             "scale": {
        -      "description": "通过扩大和收缩顶点,放大或缩小形状。形状物件将会从坐标系统的原点开始缩放。缩放值为十进制百分比。比如说,调用函数 scale(2.0) 将使该形状放大 200%。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积相乘。比如说,调用 scale(2.0) 然后 scale(1.5) 效果会与 scale(3.0) 相同。如果 scale() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>给予此函数一个 z 参数只在 WEBGL 模式下受支持。这函数能使用 push() 及 pop() 控制。",
        -      "params": ["数字|p5.Vector|数字[]:缩放物件的百分比,或如果给予多个参数 x 轴的缩放百分比",
        -                 "数字:y 轴的缩放百分比",
        -                 "数字:z 轴的缩放百分比(只适用于 WEBGL 模式)",
        -                 "p5.Vector|数字[]:各轴缩放百分比"],
        +      "description": "꼭지점을 확장하거나 축소하여 도형의 크기를 키우거나 줄입니다. 객체의 크기는 언제나 좌표계에 대한 상대적 원점을 기준으로 조정됩니다. 크기값들은 10진수 백분율로 지정됩니다. 예를 들어, scale(2.0) 함수를 호출하면 도형의 크기를 200% 증가시킵니다.<br><br> 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용됩니다. 예를 들어, scale(2.0)을 호출한 뒤 scale(1.5)를 호출하면, 결과적으로 scale(3.0)과 동일한 효과를 갖습니다. 모든 변형은 draw() 함수가 다시 시작하는 시점에 리셋됩니다.<br><br>매개 변수 z는 오직 WebGL 모드에서만 사용 가능합니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
        +      "params": ["숫자|p5.Vector|숫자 배열[]:객체 크기를 조정하는 백분율, 또는 여러 인수를 지정할 경우 x축에서의 객체 크기 배율을 조정하는 백분율",
        +                 "숫자: y축에서의 객체 크기를 조정하는 백분율 (선택 사항)",
        +                 "숫자: z축에서의 객체 크기를 조정하는 백분율(WebGL 모드용)(선택 사항)",
        +                 "p5.Vector|숫자 배열[]: 축을 기준으로 객체의 크기 조정"],
               "returns": ""
             },
             "shearX": {
        -      "description": "有角度参数所定义的形状 x 轴切变量。角度必须符合当时的角度模式。形状物件将会从坐标系统的原点开始切变而正数表示切变方向为顺时针方向。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 shearX(PI/2) 然后 shearX(PI/2) 效果会与 shearX(PI) 相同。如果 shearX() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>技术上,shearX() 将现有的变形矩阵乘以一个旋转矩阵。这函数能使用 push() 及 pop() 控制。",
        -      "params": ["数字:根据当时的角度模式,以弧度或角度定义和切变角度"],
        +      "description": "사용자가 지정한 각도 매개 변수에 따라 도형을 x축에서 전단(shear)합니다. 이 함수는 angleMode() 함수의 영향을 받습니다. 객체는 항상 원점에 대한 상대적 위치를 중심으로 전단되며, 양수를 입력할 경우 시계 방향으로 객체를 전단합니다.<br><br> 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용되어, 그 효과들이 축적됩니다. 예를 들어, shearX(PI/2)를 호출한 뒤 shearX(PI/2)를 또 호출하면, 결과적으로 shearX(PI)와 동일한 효과를 갖습니다. draw() 함수 내에서 shearX()를 호출하면, 반복 실행이 다시 시작되는 시점에 모든 변형 내용이 리셋됩니다.<br><br>보다 기술적으로 설명하자면, shearX() 함수는 현재 변환 행렬에 회전 행렬을 곱하는 셈입니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
        +      "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 전단각"],
               "returns": ""
             },
             "shearY": {
        -        "description": "有角度参数所定义的形状 y 轴切变量。角度必须符合当时的角度模式。形状物件将会从坐标系统的原点开始切变而正数表示切变方向为顺时针方向。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 shearY(PI/2) 然后 shearY(PI/2) 效果会与 shearY(PI) 相同。如果 shearY() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。<br><br>技术上,shearY() 将现有的变形矩阵乘以一个旋转矩阵。这函数能使用 push() 及 pop() 控制。",
        -        "params": ["数字:根据当时的角度模式,以弧度或角度定义和切变角度"],
        +        "description": "사용자가 지정한 각도 매개 변수에 따라 도형을 y축에서 전단(shear)합니다. 이 함수는 angleMode() 함수의 영향을 받습니다. 객체는 항상 원점에 대한 상대적 위치를 중심으로 전단되며, 양수를 입력할 경우 시계 방향으로 객체를 전단합니다.<br><br> 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용되어, 그 효과들이 축적됩니다. 예를 들어, shearY(PI/2)를 호출한 뒤 shearY(PI/2)를 또 호출하면, 결과적으로 shearY(PI)와 동일한 효과를 갖습니다. draw() 함수 내에서 shearY()를 호출하면, 반복 실행이 다시 시작되는 시점에 모든 변형 내용이 리셋됩니다.<br><br>보다 기술적으로 설명하자면, shearY() 함수는 현재 변환 행렬에 회전 행렬을 곱하는 셈입니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
        +        "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 전단각"],
                 "returns": ""
             },
             "translate": {
        -      "description": "定义在显示窗口内平移物件的量。x 参数将定义左/右平移,y 参数将定义上/下平移。<br><br>此变形将影响接下来所有的绘图并且接下来此函数调用效果将累积。比如说,调用 translate(50, 0) 然后 translate(20, 0) 效果会与 translate(70, 0) 相同。如果 translate() 在 draw() 内被调用,变形将会在下一次循环开始时恢复。这函数能使用 push() 及 pop() 控制。",
        -      "params": ["数字:左/右平移",
        -                 "数字:上/下平移",
        -                 "数字:前/后平移(只适用于 WEBGL 模式)",
        -                 "p5.Vector:平移向量"],
        +      "description": "디스플레이 화면 내에서 객체를 이동시킬 양을 지정합니다. 매개 변수 x는 좌/우 이동을, 매개 변수 y는 상/하 이동을 지정합니다.<br><br>이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용되어, 그 효과들이 축적됩니다. 예를 들어, translate(50, 0)를 호출한 뒤 translate(20, 0)를 또 호출하면, 결과적으로 translate(70, 0)와 동일한 효과를 갖습니다. draw() 함수 내에서 translate()을 호출하면, 반복 실행이 다시 시작되는 시점에 모든 변형 내용이 리셋됩니다.<br><br>이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
        +      "params": ["숫자: 좌/우 이동",
        +                 "숫자: 상/하 이동",
        +                 "숫자: 앞/뒤 이동(WebGL 모드용)",
        +                 "p5.Vector: 이동시킬 벡터"],
               "returns": ""
             },
         
        +// Data > Array Functions
        +      
        +    "append": {
        +      "description": "弃用:append() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>。<br><br>在数组的尾端增加一个值。将增加数组的一个大小。映射到 Array.push()。",
        +      "params": ["数组:该附加到的数组",
        +                 "任何:该附加进数组的元素"],
        +      "returns": ""
        +    },
        +    "arrayCopy": {
        +      "description": "弃用:arrayCopy() 已被弃用并将会在未来的 p5 版本中移除。<br><br>复制一个数组(或该数组的一部分)去另外一个数组。src 数组将会被复制去 dst 数组,开端位置由 srcPosition 参数定义并复制进由 dstPosition 定义的位置。该复制的元素数量由 length 参数定义。注意在复制元素时该元素将覆盖终点数组原有的元素。如果想要添加元素,请使用 use concat()。<br><br>简化版本将只使用两个参数:arrayCopy(src, dst) 将复制整个数组去另一个相同大小的数组。这等同于使用 arrayCopy(src, 0, dst, 0, src.length)。<br><br>使用这函数将比使用 for 循环数组内每一个元素并一一复制来的更有效率。",
        +      "params": ["数组:原数组",
        +                 "数字:在原数组内的开端指数",
        +                 "数组:终点数组",
        +                 "数字:在终点数组内的开端指数",
        +                 "数字:该复制的元素量"],
        +      "returns": ""
        +    },
        +    "concat": {
        +      "description": "弃用:concat() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>。<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
        +      "params": ["数组:串接的第一个数组",
        +                 "数组:串接的第二个数组"],
        +      "returns": "数组:串接后的数组"
        +    },
        +    "reverse": {
        +      "description": "弃用:reverse() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>。<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
        +      "params": ["数组:该倒转的数组"],
        +      "returns": ""
        +    },
        +    "shorten": {
        +      "description": "弃用:shorten() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>。<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
        +      "params": ["数组:该缩短的数组"],
        +      "returns": "数组:缩短后的数组"
        +    },
        +    "shuffle": {
        +      "description": "弃用:shuffle() 已被弃用并将会在未来的 p5 版本中移除。请参考<a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>(英文页面)。<br><br>随机排列数组内的元素。使用 Fisher-Yates 混洗函数。",
        +      "params": ["数组:该混洗的数组",
        +                 "布尔值:修改所给予的数组"],
        +      "returns": "数组:混洗后的数组"
        +    },
        +    "sort": {
        +      "description": "弃用:sort() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>。<br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
        +      "params": ["数组:该排列的数组",
        +                 "整数:该排列的元素数,由 0 开始"],
        +      "returns": ""
        +    },
        +    "splice": {
        +      "description": "弃用:splice() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>。<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
        +      "params": ["数组:拼接进的数组",
        +                 "任何:欲拼接进数组的值",
        +                 "整数:数组内该添加该元素的位置"],
        +      "returns": ""
        +    },
        +    "subset": {
        +      "description": "弃用:subset() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>。<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
        +      "params": ["数组:该提取元素的数组",
        +                 "整数:开始位置",
        +                 "整数:提取元素数"],
        +      "returns": "数组:提取出来的元素数组"
        +    },
        +    "float": {
        +      "description": "将一个字符串转换成其浮点值。字符串内内容必须是数字,不然将返回 NaN(不是数字)。比如说,float(\"1234.56\") 将返回 1234.56,但 float(\"giraffe\") 将返回 NaN。<br><br>当给予一数组的值时,将返回一个等同大小的浮点数组。",
        +      "params": ["字符串:该解析的浮点字符串"],
        +      "returns": "数字:该字符串的浮点值"
        +    },
        +    "int": {
        +      "description": "转换一个布尔值、字符串或浮点值成其整数值。当给予一数组的值时,将返回一个等同大小的整数数组。",
        +      "params": ["字符串|布尔值|数字:该解析的值",
        +                 "整数:该转换成的基数",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的整数值"
        +    },
        +    "str": {
        +      "description": "转换一个布尔值、字符串或数字成其字符串值。当给予一数组的值时,将返回一个等同大小的字符串数组。",
        +      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        +      "returns": "字符串:该值的字符串值"
        +    },
        +    "boolean": {
        +      "description": "转换一个数字或字符串成其布尔值。在数字上,任何非零的值(无论正负)都将转换为 true,而零将转换为 false。在字符串上,\"true\" 将转换成 true,而任何其他值都会转换成 false。当给予一数组的数字或字符串时,将返回一个等同大小的布尔值数组。",
        +      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        +      "returns": "布尔值:该值的布尔值"
        +    },
        +    "byte": {
        +      "description": "转换一个数字、代表数字的字符串或布尔值成其字节值.一个字节只能是一个介于 -128 与 127 之间的整数,因此如果在这范围外的值被转换时,它将会绕回相对的字节值。当给予一数组的数字、字符串或布尔值时,将返回一个等同大小的字节数组。",
        +      "params": ["字符串|布尔值|数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的字节值"
        +    },
        +    "char": {
        +      "description": "转换一个数字或字符串成其单一字符的值。如果提供一个字符串参数,它将会先被解析成整数然后再被转换成单一字符。当给予一数组的数字或字符串时,将返回一个等同大小的单一字符数组。",
        +      "params": ["字符串|数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "字符串:该值的字符串值"
        +    },
        +    "unchar": {
        +      "description": "转换一个单一字符成其整数值。当给予一数组的单一字符值时,将返回一个等同大小的整数数组。",
        +      "params": ["字符串:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该值的整数值"
        +    },
        +    "hex": {
        +      "description": "转换一个数字成其十六进制值的字符串。如果提供第二个参数,它将被用来定义该生成的十六进制值的字符量。当给予一数组时,将返回一个等同大小的十六进制字符串数组。",
        +      "params": ["数字:该解析的值",
        +                 "数字",
        +                 "数字[]:该解析的值"],
        +      "returns": "字符串:该值的十六进制值"
        +    },
        +    "unhex": {
        +      "description": "转换一个十六进制字符串成其整数值。当给予一数组的十六进制字符串时,将返回一个等同大小的整数数组。",
        +      "params": ["数字:该解析的值",
        +                 "数组:该解析的值"],
        +      "returns": "数字:该十六进制值的整数值"
        +    },
        +    "join": {
        +      "description": "将一数组的字符串合成一个字符串,每一个元素由 separator 参数定义的字符分隔开。如果要连接整数或浮点数数组,它们必须先使用 nf() 或 nfs() 转换成字符串。",
        +      "params": ["数组:该连接的字符串",
        +                 "字符串:在个元素之间穿插的字符串"],
        +      "returns": "字符串:连接后的字符串"
        +    },
        +    "match": {
        +      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,将返回一个大小为 1 的数组(匹配的文字为数组的第一个元素)。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。正则表达式匹配返回的元素 [0] 将会是整个匹配的字符串,而匹配组合将从元素 [1] 开始(第一组为 [1]、第二组为 [2] 等)。",
        +      "params": ["字符串:在此字符串内搜寻",
        +                 "字符串:用于搜寻的正则表达式"],
        +      "returns": "数组:搜寻到的字符串数组"
        +    },
        +    "matchAll": {
        +      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的二维字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,仍然将返回一个二维数组,但第二维度数组的大小将为一。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个二维数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。假设有一个有计算其变量 i 的循环,正则表达式匹配返回的元素 [i][0] 将会是整个匹配的字符串,而匹配组合将从元素 [i][1] 开始(第一组为 [i][1]、第二组为 [i][2] 等)。",
        +      "params": ["字符串:在此字符串内搜寻",
        +                 "字符串:用于搜寻的正则表达式"],
        +      "returns": "字符串[]:搜寻到的二维字符串数组"
        +    },
        +    "nf": {
        +      "description": "用于将数字格式化成字符串的辅助函数。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点左边的位数",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfc": {
        +      "description": "用于将数字格式化成字符串并在适当的地方添加逗号以示意 1000 位的辅助函数。此函数有两个版本:一个用于格式化整数,另一个用于格式化一数组的整数。参数 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点左边的位数",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfp": {
        +      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \"+\" 号而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字|字符串:该格式化的数字",
        +                 "整数|字符串:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "nfs": {
        +      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \" \"(空格)而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        +      "params": ["数字:该格式化的数字",
        +                 "整数:小数点左边的位数",
        +                 "整数:小数点右边的位数",
        +                 "数组:该格式化的数字"],
        +      "returns": "字符串:格式化后的字符串"
        +    },
        +    "split": {
        +      "description": "split() 函数映射到 String.split(),它使用一个字符或字符串为分隔号以将另一个字符串拆分成多个部分。delim 参数定义用于标示各个部分之间边界的字符或字符串。将返回一个含有各个部分的字符串数组。<br><br>splitTokens() 函数也与此函数相似,不过它将使用一系列字符以拆分字符串而不是使用特别定义的单一字符或字符串。",
        +      "params": ["字符串:还拆分的字符串",
        +                 "字符串:用于分隔资料的字符串"],
        +      "returns": "字符串[]:字符串数组"
        +    },
        +    "splitTokens": {
        +      "description": "splitTokens() 函数将在一个或多个字符(或 “tokens”)所标示的地方拆分一个字符串。delim 参数将定义用于标示各个部分之间边界的字符或字符串。<br><br>如果 delim 参数没有被定义,此函数将使用任何空白字符拆分。空白字符包括制表符(\\t)、换行符(\\n)、回车符(\\r)、新页符(\\f)及空格。",
        +      "params": ["字符串:还拆分的字符串",
        +                 "字符串:用于分隔资料的字符串列"],
        +      "returns": "字符串[]:字符串数组"
        +    },
        +    "trim": {
        +      "description": "从一个字符串的前端及后端删除空白字符。除了一般的空白字符如空格、回车及制表符之外,这函数也将删除 Unicode “nbsp” 字符。",
        +      "params": ["字符串:该修剪的字符串",
        +                 "数组:该修剪的字符串数组"],
        +      "returns": "字符串:修剪后的字符串"
        +    },
        +
        +
        +      
        +// Events > Accleration
        +      
             "deviceOrientation": {
               "description": "deviceOrientation 系统变量将会储存设备的旋转方向。此变量的值可以是 ‘landscape’ 或 ‘portrait’。如果没有资料可用他会被定义成 ‘undefined’。LANDSCAPE 或 PORTRAIT。",
               "returns": ""
        @@ -1226,6 +1410,11 @@
               "description": "deviceShaken() 函数将在设备的 accelerationX 及 accelerationY 加速度值改变超过阈值。默认阈值为 30。",
               "returns": ""
             },
        +      
        +      
        +// Events > Keyboard
        +      
        +      
             "keyIsPressed": {
               "description": "keyIsPressed 布尔系统变量将会在任何键被按下时为真(true)而没键被按下时为假(false)。",
               "returns": ""
        @@ -1255,6 +1444,11 @@
               "params": ["数字:该查看的键"],
               "returns": ""
             },
        +      
        +      
        +// Events > Mouse
        +      
        +      
             "mouseX": {
               "description": "mouseX 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的横向位置。如果使用的是触动而不是滑鼠的话,mouseX 将会储存上一个触动点的 x 值。",
               "returns": ""
        @@ -1322,6 +1516,20 @@
               "description": "mouseWheel() 函数将在每次直向滑鼠滚轮事件被触发式被调用,可以由实际的滑鼠滚轮或摸板触发。<br><br>event.delta 属性将返回滑鼠滚轮所滚动的量。这值可以是正数或负数,取决于滚动的方向(在 OS X 如果启用“自然”滚屏方向,正反方向将相反)。",
               "returns": ""
             },
        +    "requestPointerLock": {
        +      "description": "",
        +      "returns": ""
        +    },
        +    "exitPointerLock": {
        +      "description": "",
        +      "returns": ""
        +    },
        +      
        +      
        +      
        +// Events > Touch
        +      
        +      
             "touches": {
               "description": "touches[] 系统变量将储存一个含有现在所有触动点相对于画布 (0, 0) 位置的位置数组,及分辨个别触动点移动时的 ID。数组内的每个元素都会有 x、y 及 id 属性。<br><br>touches[] 数组并不受 Safari 及 IE 移动设备(包括手提电脑)所支持。",
               "returns": ""
        @@ -1338,6 +1546,12 @@
               "description": "touchEnded() 函数将在每次触动结束时被调用。如果 touchEnded() 函数并未有被定义,mouseReleased() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
               "returns": ""
             },
        +      
        +
        +//Image
        +      
        +      
        +      
             "createImage": {
               "description": "创造一个新的 p5.Image 物件(储存图像的数据类型)。这将提供一个全新的像素缓冲供您使用。缓冲区的大小将由所提供的宽度和高度参数决定。<br><br>.pixels 将提供一个含有所有像素资料的数组。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。请参考 .pixels 文献。您也能使用更简单的 set() 或 get()。<br><br>在获取一个图像的像素之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。",
               "params": ["整数:像素宽度",
        @@ -1360,6 +1574,11 @@
                          "函数(数组):一个用来处理图像资料的回调函数。此函数将会被给予一个数组为参数。此数组将会储存所定义的捕捉影格物件。每一个物件都会有三个属性:imageData - 为 image/octet-stream 类型、filename 及 extension。"],
               "returns": ""
             },
        +      
        +
        +// Image > Loading & Displaying
        +      
        +
             "loadImage": {
               "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.",
               "params": ["문자열: 불러올 이미지 경로",
        @@ -1403,6 +1622,11 @@
               "params": ["常量:CORNER、CORNERS 或 CENTER"],
               "returns": ""
             },
        +      
        +      
        +// Image > Pixels
        +      
        +      
             "pixels": {
               "description": "此数组为一个储存显示窗口内所有像素值的 Uint8ClampedArray。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。视网膜显示及其他高密度显示器将会有更多像素(pixelDensity^2 倍)。比如说,如果图像为 100x100 像素,总共会有 40,000 个元素在 pixels[] 数组内。而在一个视网膜显示,将会有 160,000 个元素。<br><br>数组内最初四个值(指数 0-3)将会是在坐标 (0, 0) 的像素的 R、G、B、A 值。下四个值(指数 4-7)将会是在坐标 (1, 0) 的像素的 R、G、B、A 值。一般上,如果要设置像素 (x, y) 的值: <pre>CODE BLOCK PENDING</pre> 虽然以上的方式有点复杂,它能提供足够的弹性以应对任何像素密度的显示。注意 set() 将会自动处理设定所有在任何像素密度下 (x, y) 坐标在 pixels[] 内的值,不过程序性能可能在像素数组被更改很多次时时不佳。<br><br>在使用这个数组之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。<br><br>注意这不是个普通的 Javascript 数组。这表示 Javascript 数组函数如 <code>slice()</code> 或 <code>arrayCopy()</code> 将不会有效果。",
               "returns": ""
        @@ -1467,13 +1691,12 @@
                          "数字:欲更新的区域的高度"],
               "returns": ""
             },
        -    "loadFont": {
        -      "description": "从一个文件或网址加载一个 opentype 字形文件(.otf、.ttf),将返回一个 p5.Font 物件。这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。<br><br>字形的路径应该相对于链接您的绘图的 HTML 文件。从其他 URL 或远程位置加载字形可能会被浏览器的内建安全模式阻止。",
        -      "params": ["字符串:该加载的字形名字或网址",
        -                 "函数:在 loadFont() 完成后该调用的函数",
        -                 "函数:在发生错误时该调用的函数"],
        -      "returns": "p5.Font:p5.Font 物件"
        -    },
        +      
        +      
        +      
        +// IO > Input
        +      
        +      
             "loadJSON": {
               "description": "从一个文件或网址加载一个 JSON 文件,将返回一个物件。注意如果该 JSON 文件内涵一个数组,此函数仍然会返回一个以数字为指数的物件。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。JSONP 功能支持是由填充工具所提供而您可以使用第二个参数来定义一个有 JSON 回调定义的物件,只需跟从这里的<a href='https://github.com/camsong/fetch-jsonp'>指示</a>。",
               "params": ["字符串:该加载的文件名或网址",
        @@ -1541,11 +1764,28 @@
                          "物件:Request 物件,请参考 “fetch” API <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>文献</a>以了解可使用设置"],
               "returns": ""
             },
        +      
        +    "p5.XML":{
        +        "description":"",
        +        "params":["",
        +                  "",]
        +    },  
        +      
        +      
        +// IO > Input
        +      
             "createWriter": {
               "description": "",
               "params": ["字符串:该创造的文件的名",
                          "字符串:"]
             },
        +      
        +    "p5.PrintWriter":{
        +        "description":"",
        +        "params":["",
        +                  ""]
        +    }, 
        +            
             "save": {
               "description": "储存一个图像、文字、JSON、csv、wav 或 html 文件。将提示客户电脑下载文件。<b>注意 save() 函数不建议在正在循环执行的 draw 函数内使用,因为每一次被调用 save() 函数将会弹出一个储存对话框。</b><br><br>默认上此函数将储存画布成一个图像。您也可以选择定义一个文件名。例如:<pre>CODE BLOCK PENDING</pre>除此之外,第一个参数也能是个画布 p5.Element 的对象、字符串数组、JSON 数组、JSON 物件、p5.Table、p5.Image 或 p5.SoundFile(需要 p5.sound)。第二个参数为文件名(包括扩展名)。第三个参数适用于特别给这一类物件的设定。这函数将会储存一个符合给予的参数的文件。例如:<pre>CODE BLOCK PENDING</pre>",
               "params": ["物件|字符串:如果所提供的是文件名,此函数将会使用该文件名加上 png 或 jpg 文件扩展名来储存画布为一个图像。如果所提供的是物件,此函数则会一物件所定义的方式储存文件(请参考以上范例)。",
        @@ -1574,6 +1814,11 @@
                          "字符串:可以是 \"tsv\"、\"csv\" 或 \"html\""],
               "returns": ""
             },
        +      
        +      
        +// IO > Table
        +      
        +      
             "p5.Table": {
               "description": "Los objetos Table almacenan datos con múltiples filas y columnas, tal como una hoja de cálculo tradicional. Los objetos Table pueden ser generados desde cero, dinámicamente, o usando datos desde un archivo existente.",
               "params": ["Arreglo: un arreglo de objetos p5.TableRow"],
        @@ -1585,6 +1830,11 @@
               "String: por defecto, valores separados por coma (csv)"],
               "returns": "该 p5 物件"
             },
        +      
        +
        +// IO > Time & Date
        +      
        +      
             "day": {
               "description": "p5.js 将与您的电脑的时钟沟通,day() 函数将返回当天的日期天数在 1 - 31 的范围内。",
               "returns": "整数:当天的日期天数"
        @@ -1613,25 +1863,9 @@
               "description": "p5.js 将与您的电脑的时钟沟通,year() 函数将返回当天的日期年数为一个整数(2014、2015、2016等等)。",
               "returns": "整数:当时日期的年数"
             },
        -    "p5.XML": {
        -      "description": "XML es una representación de un objeto XML, capaz de procesar código XML. Usa loadXML() para cargar archivos externos XML y crear objetos XML",
        -      "params": ["String:"],
        -      "returns": "p5.XML: 该 p5 物件.XML generado"
        -    },
        -    "createVector": {
        -      "description": "创造一个新的 p5.Vector 向量(用以储存向量的数据类型)。此函数将提供一个二维或三维的向量,准确来说一个欧几里得(也称为几何)向量。向量为一个有大小及方向的量。",
        -      "params": ["数字:该向量的 x 分量",
        -                 "数字:该向量的 y 分量",
        -                 "数字:该向量的 z 分量"],
        -      "returns": "p5.Vector"
        -    },
        -    "p5.Vector": {
        -      "description": "Una clase para describir un vector de dos o tres dimensiones, específicamente un vector euclideano (también conocido como geométrico). Un vector es una entidad que tiene tanto magnitud como dirección. El tipo de datos, sin embargo, graba los componentes del vector (x, y para 2D y x,y,z para 3D). La magnitud y la dirección pueden ser calculados con los métodos mag() y heading(). En muchos de los ejemplos de p5.js, verás que p5.Vector es usado para describir una posición, velocidad o aceleración. Por ejemplo, si consideras un rectángulo moviéndose a lo largo de la pantalla, en cada instante tiene una posición (un vector que apunta desde el origen hasta su ubicación), una velocidad(la tasa a la que la posición del objeto cambia por unidad de tiempo, expresada como vector), y aceleración (la tasa a la que la velocidad del objeto cambia por unidad de tiempo, expresada como vector). Como los vectores representan grupos de valores, no podemos simplemente usar las operaciones tradicionales de adición, multiplicación, etc. En vez de eso, necesitaremos hacer matemática de vectores, lo que es simplificado con los métodos dentro de la clase p5.Vector.",
        -      "params": ["Número: componente x del vector",
        -                 "Número: componente y del vector",
        -                 "Número: componente z del vector"],
        -      "returns": "该 p5 物件"
        -    },
        +
        +// Math > Calculation      
        +      
             "abs": {
               "description": "计算一个数字的绝对值(大小值)。映射到 Math.abs()。一个数字的绝对值一定是个正数。",
               "params": ["数字:用于计算的数字"],
        @@ -1739,6 +1973,24 @@
               "params": ["数字:该取平方根的非负数"],
               "returns": "数字:取平方根后的数字"
             },
        +    "fract()": {
        +        "description": "",
        +    },
        +      
        +      
        +// Math > Vector
        +
        +    "createVector()": {
        +        "description": "",
        +    },
        +
        +    "p5.Vector()": {
        +        "description": "",
        +    },
        +
        +
        +// Math > Noise
        +      
             "noise": {
               "description": "返回所定义坐标的柏林噪声值。柏林噪声是个用来生成比 random() 所能生成更自然及更谐波的随机数字系列。在 1980 年代有 Ken Perlin 所发明,柏林噪声至今常被用在图形应用程序中生成程序纹理、自然运动、形状、地形等等。<br><br>柏林噪声与 random() 函数最主要的不同点在于前者是在一个无限的 n 维空间内定义的,这空间内每一对坐标都相对于一个固定的半随机值(只有在程序进行时为固定的;请参考 noiseSeed() 函数)。p5.js 能计算 1 维、2 维及 3 维噪声,这取决于所给予的坐标数。返回的值一定会在 0.0 至 1.0 之间。噪音值可以通过在噪音空间内移动以制成动画,如以上范例所示。第二及第三个空间维度也能被解读成时间。<br><br>所生成的噪音结构上和一般音频信号相似,尤其是此函数的频率。与物理学上谐波的概念相似,泊林噪音也是在计算几个八度后再将其结果加起来以得到最后的结果。<br><br>另外一个控制返回随机数系列的特征的方法是控制输入坐标值的大小。因为此函数能在无限之的空内内应用,输入坐标的值并不重要,只有个别坐标之间的距离需要被注意(如在循环内使用 noise() 时)。一般来说坐标之间的距离越小,生成噪声随机数列将会越平滑。介于 0.005-0.03 之间的距离应该适合大多数应用场合,不过这可能因应用需求而变。",
               "params": ["数字:噪声空间的 x 坐标",
        @@ -1757,6 +2009,32 @@
               "params": ["数字:随机种子值"],
               "returns": ""
             },
        +
        +// Math > Random
        +      
        +
        +    "randomSeed": {
        +      "description": "定义 random() 使用的随机种子值。<br><br>默认上,random() 将在每一次改程序被执行时生成不同的结果。只需定义 seed 参数至一个常量就能确保每一次软件执行时都会返回一样的伪随机数。",
        +      "params": ["数字:随机种子值"],
        +      "returns": ""
        +    },
        +    "random": {
        +      "description": "返回一个随机的浮点数。<br><br>可使用 0、1 或 2 个参数。<br><br>如果并没有定义任何参数,将返回一个介于 0 与 1(但不包括 1)的随机数。<br><br>如果只定义一个参数并且该参数为数字,将返回一个介于 0 与 该数字(但不包括该数字)的随机数。<br><br>如果值定义一个参数并且该参数为数组,将返回该数组中随机一个元素。<br><br>如果定义两个参数,将返回一个介于第一个参数与第二个参数(但不包括第二个参数)的随机数。",
        +      "params": ["数字:最低值(包括此值)",
        +                 "数字:最高值(不包括此值)",
        +                 "数组:供选择的数组"],
        +      "returns": "数字:随机数"
        +    },
        +    "randomGaussian": {
        +      "description": "返回一个符合高斯,或正态,分布的随机数。理论上 randomGaussian() 没有最高或最低返回值。不过,差均值很多的值被返回的机率将会很低;而接近均质的值被返回的机率将会相对较高。<br><br>可使用 0、1 或 2 个参数。<br>如果并没有定义任何参数,将使用均值为 0 与 标准差为 1。<br>如果只定义一个参数,该参数将为均值(标准差为 1)。<br>如果定义两个参数,第一个参数为均值,第二个参数为标准差。",
        +      "params": ["数字:均值",
        +                 "数字:标准偏差"],
        +      "returns": "数字:随机数"
        +    },
        +      
        +      
        +// Math > Trigonometry
        +      
             "acos": {
               "description": "cos() 的反值,将返回一个值的反余弦值。此函数接受介于 -1 与 1 之间的值并将返回介于 0 与 PI(3.1415927)之间的值。",
               "params": ["数字:该取反余弦值的值"],
        @@ -1808,24 +2086,10 @@
               "params": ["常量:RADIANS 或 DEGREES"],
               "returns": ""
             },
        -    "randomSeed": {
        -      "description": "定义 random() 使用的随机种子值。<br><br>默认上,random() 将在每一次改程序被执行时生成不同的结果。只需定义 seed 参数至一个常量就能确保每一次软件执行时都会返回一样的伪随机数。",
        -      "params": ["数字:随机种子值"],
        -      "returns": ""
        -    },
        -    "random": {
        -      "description": "返回一个随机的浮点数。<br><br>可使用 0、1 或 2 个参数。<br><br>如果并没有定义任何参数,将返回一个介于 0 与 1(但不包括 1)的随机数。<br><br>如果只定义一个参数并且该参数为数字,将返回一个介于 0 与 该数字(但不包括该数字)的随机数。<br><br>如果值定义一个参数并且该参数为数组,将返回该数组中随机一个元素。<br><br>如果定义两个参数,将返回一个介于第一个参数与第二个参数(但不包括第二个参数)的随机数。",
        -      "params": ["数字:最低值(包括此值)",
        -                 "数字:最高值(不包括此值)",
        -                 "数组:供选择的数组"],
        -      "returns": "数字:随机数"
        -    },
        -    "randomGaussian": {
        -      "description": "返回一个符合高斯,或正态,分布的随机数。理论上 randomGaussian() 没有最高或最低返回值。不过,差均值很多的值被返回的机率将会很低;而接近均质的值被返回的机率将会相对较高。<br><br>可使用 0、1 或 2 个参数。<br>如果并没有定义任何参数,将使用均值为 0 与 标准差为 1。<br>如果只定义一个参数,该参数将为均值(标准差为 1)。<br>如果定义两个参数,第一个参数为均值,第二个参数为标准差。",
        -      "params": ["数字:均值",
        -                 "数字:标准偏差"],
        -      "returns": "数字:随机数"
        -    },
        +      
        +      
        +// Typography > Attributes
        +      
             "textAlign": {
               "description": "定义绘制问题的对齐方向。使用两个参数:horizAlign(LEFT、CENTER 或 RIGHT)及 vertAlign(TOP、BOTTOM、CENTER 或 BASELINE)。<br><br>horizAlign 参数为 text() 函数的 x 值,而 vertAlign 参数为 y 值。<br><br>因此如果您使用 textAlign(LEFT),您将会使文字最左方对齐 text() 函数所使用的 x 参数。如果您使用 textAlign(RIGHT, TOP),您将会使文字最右方对齐 x 值而文字最上方对齐 y 值。",
               "params": ["常量:水平对齐,LEFT、CENTER 或 RIGHT",
        @@ -1860,6 +2124,19 @@
               "description": "返回当时字体在当时所定的大小的下端线高度。",
               "returns": "数字"
             },
        +      
        +      
        +// Typography > Loading & Displaying
        +      
        +    "loadFont": {
        +      "description": "从一个文件或网址加载一个 opentype 字形文件(.otf、.ttf),将返回一个 p5.Font 物件。这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。<br><br>字形的路径应该相对于链接您的绘图的 HTML 文件。从其他 URL 或远程位置加载字形可能会被浏览器的内建安全模式阻止。",
        +      "params": ["字符串:该加载的字形名字或网址",
        +                 "函数:在 loadFont() 完成后该调用的函数",
        +                 "函数:在发生错误时该调用的函数"],
        +      "returns": "p5.Font:p5.Font 物件"
        +    },
        +      
        +      
             "text": {
               "description": "将文字绘制在荧幕上。显示第一个参数内的资料在荧幕上由其他参数所定义的位置。将会使用默认字形除非使用 textFont() 函数定义使用其他字形同时也将使用默认大小除非使用 textSize() 定义文字大小。文字的颜色可使用 fill() 函数定义。可使用 stroke() 及 strokeWeight() 函数添加文字外形线。<br><br>文字显示将位于 textAlign() 函数所定义的位置,您可将文字绘制在坐标的左边、右边或中间。<br><br>x2 及 y2 参数将定义一个方形文字显示区而且只适用于字符串资料类型。当这两个参数被定义时,它们将使用当时的 rectMode() 设置被解读。不符合方形大小的文字将不会被绘制在荧幕上。",
               "params": ["字符串|物件|数组|数字|布尔值:该显示的字母数字符号",
        @@ -1880,183 +2157,10 @@
               "params": ["物件:puntero a la instancia p5"],
               "returns": "该 p5 物件"
             },
        -    "append": {
        -      "description": "弃用:append() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>。<br><br>在数组的尾端增加一个值。将增加数组的一个大小。映射到 Array.push()。",
        -      "params": ["数组:该附加到的数组",
        -                 "任何:该附加进数组的元素"],
        -      "returns": ""
        -    },
        -    "arrayCopy": {
        -      "description": "弃用:arrayCopy() 已被弃用并将会在未来的 p5 版本中移除。<br><br>复制一个数组(或该数组的一部分)去另外一个数组。src 数组将会被复制去 dst 数组,开端位置由 srcPosition 参数定义并复制进由 dstPosition 定义的位置。该复制的元素数量由 length 参数定义。注意在复制元素时该元素将覆盖终点数组原有的元素。如果想要添加元素,请使用 use concat()。<br><br>简化版本将只使用两个参数:arrayCopy(src, dst) 将复制整个数组去另一个相同大小的数组。这等同于使用 arrayCopy(src, 0, dst, 0, src.length)。<br><br>使用这函数将比使用 for 循环数组内每一个元素并一一复制来的更有效率。",
        -      "params": ["数组:原数组",
        -                 "数字:在原数组内的开端指数",
        -                 "数组:终点数组",
        -                 "数字:在终点数组内的开端指数",
        -                 "数字:该复制的元素量"],
        -      "returns": ""
        -    },
        -    "concat": {
        -      "description": "弃用:concat() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>。<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
        -      "params": ["数组:串接的第一个数组",
        -                 "数组:串接的第二个数组"],
        -      "returns": "数组:串接后的数组"
        -    },
        -    "reverse": {
        -      "description": "弃用:reverse() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>。<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
        -      "params": ["数组:该倒转的数组"],
        -      "returns": ""
        -    },
        -    "shorten": {
        -      "description": "弃用:shorten() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>。<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
        -      "params": ["数组:该缩短的数组"],
        -      "returns": "数组:缩短后的数组"
        -    },
        -    "shuffle": {
        -      "description": "弃用:shuffle() 已被弃用并将会在未来的 p5 版本中移除。请参考<a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>(英文页面)。<br><br>随机排列数组内的元素。使用 Fisher-Yates 混洗函数。",
        -      "params": ["数组:该混洗的数组",
        -                 "布尔值:修改所给予的数组"],
        -      "returns": "数组:混洗后的数组"
        -    },
        -    "sort": {
        -      "description": "弃用:sort() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>。<br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
        -      "params": ["数组:该排列的数组",
        -                 "整数:该排列的元素数,由 0 开始"],
        -      "returns": ""
        -    },
        -    "splice": {
        -      "description": "弃用:splice() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>。<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
        -      "params": ["数组:拼接进的数组",
        -                 "任何:欲拼接进数组的值",
        -                 "整数:数组内该添加该元素的位置"],
        -      "returns": ""
        -    },
        -    "subset": {
        -      "description": "弃用:subset() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>。<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
        -      "params": ["数组:该提取元素的数组",
        -                 "整数:开始位置",
        -                 "整数:提取元素数"],
        -      "returns": "数组:提取出来的元素数组"
        -    },
        -    "float": {
        -      "description": "将一个字符串转换成其浮点值。字符串内内容必须是数字,不然将返回 NaN(不是数字)。比如说,float(\"1234.56\") 将返回 1234.56,但 float(\"giraffe\") 将返回 NaN。<br><br>当给予一数组的值时,将返回一个等同大小的浮点数组。",
        -      "params": ["字符串:该解析的浮点字符串"],
        -      "returns": "数字:该字符串的浮点值"
        -    },
        -    "int": {
        -      "description": "转换一个布尔值、字符串或浮点值成其整数值。当给予一数组的值时,将返回一个等同大小的整数数组。",
        -      "params": ["字符串|布尔值|数字:该解析的值",
        -                 "整数:该转换成的基数",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的整数值"
        -    },
        -    "str": {
        -      "description": "转换一个布尔值、字符串或数字成其字符串值。当给予一数组的值时,将返回一个等同大小的字符串数组。",
        -      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        -      "returns": "字符串:该值的字符串值"
        -    },
        -    "boolean": {
        -      "description": "转换一个数字或字符串成其布尔值。在数字上,任何非零的值(无论正负)都将转换为 true,而零将转换为 false。在字符串上,\"true\" 将转换成 true,而任何其他值都会转换成 false。当给予一数组的数字或字符串时,将返回一个等同大小的布尔值数组。",
        -      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        -      "returns": "布尔值:该值的布尔值"
        -    },
        -    "byte": {
        -      "description": "转换一个数字、代表数字的字符串或布尔值成其字节值.一个字节只能是一个介于 -128 与 127 之间的整数,因此如果在这范围外的值被转换时,它将会绕回相对的字节值。当给予一数组的数字、字符串或布尔值时,将返回一个等同大小的字节数组。",
        -      "params": ["字符串|布尔值|数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的字节值"
        -    },
        -    "char": {
        -      "description": "转换一个数字或字符串成其单一字符的值。如果提供一个字符串参数,它将会先被解析成整数然后再被转换成单一字符。当给予一数组的数字或字符串时,将返回一个等同大小的单一字符数组。",
        -      "params": ["字符串|数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "字符串:该值的字符串值"
        -    },
        -    "unchar": {
        -      "description": "转换一个单一字符成其整数值。当给予一数组的单一字符值时,将返回一个等同大小的整数数组。",
        -      "params": ["字符串:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的整数值"
        -    },
        -    "hex": {
        -      "description": "转换一个数字成其十六进制值的字符串。如果提供第二个参数,它将被用来定义该生成的十六进制值的字符量。当给予一数组时,将返回一个等同大小的十六进制字符串数组。",
        -      "params": ["数字:该解析的值",
        -                 "数字",
        -                 "数字[]:该解析的值"],
        -      "returns": "字符串:该值的十六进制值"
        -    },
        -    "unhex": {
        -      "description": "转换一个十六进制字符串成其整数值。当给予一数组的十六进制字符串时,将返回一个等同大小的整数数组。",
        -      "params": ["数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该十六进制值的整数值"
        -    },
        -    "join": {
        -      "description": "将一数组的字符串合成一个字符串,每一个元素由 separator 参数定义的字符分隔开。如果要连接整数或浮点数数组,它们必须先使用 nf() 或 nfs() 转换成字符串。",
        -      "params": ["数组:该连接的字符串",
        -                 "字符串:在个元素之间穿插的字符串"],
        -      "returns": "字符串:连接后的字符串"
        -    },
        -    "match": {
        -      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,将返回一个大小为 1 的数组(匹配的文字为数组的第一个元素)。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。正则表达式匹配返回的元素 [0] 将会是整个匹配的字符串,而匹配组合将从元素 [1] 开始(第一组为 [1]、第二组为 [2] 等)。",
        -      "params": ["字符串:在此字符串内搜寻",
        -                 "字符串:用于搜寻的正则表达式"],
        -      "returns": "数组:搜寻到的字符串数组"
        -    },
        -    "matchAll": {
        -      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的二维字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,仍然将返回一个二维数组,但第二维度数组的大小将为一。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个二维数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。假设有一个有计算其变量 i 的循环,正则表达式匹配返回的元素 [i][0] 将会是整个匹配的字符串,而匹配组合将从元素 [i][1] 开始(第一组为 [i][1]、第二组为 [i][2] 等)。",
        -      "params": ["字符串:在此字符串内搜寻",
        -                 "字符串:用于搜寻的正则表达式"],
        -      "returns": "字符串[]:搜寻到的二维字符串数组"
        -    },
        -    "nf": {
        -      "description": "用于将数字格式化成字符串的辅助函数。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点左边的位数",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        -    },
        -    "nfc": {
        -      "description": "用于将数字格式化成字符串并在适当的地方添加逗号以示意 1000 位的辅助函数。此函数有两个版本:一个用于格式化整数,另一个用于格式化一数组的整数。参数 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点左边的位数",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        -    },
        -    "nfp": {
        -      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \"+\" 号而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        -    },
        -    "nfs": {
        -      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \" \"(空格)而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字:该格式化的数字",
        -                 "整数:小数点左边的位数",
        -                 "整数:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        -    },
        -    "split": {
        -      "description": "split() 函数映射到 String.split(),它使用一个字符或字符串为分隔号以将另一个字符串拆分成多个部分。delim 参数定义用于标示各个部分之间边界的字符或字符串。将返回一个含有各个部分的字符串数组。<br><br>splitTokens() 函数也与此函数相似,不过它将使用一系列字符以拆分字符串而不是使用特别定义的单一字符或字符串。",
        -      "params": ["字符串:还拆分的字符串",
        -                 "字符串:用于分隔资料的字符串"],
        -      "returns": "字符串[]:字符串数组"
        -    },
        -    "splitTokens": {
        -      "description": "splitTokens() 函数将在一个或多个字符(或 “tokens”)所标示的地方拆分一个字符串。delim 参数将定义用于标示各个部分之间边界的字符或字符串。<br><br>如果 delim 参数没有被定义,此函数将使用任何空白字符拆分。空白字符包括制表符(\\t)、换行符(\\n)、回车符(\\r)、新页符(\\f)及空格。",
        -      "params": ["字符串:还拆分的字符串",
        -                 "字符串:用于分隔资料的字符串列"],
        -      "returns": "字符串[]:字符串数组"
        -    },
        -    "trim": {
        -      "description": "从一个字符串的前端及后端删除空白字符。除了一般的空白字符如空格、回车及制表符之外,这函数也将删除 Unicode “nbsp” 字符。",
        -      "params": ["字符串:该修剪的字符串",
        -                 "数组:该修剪的字符串数组"],
        -      "returns": "字符串:修剪后的字符串"
        -    },
        +      
        +      
        +// Lights, Camera > Interaction
        +      
             "camera": {
               "description": "定义在一个三维绘图内相机的位置。此函数的行为与 gluLookAt 相似,不过它会覆盖原有的模型视图矩阵而不会在原有的模型视图上添加任何变形。当没有给予任何参数时,此函数将定义默认相机为 camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);",
               "params": ["数字:相机在 x 轴的位置",
        
        From 15747ac0e75b6b8835542954d8d77c62d6bd943a Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Sun, 17 May 2020 18:41:28 +0900
        Subject: [PATCH 24/36] 3rd update for revising translation layout of reference
         page
        
        ---
         src/data/reference/ko.json | 284 ++++++++++++++++++++++++-------------
         1 file changed, 188 insertions(+), 96 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index e5d557d9d0..eb10ea9a8b 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -125,7 +125,7 @@
               "returns": "초록색값"
             },
             "hue": {
        -      "description": "색상 또는 픽셀 배열로부터 색조를 추출합니다. 색조는 HSB와 HSL상 모두 존재합니다. 이 함수는 HSB 색상 객체를 사용할 경우(또는 HSB 색상 모드로 지정된 픽셀 배열을 사용할 경우) HSB로 표준화된 색조 값을 반환합니다. 기본값으로는 HSL로 표준화된 색조를 반환합니다. (단, 최대 색조가 별도로 지정되어있을 경우 다른 값을 반환합니다.)",
        +      "description": "색상 또는 픽셀 배열로부터 색조를 추출합니다. 색조는 HSB와 HSL상 모두 존재합니다. 이 함수는 HSB 색상 객체를 사용할 경우(또는 HSB 색상 모드로 지정된 픽셀 배열을 사용할 경우) HSB로 표준화된 색조 값을 반환합니다. 기본값으로는 HSL로 표준화된 색조를 반환합니다. (단, 최대 색조를 별도 지정한 경우 다른 값을 반환합니다.)",
               "params": ["객체, 색상 요소 또는 CSS 색상"],
               "returns": "색조"
             },
        @@ -749,143 +749,176 @@
         //DOM
             
           "p5.Element": {
        -    "description": "",
        -    "params": ["String: node DOM envolvente.",
        -    "Objeto: puntero a instancia p5."],
        -    "returns": "TODO"
        +    "description": "캔버스, 그래픽 버퍼, 기타 HTML 요소를 비롯하여, 스케치에 추가된 모든 요소(element)들을 위한 기본 클래스입니다. p5.Element 클래스는 직접 호출되지 않지만, 그 객체는 createCanvas, createGraphics, createDiv, createImg, createInput 호출을 통해 생성됩니다.",
        +    "params": ["문자열: 래핑된 DOM 노드",
        +               "P5: p5 인스턴스에 대한 포인터 (선택 사항)"
        +              ],
        +    "fields": ["기본 HTML 요소로, 모든 일반 HTML 메소드를 호출."
        +               ],
        +    "methods": ["지정된 부모 클래스에 요소를 연결합니다. 요소의 컨테이너를 설정하는 방법입니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 부모 노드가 반환됩니다. 캔버스 배치하는 다른 방법들은 <a href= 'https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>이 위키 페이지</a>를 참고하세요.",
        +                "요소의 ID를 설정합니다. 별도로 지정한 ID 인수가 없으면, 요소의 현재 ID를 반환합니다. 요소당 1개의 특정 id를 가질 수 있습니다. .class() 함수는 동일한 클래스 이름을 가진 여러 요소들을 식별하는 데에 사용됩니다.",
        +                "사용자가 지정한 클래스를 요소에 더합니다. 별도로 지정한 클래스 인수가 없으면, 요소의 현재 클래스(들)를 포함하는 문자열을 반환합니다.",
        +                ".mousePressed() 함수는 요소 위에서 마우스 버튼이 눌릴 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".doubleClicked() 함수는 요소 위에서 마우스 버튼을 빠르게 두 번 클릭할 때마다 한 번씩 호출됩니다. 요소에 행동 특정적 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".mouseWheel() 함수는 요소 위에서 마우스 휠을 스크롤 할 때마다 한 번싹 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.<br> 이 함수에서는 콜백 함수를 인수로서 사용할 수 있습니다. 그 경우, 요소 위에서 휠 이벤트가 발생할 때마다 콜백 함수가 하나의 event 인수로서 전달됩니다. event.deltaY 속성은 마우스 휠이 위쪽으로 회전하거나 사용자로부터 멀어지면 음수값을 반환하고, 그 반대 방향에선 양수값을 반환합니다. event.deltaX 속성은 마우스 가로 휠 스크롤을 읽는다는 점을 제외하고 event.deltaY와 동일하게 작동합니다.",
        +                ".mouseReleased() 함수는 요소 위에서 마우스 버튼을 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".mouseClicked() 함수는 요소 위에서 마우스 버튼을 클릭한 뒤 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".mouseMoved() 함수는 마우스가 요소 위에서 움직일 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".mouseOver() 함수는 마우스가 요소 위에 올라올 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".mouseOut() 함수는 마우스가 요소 위에서 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".touchStarted() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".touchMoved() 함수는 터치 움직임이 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".touchEnded() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".dragOver() 함수는 요소 위에 파일을 드래그할 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                ".dragLeave() 함수는 드래그된 파일이 요소 영역을 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                "요소에 특정 클래스를 추가합니다.",
        +                "요소로부터 특정 클래스를 제거합니다.",
        +                "요소에 이미 클래스가 설정되어 있는지 확인합니다.",
        +                "요소 클래스를 토글합니다.",
        +                "지정된 부모 클래스에 요소를 자식으로서 연결합니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 자식 DOM 노드 배열이 반환됩니다. ",
        +                "p5 Element를 수직으로, 수평으로, 또는 수직 및 수평으로 가운데 정렬합니다. 별도로 지정한 부모가 있는 경우 부모를 기준으로, 부모가 없는 경우 그 자신을 기준으로 합니다. 별도로 지정한 인수가 없으면 요소는 수직 및 수평으로 정렬됩니다.",
        +                "사용자가 별도로 지정한 인수로서 요소의 내부 HTML을 설정하며, 기존의 모든 HTML를 대체합니다. 참(true)이 그 2번째 인수로서 포함된 경우, 기존의 모든 HTML을 대체하는 대신 새로운 HTML을 추가(append)합니다. 별도로 지정한 인수가 없으면 요소의 내부 HTML을 반환합니다.",
        +                "요소의 위치를 설정합니다. 별도로 지정한 위치 유형 인수가 없는 경우, 화면창의 (0,0)을 기준으로 합니다. 기본적으로, 이 메소드를 통해 position:absolute와 left 및 top 스타일 속성을 설정합니다. 선택적으로, 3번째 인수를 통해 x 및 y 좌표의 <a href ='https://developer.mozilla.org/en-US/docs/Web/CSS/position'>위치 지정 체계</a>를 설정할 수 있습니다. 별도로 지정한 인수가 없으면 함수는 요소의 x와 y의 위치를 반환합니다.",
        +                "별도 지정한 값(2번째 인수)으로 CSS 스타일 속성(1번째 인수)을 설정합니다. 1개의 인수만 지정할 경우, .style()은 주어진 속성의 값을 반환합니다. 그러나 이 인수를 CSS 구문('text-align:center')으로 작성할 경우, .style()은 CSS를 설정합니다.",
        +                "사용자가 지정한 요소에 새 속성을 추가하거나, 요소의 기존 속성값을 변경합니다. 별도로 지정한 값이 없는 경우 주어진 속성의 값을 반환하고, 속성이 설정되지 않은 경우 null을 반환합니다. ",
        +                "요소로부터 속성을 제거합니다.",
        +                "별도로 지정한 인수가 없는 경우, 요소의 값을 반환하거나 설정합니다.",
        +                "현재 요소를 보여줍니다. display:block로 스타일을 설정합니다.",
        +                "현재 요소를 숨깁니다. display:none으로 스타일을 설정합니다.",
        +                "요소의 너비와 높이를 설정합니다. AUTO는 한 번에 한 개의 수치를 조정하는 데에 쓰입니다. 별도로 지정한 인수가 없는 경우, 객체 속 요소의 너비와 높이를 반환합니다. 이미지 파일과 같이 불러오기가 필요한 요소의 경우, 불러오기가 완료된 후 함수를 호출하는 것을 권장합니다.",
        +                "요소를 제거하고, 모든 미디어 스트림을 중지하며, 모든 리스너를 해제합니다.",
        +                "요소에 드롭된 파일이 로드될 때마다 호출되는 콜백을 등록합니다. p5는 메모리에 드롭된 모든 파일을 로드하고 이를 p5.File 객체로서 콜백에 전달합니다. 동시에 여러 파일을 드롭할 경우, 콜백이 여러 번 호출됩니다. 선택적으로, raw 드롭 이벤트에 등록될 2번째 콜백을 전달할 수 있습니다. 이 경우, 콜백에 본래 DragEvent도 제공됩니다. 동시에 여러 파일을 드롭하면 2번째 콜백이 드롭당 한 번씩 발생하며, 1번째 콜백은 로드된 파일당 한 번씩 발생합니다.",
        +               ]
           },
         
           "select": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "지정한 ID, 클래스, 또는 태그 이름(접두어 '#'로 ID를, '.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element를 반환합니다. 클래스나 태그의 이름이 2개 이상의 요소로 지정된 경우, 1번째 요소만 반환됩니다. DOM 노드는 .elt로 검섹할 수 있습니다. 아무 것도 검색되지 않을 경우 null을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        +    "params": ["문자열: 검색할 요소의 id, 클래스, 또는 태그 이름",
        +               "문자열|p5.Element|HTML 요소: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        +    "returns": "검색된 노드를 포함한 p5.Element"
           },
           "selectAll": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "지정한 클래스 또는 태그 이름('.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element 배열로 반환합니다. DOM 노드는 .elt로 검색할 수 있습니다. 아무 것도 검색되지 않을 경우 빈 배열을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        +    "params": ["문자열: 검색할 요소의 클래스 또는 태그 이름",
        +               "문자열: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        +    "returns": "검색된 노드를 포함한 p5.Element 배열"
           },
           "removeElements": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "createCanvase() 또는 createGraphics()로 생성된 캔버스와 그래픽을 제외하고, p5로 생성된 모든 요소를 제거합니다. 이벤트 핸들러 역시 제거되며, 요소가 DOM에서 제거됩니다.",
        +    "params": "",
        +    "returns": ""
           },
           "changed": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": ".changed() 함수는 요소값이 변경될 때 호출됩니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        +    "params": ["함수|불리언: 요소값이 변경될 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        +    "returns": ""
           },
           "input": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": ".input() 함수는 요소가 사용자 입력을 감지할 때 호출됩니다. 입력 이벤트는 키 또는 슬라이더 요소의 변경을 감지합니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        +    "params": ["함수|불리언: 요소가 사용자 입력을 감지할 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        +    "returns": ""
           },
           "createDiv": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "주어진 내부 HTML을 사용하여 DOM에 <div></div> 요소를 생성합니다.",
        +    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createP": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "주어진 내부 HTML을 사용하여 DOM에 <p></p> 요소를 생성합니다. 문단형 텍스트 작성시 사용됩니다.",
        +    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createSpan": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "주어진 내부 HTML을 사용하여 DOM에 <span></span> 요소를 생성합니다.",
        +    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createImg": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "주어진 src와 대체 텍스트(alt text)를 사용하여 DOM에 <img> 요소를 생성합니다.",
        +    "params": ["문자열: 이미지의 src 또는 url 경로",
        +               "문자열: 이미지가 로드되지 않을 경우 사용할 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Attributes'>대체 텍스트</a>. 빈 문자열(" ")로 이미지 숨기기 가능",
        +               "문자열: img 요소의 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin'>교차 출처 속성(crossOrigin property)</a>. '익명(anonymous)' 또는 '사용 자격 증명(use-credentials)'을 통해 교차 출처 권한이 있는 이미지를 검색하세요. 이는 캔버스에 이미지를 사용하기 위함이며, 빈 문자열(" ")이 전달된 경우 교차 출처 리소스 공유(CORS)는 사용되지 않습니다.",
        +               "gkatn: 인수로 지정된 p5.Element가 이미지 데이터를 불러왔을 때 호출되는 콜백 함수 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createA": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 하이퍼링크를 포함한 <a></a> 요소를 생성합니다.",
        +    "params": ["문자열: 링크될 페이지 url",
        +               "문자열: 화면에 보여질 링크 요소의 내부 HTML",
        +               "문자열: 새로운 링크가 보여질 대상, _blank, _self, _parent, _top 중 지정 가능 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createSlider": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 슬라이더<input></input> 요소를 생성합니다. .size() 함수로 슬라이더의 길이를 설정합니다.",
        +    "params": ["숫자: 슬라이더의 최소값",
        +               "숫자: 슬라이더의 최대값",
        +               "숫자: 슬라이더의 기본값(선택 사항)",
        +               "숫자: 슬라이더의 단위당 이동 크기(이동 크기가 0으로 지정된 경우, 슬라이더는 최소값과 최대값 사이를 부드럽게 이동합니다.)(선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createButton": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 <button></button> 요소를 생성합니다. .size() 함수로 버튼의 크기를 설정합니다. .mousePressed() 함수로 버튼이 클릭됐을 때의 행동을 지정합니다.",
        +    "params": ["문자열: 버튼 위에 나타나는 레이블",
        +               "문자열: 버튼값 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createCheckbox": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 체크박스<input></input> 요소를 생성합니다. .checked() 함수를 통해 체크되었는지의 여부를 반환합니다.",
        +    "params": ["문자열: 체크박스 위에 나타나는 레이블 (선택 사항)",
        +               "불리언: 체크박스의 값: 체크는 참(true), 체크 해제는 거짓(false) (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createSelect": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 드롭다운 메뉴<select></select> 요소를 생성합니다. 이미 생성된 셀렉트 박스(select box)를 선택할 경우, p5.Element에 select-box 메소드를 지정하는 데에도 쓰입니다. 셀렉트 박스 생성 후, .option() 메소드로 선택지(option)를 설정할 수 있습니다. .selected() 메소드는 p5.Element 인스턴스인 현재 드롭다운 요소를 반환합니다. .selected() 메소드는 특정 선택지를 최초 페이지 로드시의 기본값으로서 설정할 수 있습니다. .disable() 메소드는 특정 선택지를 비활성화하고, 별도로 지정된 인수가 없는 경우엔 전체 드롭다운 요소를 비활성화 상태로 표시합니다.",
        +    "params": ["불리언: 드롭다운이 여러 개의 선택지를 제공할 경우 참(true) (선택 사항)",
        +               "객체: DOM 셀렉트 요소"],
        +    "returns": "p5.Element"
           },
           "createRadio": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 라디오 버튼<input></input> 요소를 생성합니다. 라디오 버튼 생성 후, .option() 메소드로 옵션을 설정할 수 있습니다. .value() 메소드는 현재 선택된 옵션을 반환합니다.",
        +    "params": ["문자열: 생성된 div와 input field 각각의 id 및 이름 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createColorPicker": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 색상 입력을 위한 색상 추출(colorPicker) 요소를 생성합니다. .value() 메소드는 색상의 헥사(Hex) 문자열(#rrggbb)을 반환합니다. .color() 메소드는 현재 선택된 색상의 p5.Color 객체를 반환합니다.",
        +    "params": ["문자열|p5.Color: 요소의 색상 기본값 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createInput": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 텍스트 입력을 위한 <input></input> 요소를 생성합니다. .size() 함수로 상자의 크기를 설정합니다.",
        +    "params": ["문자열: 입력 상자의 기본값 (선택 사항)",
        +               "문자열: 텍스트 유형 (예: text, password 등) 기본값은 text (선택 사항)"],
        +    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
           },
           "createFileInput": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "'파일(file)' 유형의 DOM에 <input></input> 요소를 생성합니다. 스케치에 사용할 로컬 파일을 선택할 수 있게 됩니다.",
        +    "params": ["함수: 파일이 로드될 때의 콜백 함수 (선택 사항)",
        +               "문자열: 여러 파일 선택 허용 (선택 사항)"],
        +    "returns": "p5.Element: 생성된 DOM 요소를 담고있는 p5.Element에 대한 포인터"
           },
           "createVideo": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 간단한 오디오/비디오 재생을 위한 HTML5 <video> 요소를 생성합니다. 화면에 나타나기가 기본값이며, .hide()로 숨길 수 있습니다. video() 함수를 통해 캔버스에 그릴 수 있습니다. 1번째 매개 변수는 비디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 비디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        +    "params": ["문자열|문자열 배열[]: 비디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        +               "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        +    "returns": "p5.MediaElement: 비디오 p5.Element에 대한 포인터"
           },
           "createAudio": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "DOM에 간단한 오디오 재생을 위한 HTML5 <audio> 요소를 생성합니다. 1번째 매개 변수는 오디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 오디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        +    "params": ["문자열|문자열 배열[]: 오디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        +               "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        +    "returns": "p5.MediaElement: 오디오 p5.Element에 대한 포인터"
           },
           "VIDEO": {
             "description": "",
             "params": ["",
             ""],
        -    "returns": "TODO"
        +    "returns": ""
           },
           "AUDIO": {
             "description": "",
             "params": ["",
             ""],
        -    "returns": "TODO"
        +    "returns": ""
           },
           "createCapture": {
             "description": "",
        @@ -919,7 +952,7 @@
             "params": ["숫자: 너비값",
                        "숫자: 높이값",
                        "상수: 사용할 렌더러, P2D 또는 WEBGL",
        -               "P5: p5 인스턴스를 가리키는 포인터 (선택 사항)",
        +               "P5: p5 인스턴스에 대한 포인터 (선택 사항)",
             ""],
             "methods": ["그래픽 버퍼 객체로 자동 재설정되지 않은 특정값들(예: 레퍼런스 중 변형(Transform) 또는 라이트(Light) 항목에 해당하는 함수들로서 지정된 값들). 이 메소드를 draw() 함수 안에서 호출하면, 기본 캔버스의 행위를 복제합니다.",
                        "페이지에서 그래픽 객체를 제거하고 이 객체에 연결된 모든 소스들을 연결 해제합니다."]
        @@ -1152,6 +1185,61 @@
               "returns": ""
             },
         
        +// Data > Array Functions
        +    
        +    "storeItem":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "getItem":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "clearStorage":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "removeItem":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +      
        +      
        +// Data > Dictionary
        +      
        +    "createStringDict":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "createNumberDict":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "p5.TypedDict":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +    "p5.NumberDict":{
        +        "description":"",
        +        "params":["",
        +                  ""],
        +        "returns":""
        +    },
        +
         // Data > Array Functions
               
             "append": {
        @@ -1211,6 +1299,11 @@
                          "整数:提取元素数"],
               "returns": "数组:提取出来的元素数组"
             },
        +      
        +      
        +// Data > Conversion
        +      
        +      
             "float": {
               "description": "将一个字符串转换成其浮点值。字符串内内容必须是数字,不然将返回 NaN(不是数字)。比如说,float(\"1234.56\") 将返回 1234.56,但 float(\"giraffe\") 将返回 NaN。<br><br>当给予一数组的值时,将返回一个等同大小的浮点数组。",
               "params": ["字符串:该解析的浮点字符串"],
        @@ -1264,6 +1357,12 @@
                          "数组:该解析的值"],
               "returns": "数字:该十六进制值的整数值"
             },
        +      
        +      
        +      
        +// Data > String Functions
        +      
        +      
             "join": {
               "description": "将一数组的字符串合成一个字符串,每一个元素由 separator 参数定义的字符分隔开。如果要连接整数或浮点数数组,它们必须先使用 nf() 或 nfs() 转换成字符串。",
               "params": ["数组:该连接的字符串",
        @@ -2284,13 +2383,6 @@
               "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."]
             }
           },
        -    "p5.Image": {
        -    "loadPixels": {
        -      "description": "blah",
        -      "params": ["Numero: blah",
        -                 "Numero: blah"],
        -      "returns": "TODO"
        -    }
        -  }
        +
           
         }
        \ No newline at end of file
        
        From fca6eb4a56845f1d1384b989ea9686530e267548 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Mon, 18 May 2020 11:18:03 +0900
        Subject: [PATCH 25/36] 4th update on korean translation of reference page
        
        ---
         src/data/ko.yml            |  28 +++---
         src/data/reference/ko.json | 183 ++++++++++++++++++++++---------------
         2 files changed, 123 insertions(+), 88 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 902706f305..9a58e6b7a5 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -400,23 +400,23 @@ libraries:
           core-libraries: "주요 라이브러리"
           community-libraries: "커뮤니티 라이브러리"
           libraries-created-by: "제작: "
        -  p5.sound: "p5.sound는 p5에 웹 오디오 기능(오디오 입력, 재생, 분석 합성 등)을 더해줍니다. "
        -  p5.accessibility: "p5.accessibility는 p5 캔버스에 대한 맹인 또는 시각 장애인의 접근성을 높여줍니다. "
        -  asciiart: "p5.asciiart는 p5js를 아스키(ASCII) 아트로 쉽고 간단하게 변환해줍니다. 즉, p5js를 위한 아스키 아트 컨버터입니다. "
        -  p5.ble: "p5.ble은 BLE 기기와 p5 스케치를 연결해주는 자바스크립트 라이브러리입니다. "
        -  blizard.js: "blizard.js는 DOM 조작을 간단하게 처리해주는 라이브러리입니다. "
        -  p5.bots: "p5.bots를 통해 브라우저와 아두이노(Arduino) 및 여타 마이크로프로세서 간의 인터랙션을 만들 수 있습니다. 센서 데이터로 스케치를 만들거나, 스케치로 LED, 모터, 그 외의 것을 작동시켜 보세요! "
        -  p5.clickable: "이벤트 기반의, 사용이 편리한 p5.js 버튼 라이브러리입니다. "
        -  p5.cmyk.js: "CMYK ColorSpace"
        -  p5.collide2D: "p5.collide2D는 p5.js로 제작된 2D 기하 간의 충돌 감지 계산 툴을 제공합니다. "
        -  p5.createloop: "단 한 줄의 코드로 노이즈와 GIF로 이루어진 애니메이션 루프를 만들어보세요. "
        -  p5.dimensions: "p5.dimensions은 p5.js의 벡터 기능을 확장하여 n차원에서 작동하도록 합니다. "
        +  p5.sound: "p5.sound는 p5에 웹 오디오 기능(오디오 입력, 재생, 분석 합성 등)을 추가합니다. "
        +  p5.accessibility: "p5.accessibility는 p5 캔버스에 대한 맹인 또는 시각 장애인의 접근성을 향상합니다. "
        +  asciiart: "p5.asciiart는 p5.js를 아스키(ASCII) 아트로 쉽고 간단하게 변환합니다. 한마디로, p5.js를 위한 아스키 아트 컨버터입니다. "
        +  p5.ble: "p5.ble은 BLE 기기와 p5 스케치를 연결합니다. "
        +  blizard.js: "blizard.js는 DOM 조작을 간단하게 처리합니다. "
        +  p5.bots: "p5.bots를 통해 브라우저, 아두이노(Arduino), 마이크로프로세서 간의 인터랙션을 만들 수 있습니다. 센서 데이터로 스케치를 만들거나, 스케치에서 LED나 모터를 작동해보세요! "
        +  p5.clickable: "사용이 편리한, 이벤트 기반 p5.js 버튼 라이브러리입니다."
        +  p5.cmyk.js: "CMYK 컬러 스페이스. "
        +  p5.collide2D: "p5.collide2D는 p5.js로 만들어진 2D 도형들 간의 충돌을 감지하는 툴을 제공합니다. "
        +  p5.createloop: "노이즈와 GIF로 구성된 애니메이션 루프를 단 한 줄의 코드로 만들어보세요. "
        +  p5.dimensions: "p5.dimensions은 p5.js의 벡터 기능을 확장하여 n차원에서 작동하게 합니다. "
           p5.EasyCam: "패닝, 줌, 회전이 가능한 간단한 3D 카메라 컨트롤. Thomas Diewald가 핵심적으로 기여하였습니다. "
           p5.experience: "확장형 p5.js 라이브러리로, 캔버스 기반 웹 어플리케이션 제작을 위한 이벤트리스닝 기능을 추가할 수 있습니다. "
        -  p5.func: "p5.func은 시간(time), 빈도(frequency), 그리고 공간 영역에서의 기능 생성을 위한 새로운 오브젝트와 유틸리티를 제공합니다. "
        +  p5.func: "p5.func은 시간, 빈도, 그리고 공간 기능 생성을 위한 새로운 객체 및 기능을 제공합니다. "
           p5.geolocation: "p5.geolocation은 사용자 위치를 획득, 관찰, 계산, 지오펜싱(geo-fencing)하기 위한 기술을 제공합니다. "
        -  p5.gibber: "p5.gibber는 빠른 속도의 음악 시퀀싱 및 오디오 합성 기능을 제공합니다. "
        -  grafica.js: "grafica.js는 p5.js 스케치상 변형이 쉬운 2D 플롯을 더합니다. "
        +  p5.gibber: "p5.gibber는 음악 시퀀싱 및 오디오 합성 기능을 빠른 속도로 제공합니다. "
        +  grafica.js: "grafica.js는 p5.js 스케치상 변형이 쉬운 2D 플롯을 추가합니다. "
           p5.gui: "p5.gui는 p5.js 스케치를 위한 그래픽 유저 인터페이스를 생성합니다. "
           p5.localmessage: "p5.localmessage는 멀티윈도우 스케칭을 위한 스케치 간 로컬 메시지 전송 기능 및 인터페이스를 제공합니다. "
           marching: "래스터(raster)에서 벡터(vector)로의 변환, 등면."
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index eb10ea9a8b..3607da0a85 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -910,39 +910,60 @@
           },
           "VIDEO": {
             "description": "",
        -    "params": ["",
        -    ""],
        +    "params": [""],
             "returns": ""
           },
           "AUDIO": {
             "description": "",
        -    "params": ["",
        -    ""],
        +    "params": [""],
             "returns": ""
           },
           "createCapture": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "웹캠의 오디오/비디오 피드를 담는 <video> 요소를 생성합니다. 이 요소는 캔버스와는 별개로 작동합니다. '화면에 나타내기'가 기본값으로 주어지며, .hide()를 사용하여 화면으로부터 숨길 수 있습니다. image() 함수를 사용하여 피드를 캔버스에 그릴 수 있습니다. loadedmetadata 속성을 사용하여 요소가 완전히 로드된 시점을 감지할 수 있습니다. (2번째 예제 참고)<br><br> 피드의 구체적인 속성은 제약 조건(Constraints) 객체를 전달할 수 있습니다. 속성 및 제약 조건 객체와 관련해서는 <a href = 'https://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'>W3C 사양</a>을 참고하세요. 모든 브라우저가 이 기능을 지원하지 않는 점에 유의하세요.<br><br>보안 정보: 최신 브라우저 보안 사양은 createCapture() 이면의 getUserMedia() 메소드가 로컬 또는 HTTPS에서 코드 실행시에만 작동할 것을 요구합니다. 자세한 사항은 <a href = 'https://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>여기</a>와 <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>여기</a>서 확인하세요. ",
        +    "params": ["문자열|상수|객체: 캡쳐 유형, VIDEO 또는 AUDIO 중 하나로 지정 가능. 별도의 매개 변수가 지정되지 않을 경우 기본값으로 둘 다 또는 제약 조건 객체",
        +               "함수: 스트림 로드 완료 후 1번 호출되는 함수 (선택 사항)"],
        +    "returns": ""
           },
           "createElement": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "지정된 콘텐츠를 지닌 DOM에 태그된 요소를 생성합니다.",
        +    "params": ["문자열: 새로운 요소의 태그",
        +               "문자열: 요소 안에 삽입될 HTML 콘텐츠 (선택 사항)"],
        +    "returns": ""
           },
           "p5.MediaElement": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "오디오/비디오 처리를 위해 p5.Element를 확장합니다. p5.Element의 메소드 뿐 아니라, 미디어 제어를 위한 메소드도 포함합니다. p5.MediaElements는 직접 호출되지 않지만, createVideo, createAudio, CreateCapture 호출을 통해 생성됩니다.",
        +    "params": ["문자열: 래핑된 DOM 노드"],
        +    "fields": ["미디어 요소 소스 경로"],
        +    "methods": ["HTML5 미디어 요소를 재생합니다.",
        +               "HTML5 미디어 요소를 중지합니다. (현재 시간을 0으로 설정)",
        +               "HTML5 미디어 요소를 일시정지합니다.",
        +               "HTML5 미디어 요소의 반복을 참(true)로 설정하고, 재생 시작합니다.",
        +               "HTML5 미디어 요소의 반복을 거짓(false)으로 설정합니다. 종료 시점에 도달하면 요소가 중지합니다.",
        +               "HTML5 미디어 요소 자동재생 여부 설정",
        +               "HTML5 미디어 요소의 볼륨을 설정합니다. 별도로 지정한 인수가 없으면, 현재 볼륨을 반환합니다.",
        +               "별도로 지정한 인수가 없으면, 요소의 현재 재생 속도를 반환하빈다. 속도 매개 변수는 2.0일 때 2배속으로, 0.5일 때 0.5배속으로, -1일 때 정상 속도로 역재생합니다. (모든 브라우저가 역재생을 지원하지 않으며, 일부 지원 브라우저에서도 부드럽게 재생되지 않을 수 있습니다.)",
        +               "별도로 지정한 인수가 없을 경우, 요소의 현재 시간을 반환합니다. 인수가 지정될 경우, 요소의 현재 시간이 해당 인수로 설정됩니다.",
        +               "HTML5 미디어 요소의 지속 시간을 반환합니다.",
        +               "오디오/비디오 요소가 종료 시점에 도달할 때 호출할 이벤트를 예약합니다. 요소가 반복하는 경우 호출되지 않습니다. 요소는 oneded 콜백에 인수로 전달됩니다.",
        +               "요소가 출력한 오디오를 특정 audioNode나 p5.sound 객체로 보냅니다. 요소가 없는 경우, p5의 마스터 출력에 연결합니다. 모든 연결은 .disconnect() 메소드로 제거할 수 있습니다. p5.sound.js 애드온 라이브러리로 이러한 방법을 사용할 수 있습니다.",
        +               "마스터 출력을 비롯하여 모든 웹 오디오 라우팅을 분리합니다. 사용 예: 오디오 효과를 통해 출력을 다시 라우팅할 때",
        +               "웹 브라우저가 지정한 기본 미디어 요소(MediaElement) 컨트롤을 나타냅니다.",
        +               "기본 미디어 요소(MediaElement) 컨트롤을 숨깁니다.",
        +               "오디오/비디오와 같은 미디어 요소(MediaElement)가 재생 큐 지점에 도달할 때 발생할 이벤트를 예약합니다. 콜백 함수, 콜백이 발생할 시간(초 단위), 콜백에 대한 선택적 매개 변수를 허용합니다. 1번째 매개 변수는 시간(time)을, 2번째 매개 변수는 param을 콜백 함수에 전달합니다.",
        +               "ID를 기반으로 콜백을 제거합니다. ID는 addCue 메소드로 반환됩니다.",
        +               "addCue 메소드로 예약된 모든 콜백을 제거합니다."],
        +    "returns": ""
           },
           "p5.File": {
        -    "description": "",
        -    "params": ["",
        -    ""],
        -    "returns": "TODO"
        +    "description": "파일을 위한 기본 클래스입니다. Element.drop()과 createFileInput()에 사용됩니다.",
        +    "params": "파일: 래핑된 파일",
        +    "fields": ["기본 파일 객체. 모든 일반 File 메소드를 호출할 수 있습니다.",
        +              "파일 유형 (이미지, 텍스트 등)",
        +              "파일 하위 유형 (주로 jpg, png, xml 등의 파일 확장자)",
        +              "파일명",
        +              "파일 크기",
        +              "이미지 데이터를 담는 URL 문자열"],
        +    "returns": ""
           },
             
         //Rendering
        @@ -1188,27 +1209,24 @@
         // Data > Array Functions
             
             "storeItem":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        +        "description":"로컬 저장소에 값을 키 이름(key name)으로 저장합니다. 로컬 저장소는 브라우저에 저장되며, 브라우징 세션과 페이지를 다시 불러오는 사이에 유지됩니다. 키(key)는 변수명과 동일하게 지정될 수 있으나, 반드시 그럴 필요는 없습니다. 저장된 항목(item)을 가져오려면 <a href = 'https://p5js.org/reference/#/p5/getItem'>getItem</a>을 참조하세요.<br><br>비밀번호나 개인 정보와같이 민감한 데이터는 로컬 저장소에 저장되면 안됩니다.",
        +        "params":["문자열:",
        +                  "문자열|숫자|객체|불리언|p5.Color|p5.Vector:"],
                 "returns":""
             },
             "getItem":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        -        "returns":""
        +        "description":"storeItem()로 저장한 항목(item)의 값을 로컬 저장소로부터 반환합니다.",
        +        "params":["문자열: 로컬 저장소에 저장시 사용할 이름"],
        +        "returns":"숫자|객체|문자열|불리언|p5.Color|p5.Vector: 저장된 항목의 값"
             },
             "clearStorage":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        +        "description":"현재 영역에서 storeItem()으로 설정된 모든 로컬 저장소 항목(item)을 제거합니다.",
        +        "params":"",
                 "returns":""
             },
             "removeItem":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        +        "description":"storeItem()으로 저장된 항목(item)을 제거합니다.",
        +        "params":["문자열"],
                 "returns":""
             },
               
        @@ -1216,40 +1234,57 @@
         // Data > Dictionary
               
             "createStringDict":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        -        "returns":""
        +        "description":"키-값(key-value) 쌍 또는 사용자가 지정한 객체를 사용하여 p5.StringDict의 새로운 인스턴스를 생성합니다.",
        +        "params":["문자열:",
        +                  "문자열:"
        +                  "객체: 객체"],
        +        "returns":"p5.StringDict:"
             },
             "createNumberDict":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        -        "returns":""
        +        "description":"키-값(key-value) 쌍 또는 사용자가 지정한 객체를 사용하여 p5.NumberDict의 새로운 인스턴스를 생성합니다.",
        +        "params":["숫자:",
        +                  "숫자",
        +                  "객체: 객체",
        +                 ],
        +        "returns":"p5.NumberDict:"
             },
             "p5.TypedDict":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        +        "description":"모든 p5.Dictionary 유형을 위한 기본 클래스 입니다. 사용자가 지정한 사전(Dictionary) 클래스는 이 클래스를 상속할 수 있습니다.",
        +        "methods":["사전 안에 현재 저장된 키-값(key-value) 쌍의 개수를 반환합니다.",
        +                  "지정된 키(key)가 사전 안에 존재할 경우 참(true)을, 그렇지 않으면 거짓(false)를 반환합니다.",
        +                  "지정된 키에 저장된 값을 반환합니다.",
        +                  "지정된 키가 사전 안에 존재할 경우 연관된 값을 반환합니다. 그렇지 않으면 새로운 키-값 쌍이 추가됩니다.",
        +                  "새로운 키-값 쌍을 사전 안에 생성합니다.",
        +                  "기존에 저장된 모든 키-값 쌍들을 사전으로부터 제거합니다.",
        +                  "특정 키에 저장된 키-값 쌍을 사전으로부터 제거합니다.",
        +                  "Dictionary에 현재 저장된 항목들의 로그를 콘솔창에 출력합니다.",
        +                  "로컬 다운로드를 위해 사전을 CSV 파일로 변환합니다.",
        +                  "로컬 다운로드를 위해 사전을 JSON 파일로 변환합니다."],
                 "returns":""
             },
             "p5.NumberDict":{
        -        "description":"",
        -        "params":["",
        -                  ""],
        +        "description":"숫자를 위한 간단한 사전 클래스<br>p5.TypedDict를 확장합니다.",
        +        "params":["특정 키에 현재 저장된 값에 사용자가 지정한 숫자를 더하고, 그 결과값은 사전 안에 저장되어있던 기존값을 대체합니다.",
        +                  "특정 키에 현재 저장된 값에서 사용자가 지정한 숫자를 빼고, 그 결과값은 사전 안에 저장되어있던 기존값을 대체합니다.",
        +                  "특정 키에 현재 저장된 값에 사용자가 지정한 숫자를 곱하고, 그 결과값은 사전 안에 저장되어있던 기존값을 대체합니다.",
        +                  "특정 키에 현재 저장된 값을 사용자가 지정한 숫자로 나누고, 그 몫은 사전 안에 저장되어있던 기존값을 대체합니다.",
        +                  "사전 안에 현재 저장된 값들 중 가장 낮은 숫자를 반환합니다.",
        +                  "사전 안에 현재 저장된 값들 중 가장 높은 숫자를 반환합니다.",
        +                  "사전에서 사용된 키들 중 가장 낮은 키를 반환합니다.",
        +                  "사전에서 사용된 키들 중 가장 높은 키를 반환합니다."],
                 "returns":""
             },
         
         // Data > Array Functions
               
             "append": {
        -      "description": "弃用:append() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>。<br><br>在数组的尾端增加一个值。将增加数组的一个大小。映射到 Array.push()。",
        -      "params": ["数组:该附加到的数组",
        -                 "任何:该附加进数组的元素"],
        -      "returns": ""
        +      "description": "사용 불가: append()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>를 대신 사용하세요.<br><br>배열의 끝에 값을 추가하여, 그 길이를 1씩 확장합니다. Array.push()에 매핑합니다.",
        +      "params": ["배열: 추가할 배열",
        +                 "전부: 배열에 추가될 모든 것"],
        +      "returns": "추가된 배열"
             },
             "arrayCopy": {
        -      "description": "弃用:arrayCopy() 已被弃用并将会在未来的 p5 版本中移除。<br><br>复制一个数组(或该数组的一部分)去另外一个数组。src 数组将会被复制去 dst 数组,开端位置由 srcPosition 参数定义并复制进由 dstPosition 定义的位置。该复制的元素数量由 length 参数定义。注意在复制元素时该元素将覆盖终点数组原有的元素。如果想要添加元素,请使用 use concat()。<br><br>简化版本将只使用两个参数:arrayCopy(src, dst) 将复制整个数组去另一个相同大小的数组。这等同于使用 arrayCopy(src, 0, dst, 0, src.length)。<br><br>使用这函数将比使用 for 循环数组内每一个元素并一一复制来的更有效率。",
        +      "description": "사용 불가: copyArray()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<br>배열(또는 그 일부)을 다른 배열에 복사합니다. src 배열이 dst 배열에 복사되며, srcPosition으로 지정된 위치에서 시작하여 dstPosition으로 지정된 위치를 향합니다. 복사할 요소의 개수는 배열의 길이로 결정됩니다. 값을 복사하면 대상 배열의 기존값을 덮어씁니다. 덮어쓰기없이 값을 추가하려면 concat()을 사용하세요.<br>",
               "params": ["数组:原数组",
                          "数字:在原数组内的开端指数",
                          "数组:终点数组",
        @@ -1258,42 +1293,42 @@
               "returns": ""
             },
             "concat": {
        -      "description": "弃用:concat() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>。<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
        +      "description": "사용 불가: concat()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>를 대신 사용하세요.<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
               "params": ["数组:串接的第一个数组",
                          "数组:串接的第二个数组"],
               "returns": "数组:串接后的数组"
             },
             "reverse": {
        -      "description": "弃用:reverse() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>。<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
        +      "description": "사용 불가: reverse()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>를 대신 사용하세요.<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
               "params": ["数组:该倒转的数组"],
               "returns": ""
             },
             "shorten": {
        -      "description": "弃用:shorten() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>。<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
        +      "description": "사용 불가: shorten()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>를 대신 사용하세요.<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
               "params": ["数组:该缩短的数组"],
               "returns": "数组:缩短后的数组"
             },
             "shuffle": {
        -      "description": "弃用:shuffle() 已被弃用并将会在未来的 p5 版本中移除。请参考<a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>(英文页面)。<br><br>随机排列数组内的元素。使用 Fisher-Yates 混洗函数。",
        +      "description": "사용 불가: shuffle()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>를 대신 사용하세요.<br><br><a href = 'https://bost.ocks.org/mike/shuffle/'>피셔-예이츠(Fisher-Yates) 셔플 알고리즘</a>을 구현합니다.",
               "params": ["数组:该混洗的数组",
                          "布尔值:修改所给予的数组"],
               "returns": "数组:混洗后的数组"
             },
             "sort": {
        -      "description": "弃用:sort() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>。<br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
        +      "description": "사용 불가: sort()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>를 대신 사용하세요. <br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
               "params": ["数组:该排列的数组",
                          "整数:该排列的元素数,由 0 开始"],
               "returns": ""
             },
             "splice": {
        -      "description": "弃用:splice() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>。<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
        +      "description": "사용 불가: splice()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>를 대신 사용하세요.<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
               "params": ["数组:拼接进的数组",
                          "任何:欲拼接进数组的值",
                          "整数:数组内该添加该元素的位置"],
               "returns": ""
             },
             "subset": {
        -      "description": "弃用:subset() 已被弃用并将会在未来的 p5 版本中移除。请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>。<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
        +      "description": "弃用:subset()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. 请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>를 대신 사용하세요.<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
               "params": ["数组:该提取元素的数组",
                          "整数:开始位置",
                          "整数:提取元素数"],
        @@ -1305,29 +1340,29 @@
               
               
             "float": {
        -      "description": "将一个字符串转换成其浮点值。字符串内内容必须是数字,不然将返回 NaN(不是数字)。比如说,float(\"1234.56\") 将返回 1234.56,但 float(\"giraffe\") 将返回 NaN。<br><br>当给予一数组的值时,将返回一个等同大小的浮点数组。",
        -      "params": ["字符串:该解析的浮点字符串"],
        -      "returns": "数字:该字符串的浮点值"
        +      "description": "문자열을 실수(float), 즉 부동 소수점 숫자형 표현으로 변환합니다. 이 때, 문자열의 구문은 숫자 형식과 유사해야 합니다. 그렇지 않으면 NaN(숫자 아님)이 반환됩니다. 예컨대, float (\"1234.56\")은 1234.56으로 연산되지만, float (\"giraffe\")는 NaN을 반환합니다.<br>전달된 배열과 길이가 동일한 실수 배열이 반환됩니다.",
        +      "params": ["문자열: 구문 분석할 실수 문자열"],
        +      "returns": "숫자: 문자열의 부동 소수점 숫자형 표현"
             },
             "int": {
        -      "description": "转换一个布尔值、字符串或浮点值成其整数值。当给予一数组的值时,将返回一个等同大小的整数数组。",
        -      "params": ["字符串|布尔值|数字:该解析的值",
        -                 "整数:该转换成的基数",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的整数值"
        +      "description": "불리언(boolean), 문자열(string), 실수(float)를 정수(int)형 표현으로 변환합니다. 전달된 배열과 길이가 동일한 정수 배열이 반환됩니다.",
        +      "params": ["문자열|불리언|숫자: 구문 분석할 값",
        +                 "정수: 기수로 변환 (기본값: 10) (선택 사항)",
        +                 "배열: 구문 분석할 값"],
        +      "returns": "숫자: 값의 정수형 표현"
             },
             "str": {
        -      "description": "转换一个布尔值、字符串或数字成其字符串值。当给予一数组的值时,将返回一个等同大小的字符串数组。",
        -      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        -      "returns": "字符串:该值的字符串值"
        +      "description": "불리언(boolean), 문자열(string), 또는 숫자를 문자열 표현으로 변환합니다. 전달된 배열과 길이가 동일한 문자열 배열이 반환됩니다.",
        +      "params": ["문자열|불리언|숫자: 구문 분석할 값"],
        +      "returns": "숫자: 값의 문자열 표현"
             },
             "boolean": {
        -      "description": "转换一个数字或字符串成其布尔值。在数字上,任何非零的值(无论正负)都将转换为 true,而零将转换为 false。在字符串上,\"true\" 将转换成 true,而任何其他值都会转换成 false。当给予一数组的数字或字符串时,将返回一个等同大小的布尔值数组。",
        -      "params": ["字符串|布尔值|数字|数组:该解析的值"],
        -      "returns": "布尔值:该值的布尔值"
        +      "description": "불리언(boolean)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 불리언은 참(true) 또는 거짓(false)으로 값을 나타냅니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type'>MDN Entry</a>에서 발췌: 불리언은 논리적 개체를 나타내며 참(true) 또는 거짓(false)이라는 두 개의 값만 갖습니다.",
        +      "params": [""],
        +      "returns": ""
             },
             "byte": {
        -      "description": "转换一个数字、代表数字的字符串或布尔值成其字节值.一个字节只能是一个介于 -128 与 127 之间的整数,因此如果在这范围外的值被转换时,它将会绕回相对的字节值。当给予一数组的数字、字符串或布尔值时,将返回一个等同大小的字节数组。",
        +      "description": "숫자, 숫자의 문자열 표현, 또는 불리언을 바이트 표현으로 변환합니다. 바이트는 -128과 127 사이의 정수이므로, 이 범위를 벗어난 값은 상응하는 바이트 표현에 래핑됩니다. 숫자, 문자열 또는 부울 값의 배열이 전달되면 길이가 같은 바이트 배열이 반환됩니다.,
               "params": ["字符串|布尔值|数字:该解析的值",
                          "数组:该解析的值"],
               "returns": "数字:该值的字节值"
        
        From b9f09795822decafb82f30d42c96a337f59487d3 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Wed, 20 May 2020 14:56:13 +0900
        Subject: [PATCH 26/36] updates in the ko translation of reference page as of
         May 20
        
        ---
         src/data/reference/ko.json | 52 +++++++++++++++++++-------------------
         1 file changed, 26 insertions(+), 26 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 3607da0a85..29f0f51768 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -1362,35 +1362,35 @@
               "returns": ""
             },
             "byte": {
        -      "description": "숫자, 숫자의 문자열 표현, 또는 불리언을 바이트 표현으로 변환합니다. 바이트는 -128과 127 사이의 정수이므로, 이 범위를 벗어난 값은 상응하는 바이트 표현에 래핑됩니다. 숫자, 문자열 또는 부울 값의 배열이 전달되면 길이가 같은 바이트 배열이 반환됩니다.,
        -      "params": ["字符串|布尔值|数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的字节值"
        +      "description": "숫자, 숫자의 문자열 표현, 또는 불리언을 바이트 표현으로 변환합니다. 바이트는 -128과 127 사이의 정수이므로, 이 범위를 벗어난 값은 상응하는 바이트 표현에 래핑됩니다. 숫자, 문자열, 또는 불리언 값의 배열을 전달하면, 동일한 길이의 바이트 배열이 반환됩니다.",
        +      "params": ["문자열|불리언|숫자: 구문 분석할 값",
        +                 "배열: 구문 분석할 값"],
        +      "returns": "값의 바이트형 표현"
             },
             "char": {
        -      "description": "转换一个数字或字符串成其单一字符的值。如果提供一个字符串参数,它将会先被解析成整数然后再被转换成单一字符。当给予一数组的数字或字符串时,将返回一个等同大小的单一字符数组。",
        -      "params": ["字符串|数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "字符串:该值的字符串值"
        -    },
        +      "description": "숫자나 문자열을 단일 문자형(character) 문자열 표현으로 변환합니다. 사용자가 별도 지정한 문자열 매개 변수의 경우, 먼저 정수로서 구문 분석된 후 단일 문자형 문자열로 변환됩니다. 숫자 또는 문자열 값의 배열을 전달하면, 동일한 길이의 단일 문자형 문자열이 반환됩니다.",
        +      "params": ["문자열|숫자: 구문 분석할 값",
        +                 "배열: 구문 분석할 값"],
        +      "returns": "값의 문자열 표현"
        +    },             
             "unchar": {
        -      "description": "转换一个单一字符成其整数值。当给予一数组的单一字符值时,将返回一个等同大小的整数数组。",
        -      "params": ["字符串:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该值的整数值"
        +      "description": "단일 문자형 문자열 표현을 정수로 변환합니다. 단일 문자열 문자열 값의 배열을 전달하면, 동일한 길이의 정수 배열이 반환됩니다.",
        +      "params": ["문자열: 구문 분석할 값",
        +                 "배열: 구문 분석할 값"],
        +      "returns": "값의 정수형 표현"
             },
             "hex": {
        -      "description": "转换一个数字成其十六进制值的字符串。如果提供第二个参数,它将被用来定义该生成的十六进制值的字符量。当给予一数组时,将返回一个等同大小的十六进制字符串数组。",
        -      "params": ["数字:该解析的值",
        -                 "数字",
        -                 "数字[]:该解析的值"],
        -      "returns": "字符串:该值的十六进制值"
        +      "description": "숫자를 16진수 문자열로 변환합니다. 전달된 2번째 매개 변수는 16진수 표기법으로 생성할 문자 개수를 설정합니다. 배열이 전달되면, 동일한 길이를 갖는 16진수 문자열을 반환합니다.",
        +      "params": ["숫자: 구문 분석할 값",
        +                 "숫자: (선택 사항)",
        +                 "숫자 배열[]: 구문 분석할 숫자 값들 배열"],
        +      "returns": "값의 16진수 문자열 표현"
             },
             "unhex": {
        -      "description": "转换一个十六进制字符串成其整数值。当给予一数组的十六进制字符串时,将返回一个等同大小的整数数组。",
        -      "params": ["数字:该解析的值",
        -                 "数组:该解析的值"],
        -      "returns": "数字:该十六进制值的整数值"
        +      "description": "16진수 문자열 표현을 정수로 변환합니다. 16진수 문자열 값의 배열을 전달하면, 동일한 길이의 정수 배열이 반환됩니다.",
        +      "params": ["문자열: 구문 분석할 값",
        +                 "배열: 구문 분석할 값"],
        +      "returns": "16진수 값의 정수형 표현"
             },
               
               
        @@ -1399,10 +1399,10 @@
               
               
             "join": {
        -      "description": "将一数组的字符串合成一个字符串,每一个元素由 separator 参数定义的字符分隔开。如果要连接整数或浮点数数组,它们必须先使用 nf() 或 nfs() 转换成字符串。",
        -      "params": ["数组:该连接的字符串",
        -                 "字符串:在个元素之间穿插的字符串"],
        -      "returns": "字符串:连接后的字符串"
        +      "description": "문자열 배열을 결합하여 하나의 문자열을 만듭니다. 각 문자열은 사용자가 구분자 매개 변수로 지정한 문자를 통해 구분됩니다. 정수(int) 또는 실수(float) 배열을 결합하려면, 먼저 nf() 또는 nfs()를 통해 문자열로 변환되어야 합니다.",
        +      "params": ["배열: 결합할 문자열 배열",
        +                 "문자열: 각 항목 사이에 놓일 문자열"],
        +      "returns": "문자열: 결합된 문자열"
             },
             "match": {
               "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,将返回一个大小为 1 的数组(匹配的文字为数组的第一个元素)。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。正则表达式匹配返回的元素 [0] 将会是整个匹配的字符串,而匹配组合将从元素 [1] 开始(第一组为 [1]、第二组为 [2] 等)。",
        
        From 6388fe2044b9d3256658868b9957fc886aa110f8 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Wed, 20 May 2020 16:25:16 +0900
        Subject: [PATCH 27/36] quick update on match() && matchall()
        
        ---
         src/data/reference/ko.json | 8 ++++----
         1 file changed, 4 insertions(+), 4 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 29f0f51768..68d7c89ca6 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -1405,10 +1405,10 @@
               "returns": "문자열: 결합된 문자열"
             },
             "match": {
        -      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,将返回一个大小为 1 的数组(匹配的文字为数组的第一个元素)。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。正则表达式匹配返回的元素 [0] 将会是整个匹配的字符串,而匹配组合将从元素 [1] 开始(第一组为 [1]、第二组为 [2] 等)。",
        -      "params": ["字符串:在此字符串内搜寻",
        -                 "字符串:用于搜寻的正则表达式"],
        -      "returns": "数组:搜寻到的字符串数组"
        +      "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들)을 문자열 배열로 반환합니다.일치하는 내용이 없는 경우, null을 반환합니다. 그룹이 정규 표현식으로 지정되지 않지만 시퀀스가 일치하는 경우, 길이가 1인 배열(일치하는 텍스트가 배열의 첫번째 요소인 배열)을 반환합니다.<br><br>이 함수를 사용할 때, 결과값이 null인지의 여부를 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우 배열이 반환됩니다.<br><br> (괄호 속 요소들이 지정한) 그룹이 정규식 표현일 경우, 각각의 내용들이 배열로 반환됩니다. 일치하는 정규식 표현의 요소[0]는 일치하는 모든 문자열을 반환하는데, 이 경우 일치하는 그룹은 요소[1](첫 번째 그룹이 [1], 두번째 그룹이[2])에서 시작합니다.",
        +      "params": ["문자열: 검색할 문자열",
        +                 "문자열: 매칭에 사용될 정규식 표현"],
        +      "returns": "검색된 문자열들의 배열"
             },
             "matchAll": {
               "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的二维字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,仍然将返回一个二维数组,但第二维度数组的大小将为一。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个二维数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。假设有一个有计算其变量 i 的循环,正则表达式匹配返回的元素 [i][0] 将会是整个匹配的字符串,而匹配组合将从元素 [i][1] 开始(第一组为 [i][1]、第二组为 [i][2] 等)。",
        
        From da953a79627bdcb36475de7b4b10cac674e8f9f8 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Wed, 20 May 2020 19:23:50 +0900
        Subject: [PATCH 28/36] updates as of May 20 7 23 pm
        
        ---
         src/data/reference/ko.json | 142 +++++++++++++++++++------------------
         1 file changed, 74 insertions(+), 68 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 68d7c89ca6..b9de623e2b 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -1405,65 +1405,65 @@
               "returns": "문자열: 결합된 문자열"
             },
             "match": {
        -      "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들)을 문자열 배열로 반환합니다.일치하는 내용이 없는 경우, null을 반환합니다. 그룹이 정규 표현식으로 지정되지 않지만 시퀀스가 일치하는 경우, 길이가 1인 배열(일치하는 텍스트가 배열의 첫번째 요소인 배열)을 반환합니다.<br><br>이 함수를 사용할 때, 결과값이 null인지의 여부를 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우 배열이 반환됩니다.<br><br> (괄호 속 요소들이 지정한) 그룹이 정규식 표현일 경우, 각각의 내용들이 배열로 반환됩니다. 일치하는 정규식 표현의 요소[0]는 일치하는 모든 문자열을 반환하는데, 이 경우 일치하는 그룹은 요소[1](첫 번째 그룹이 [1], 두번째 그룹이[2])에서 시작합니다.",
        +      "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들) 리스트를 문자열 배열로 반환합니다. 매치하는 내용이 없는 경우, null을 반환합니다. 정규 표현식에 그룹이 지정되지 않지만 시퀀스가 일치하는 경우, 길이가 1인 배열(일치하는 텍스트가 배열의 첫번째 요소인 배열)을 반환합니다.<br><br>match() 함수 사용시, 결과값이 null인지를 잘 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우, 배열이 반환됩니다.<br><br>그룹(괄호들로 지정)이 정규식 표현인 경우, 각각의 내용들이 배열로 반환됩니다. 매치하는 정규식 표현의 요소[0]는 모든 매칭 문자열을 반환하는데, 이 경우 매칭 그룹은 요소[1](첫 번째 그룹은 [1], 두번째 그룹은 [2])에서 시작합니다.",
               "params": ["문자열: 검색할 문자열",
                          "문자열: 매칭에 사용될 정규식 표현"],
               "returns": "검색된 문자열들의 배열"
             },
             "matchAll": {
        -      "description": "这函数可被用来在一段文字上应用正则表达式,并将返回含有符合表达式的组合(在括号内的元素)的二维字符串数组。如果没找到任何匹配组合,将返回 null。如果正则表达式内没有定义任何组合,但有搜寻到匹配序列,仍然将返回一个二维数组,但第二维度数组的大小将为一。<br><br>使用此函数时,先查看结果是否为 null。如果结果为 null,那表示该段文字没有匹配序列。如果有找到匹配序列,将返回一个二维数组。<br><br>如果正则表达式内有组合(由括号定义),那个别内容将会以数组的形式返回。假设有一个有计算其变量 i 的循环,正则表达式匹配返回的元素 [i][0] 将会是整个匹配的字符串,而匹配组合将从元素 [i][1] 开始(第一组为 [i][1]、第二组为 [i][2] 等)。",
        -      "params": ["字符串:在此字符串内搜寻",
        -                 "字符串:用于搜寻的正则表达式"],
        -      "returns": "字符串[]:搜寻到的二维字符串数组"
        +      "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들)의 리스트를 2차원 문자열 배열로 반환합니다. 매치하는 내용이 없는 경우, null을 반환합니다. 정규 표현식에 그룹이 지정되지 않지만 시퀀스가 일치하는 경우, 2차원 배열이 반환되지만 2번째 차원의 길이는 1이 됩니다.<br><br>matchAll() 함수 사용시, 결과값이 null인지를 잘 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우, 2D 배열이 반환됩니다.<br><br>그룹(괄호들로 지정)이 정규식 표현인 경우, 각각의 내용들이 배열로 반환됩니다. 카운터 변수 i가 있는 반복문을 가정할 때, 매칭되는 정규식의 [i][0] 요소는 모든 매칭 문자열을 반환하고, 매칭 그룹은 [i][1](첫 번째 그룹은 [i][1], 두번째 그룹은 [i][2], ...)에서 시작합니다.",
        +      "params": ["문자열: 검색할 문자열",
        +                 "문자열: 매칭에 사용될 정규식 표현"],
        +      "returns": "검색된 문자열들의 2D 배열"
             },
             "nf": {
        -      "description": "用于将数字格式化成字符串的辅助函数。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点左边的位数",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        +      "description": "숫자를 문자열로 형식화하는 기능으로, 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수로는 각각 자릿수(digit), 소수점 기준 왼쪽 자릿수(left), 소수점 기준 오른쪽 자릿수(right)를 지정할 수 있으며, 이 매개 변수 값들은 항상 양의 정수여야 합니다. <br> 참고: left와 right 매개 변수 사용시, 그 값이 현재 숫자의 자릿수 길이보다 클 경우 자릿수를 맞추기 위해 매개 변수에 0이 붙는 점에 유의하세요. 예를 들어, 현재 숫자가 123.2이고 전달된 left 매개 변수가 4인 경우, 그 길이가 num의 정수 부분인 123의 길이(즉, 3)보다 큽니다. 이 경우, 0123.2가 반환됩니다. right 매개 변수의 경우에도 마찬가지로 값이 3인 정수 123.200이 반환됩니다.",
        +      "params": ["숫자|문자열: 형식화할 숫자",
        +                 "정수|문자열: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                 "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                 "배열: 형식화할 숫자들"],
        +      "returns": "문자열: 형식화된 문자열"
             },
             "nfc": {
        -      "description": "用于将数字格式化成字符串并在适当的地方添加逗号以示意 1000 位的辅助函数。此函数有两个版本:一个用于格式化整数,另一个用于格式化一数组的整数。参数 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点左边的位数",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        +      "description": "숫자를 문자열로 형식화하고 1000을 단위로 표시하기 위해 쉼표를 배치하는 기능입니다. 크게 두 가지 버전이 제공되는데, 하나는 정수(int)를 형식화하는 것이고, 다른 하나는 정수 배열을 형식화합니다. 매개 변수의 값들은 항상 양의 정수여야 합니다.",
        +      "params": ["숫자|문자열: 형식화할 숫자",
        +                 "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                 "배열: 형식화할 숫자들"],
        +      "returns": "문자열: 형식화된 문자열"
             },
             "nfp": {
        -      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \"+\" 号而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字|字符串:该格式化的数字",
        -                 "整数|字符串:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        +      "description": "숫자를 문자열로 형식화하는 기능입니다. nf()와 유사하나, 양수 앞에 '+'를, 음수 앞에 '-' 기호를 추가합니다. 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수 중, 소수점 기준 왼쪽 자릿수(left)와 소수점 기준 오른쪽 자릿수(right)의 값은 항상 양의 정수여야 합니다.",
        +      "params": ["숫자: 형식화할 숫자",
        +                 "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                 "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                 "숫자 배열[]: 형식화할 숫자들"],
        +      "returns": "문자열: 형식화된 문자열"
             },
             "nfs": {
        -      "description": "用于将数字格式化成字符串的辅助函数。与 nf() 相似但会在正数前加个 \" \"(空格)而在负数前加个 \"-\" 号。此函数有两个版本:一个用于格式化浮点数,另一个用于格式化整数。参数 left 及 right 的值必须是正整数。",
        -      "params": ["数字:该格式化的数字",
        -                 "整数:小数点左边的位数",
        -                 "整数:小数点右边的位数",
        -                 "数组:该格式化的数字"],
        -      "returns": "字符串:格式化后的字符串"
        +      "description": "숫자를 문자열로 형식화하는 기능입니다. nf()와 유사하나, '-' 기호가 붙은 음수와 정렬할 경우를 위해 '_(공백)' 기호를 양수 앞에 추가합니다. nfs()는 주로 음수가 아닌 숫자의 자릿수에 음수를 맞출 때 사용됩니다. (명확한 이해를 위해 예제를 참고하세요.) 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수 중, 자릿수(digit), 소수점 기준 왼쪽 자릿수(left)와 소수점 기준 오른쪽 자릿수(right)의 값은 항상 양의 정수여야 합니다. (IMP): 정렬 결과는 사용자의 타입페이스에 따라 달라집니다. 참고: left와 right 매개 변수 사용시, 그 값이 현재 숫자의 자릿수 길이보다 클 경우 자릿수를 맞추기 위해 매개 변수에 0이 붙는 점에 유의하세요. 예를 들어, 현재 숫자가 123.2이고 전달된 left 매개 변수가 4인 경우, 그 길이가 num의 정수 부분인 123의 길이(즉, 3)보다 큽니다. 이 경우, 0123.2가 반환됩니다. right 매개 변수의 경우에도 마찬가지로 값이 3인 정수 123.200이 반환됩니다.",
        +      "params": ["숫자: 형식화할 숫자",
        +                 "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                 "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                 "배열: 형식화할 숫자들"],
        +      "returns": "문자열: 형식화된 문자열"
             },
             "split": {
        -      "description": "split() 函数映射到 String.split(),它使用一个字符或字符串为分隔号以将另一个字符串拆分成多个部分。delim 参数定义用于标示各个部分之间边界的字符或字符串。将返回一个含有各个部分的字符串数组。<br><br>splitTokens() 函数也与此函数相似,不过它将使用一系列字符以拆分字符串而不是使用特别定义的单一字符或字符串。",
        -      "params": ["字符串:还拆分的字符串",
        -                 "字符串:用于分隔资料的字符串"],
        -      "returns": "字符串[]:字符串数组"
        +      "description": "split() 함수는 String.split()에 매핑되며, 구분 기호를 사용하여 문자 또는 문자열을 분할합니다. 분리 문자(delim) 매개 변수는 분할 경계를 나타낼 기호를 지정합니다. 각 조각들을 포함한 문자열 배열이 반환됩니다.<br>splitTokens() 역시 비슷하게 작동하나, 특정 문자나 시퀀스 대신 여러 개의 분리 문자를 분할한다는 점에서 다릅니다.",
        +      "params": ["문자열: 분할될 문자열",
        +                 "문자열: 데이터 분할에 쓰이는 문자열"],
        +      "returns": "문자열 배열[]: 문자열들의 배열"
             },
             "splitTokens": {
        -      "description": "splitTokens() 函数将在一个或多个字符(或 “tokens”)所标示的地方拆分一个字符串。delim 参数将定义用于标示各个部分之间边界的字符或字符串。<br><br>如果 delim 参数没有被定义,此函数将使用任何空白字符拆分。空白字符包括制表符(\\t)、换行符(\\n)、回车符(\\r)、新页符(\\f)及空格。",
        -      "params": ["字符串:还拆分的字符串",
        -                 "字符串:用于分隔资料的字符串列"],
        -      "returns": "字符串[]:字符串数组"
        +      "description": "splitTokens() 함수는 일명 '토큰(token)'이라 불리는, 하나 이상의 분리 문자를 사용하여 문자열을 분할합니다. <br><br> 분리 문자(delim) 매개 변수를 지정하지 않는 경우, 공백 문자를 사용하여 분할합니다. 공백 문자는 탭(\\t), 줄바꾸기(\\n), 캐리지 반환(CR: Carriage Return)(\\r), 폼 피드(FF: Form Feed)(\\f), 그리고 공백을 포함합니다.",
        +      "params": ["문자열: 분할될 문자열",
        +                 "문자열: 데이터 분할에 쓰이는 문자열"],
        +      "returns": "문자열 배열[]:문자열들의 배열"
             },
             "trim": {
        -      "description": "从一个字符串的前端及后端删除空白字符。除了一般的空白字符如空格、回车及制表符之外,这函数也将删除 Unicode “nbsp” 字符。",
        -      "params": ["字符串:该修剪的字符串",
        -                 "数组:该修剪的字符串数组"],
        -      "returns": "字符串:修剪后的字符串"
        +      "description": "문자열 앞뒤의 공백 문자를 제거합니다. 공백, 캐리지 반환(CR: Carriage Return), 탭과 같은 표준 공백 문자 외에, 유니코드 'nbsp' 문자도 제거합니다.",
        +      "params": ["문자열: 트리밍될 문자열",
        +                 "배열: 트리밍될 문자열 배열"],
        +      "returns": "문자열: 트리밍된 문자열"
             },
         
         
        @@ -1471,77 +1471,83 @@
         // Events > Accleration
               
             "deviceOrientation": {
        -      "description": "deviceOrientation 系统变量将会储存设备的旋转方向。此变量的值可以是 ‘landscape’ 或 ‘portrait’。如果没有资料可用他会被定义成 ‘undefined’。LANDSCAPE 或 PORTRAIT。",
        +      "description": "시스템 변수 deviceOrientation는 기기의 방향을 담습니다. 변수값은 LANDSCAPE(가로) 또는 PORTRAIT(세로)로 설정가능합니다. 사용 가능한 데이터가 없는 경우, '정의되지 않음(undefined)로 설정됩니다.",
               "returns": ""
             },
             "accelerationX": {
        -      "description": "accelerationX 系统变量将会储存设备的 x 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 accelerationX는 기기의 x축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "accelerationY": {
        -      "description": "accelerationY 系统变量将会储存设备的 y 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 accelerationY는 기기의 y축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "accelerationZ": {
        -      "description": "accelerationZ 系统变量将会储存设备的 z 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 accelerationZ는 기기의 z축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "pAccelerationX": {
        -      "description": "pAccelerationX 系统变量将会储存上一个影格该设备的 x 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 pAccelerationX는 기기의 직전 프레임부터 현재 프레임까지의 x축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "pAccelerationY": {
        -      "description": "pAccelerationY 系统变量将会储存上一个影格该设备的 y 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 pAccelerationY는 기기의 직전 프레임부터 현재 프레임까지의 y축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "pAccelerationZ": {
        -      "description": "pAccelerationZ 系统变量将会储存上一个影格该设备的 z 轴加速度。值的单位为每平方秒米。",
        +      "description": "시스템 변수 pAccelerationZ는 기기의 직전 프레임부터 현재 프레임까지의 z축상 가속도값을 담습니다. 값은 초당 미터 제곱으로 표기됩니다.",
               "returns": ""
             },
             "rotationX": {
        -      "description": "rotationX 系统变量将会储存设备在 x 轴的旋转角度。值介于 0 与 +/-180 度之间。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "description": "시스템 변수 rotationX는 기기의 x축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 -180부터 180까지이고, RADIANS로 설정된 경우 -PI부터 PI까지입니다.<br><br>참고: rotation 함수를 호출하는 순서에 유의하세요. 여러 축에 대한 회전 함수를 동시에 사용할 경우, 반드시 Z-X-Y 순서로 호출해야 합니다. 그렇지 않으면 예기지 못한 결과가 발생할 수 있습니다.",
               "returns": ""
             },
             "rotationY": {
        -      "description": "rotationY 系统变量将会储存设备在 y 轴的旋转角度。值介于 0 与 +/-90 度之间。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "description": "시스템 변수 rotationY는 기기의 y축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 -90부터 90까지이고, RADIANS로 설정된 경우 -PI/2부터 PI/2까지입니다.<br><br>참고: rotation 함수를 호출하는 순서에 유의하세요. 여러 축에 대한 회전 함수를 동시에 사용할 경우, 반드시 Z-X-Y 순서로 호출해야 합니다. 그렇지 않으면 예기지 못한 결과가 발생할 수 있습니다.",
               "returns": ""
             },
             "rotationZ": {
        -      "description": "rotationZ 系统变量将会储存设备在 z 轴的旋转角度。值介于 0 与 359 度之间。<br><br>与 rotationX 及 rotationY 不同的是,这变量只能在有内建指南针的设备使用。<br><br>注意:旋转的顺序很重要,比如说,如果同时使用它们必须依 Z-X-Y 的顺序调用或可能会有难以预料的行为。",
        +      "description": "시스템 변수 rotationZ는 기기의 z축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 0부터 360까지이고, RADIANS로 설정된 경우 0부터 2*PI까지입니다.<br><br>rotationX 및 rotationY와는 달리, 이 변수는 나침반이 내장된 기기에 한해 사용가능합니다.<br><br>참고: rotation 함수를 호출하는 순서에 유의하세요. 여러 축에 대한 회전 함수를 동시에 사용할 경우, 반드시 Z-X-Y 순서로 호출해야 합니다. 그렇지 않으면 예기지 못한 결과가 발생할 수 있습니다.",
               "returns": ""
             },
             "pRotationX": {
        -      "description": "pRotationX 系统变量将会储存上一个影格该设备在 x 轴的旋转角度。值介于 0 与 +/-180 度之间。<br><br>pRotationX 可以和 rotationX 一起使用以找出设备 x 轴的旋转方向。",
        +      "description": "시스템 변수 pRotationX는 기기의 직전 프레임부터 현재 프레임까지의 x축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 -180부터 180까지이고, RADIANS로 설정된 경우 -PI부터 PI까지입니다.<br><br>pRotationX와 rotationX를 함께 사용하여 기기의 x축상 회전 방향을 정할 수 있습니다.",
               "returns": ""
             },
             "pRotationY": {
        -      "description": "pRotationY 系统变量将会储存上一个影格该设备在 y 轴的旋转角度。值介于 0 与 +/-90 度之间。<br><br>pRotationY 可以和 rotationY 一起使用以找出设备 y 轴的旋转方向。",
        +      "description": "시스템 변수 pRotationY는 기기의 직전 프레임부터 현재 프레임까지의 y축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 -90부터 90까지이고, RADIANS로 설정된 경우 -PI/2부터 PI/2까지입니다.<br><br>pRotationY와 rotationY를 함께 사용하여 기기의 y축상 회전 방향을 정할 수 있습니다.",
               "returns": ""
             },
             "pRotationZ": {
        -      "description": "pRotationZ 系统变量将会储存上一个影格该设备在 z 轴的旋转角度。值介于 0 与 359 度之间。<br><br>pRotationZ 可以和 rotationZ 一起使用以找出设备 z 轴的旋转方向。",
        +      "description": "시스템 변수 pRotationZ는 기기의 직전 프레임부터 현재 프레임까지의 z축상 회전값을 담습니다. 스케치의 angleMode()가 DEGREES로 설정된 경우 값의 범위는 -90부터 90까지이고, RADIANS로 설정된 경우 0부터 2*PI까지입니다.<br><br>pRotationZ와 rotationZ를 함께 사용하여 기기의 z축상 회전 방향을 정할 수 있습니다.",
               "returns": ""
             },
        +    "turnAxis":{
        +      "description":"장치가 회전시, deviceTurned() 메소드를 트리거하는 축을 turnAxis 변수에 저장합니다. turnAxis 변수는 deviceTurned() 함수가 지정한 범위 내에서만 정의됩니다.",
        +      "returns":""
        +    },
        +      
        +      
             "setMoveThreshold": {
        -      "description": "setMoveThreshold() 函数可用来设置 deviceMoved() 函数的移动阈值。默认阈值为 0.5。",
        -      "params": ["数字:阈值"],
        +      "description": "setMoveThreshold() 함수로 deviceMoved() 함수의 이동 임계값을 설정합니다. 기본 임계값은 0.5입니다.",
        +      "params": ["숫자: 임계값"],
               "returns": ""
             },
             "setShakeThreshold": {
        -      "description": "setShakeThreshold() 函数可用来设置 deviceShaken() 函数的摇动阈值。默认阈值为 30。",
        +      "description": "setShakeThreshold() 함수로 deviceShaken() 함수의 이동 임계값을 설정합니다. 기본 임계값은 30입니다.",
               "params": ["数字:阈值"],
               "returns": ""
             },
             "deviceMoved": {
        -      "description": "deviceMoved() 函数将在设备在 X、Y 或 Z 轴被移动多过阈值时被调用。默认阈值为 0.5。",
        +      "description": "deviceMoved() 함수는 장치가 X,Y,Z 축을 따라 임계값 이상으로 이동할 때 호출됩니다. 기본 임계값은 0.5입니다. 임계값은 setMoveThreshold()로 변경할 수 있습니다.",
               "returns": ""
             },
             "deviceTurned": {
        -      "description": "deviceTurned() 函数将在设备被连续旋转多过 90 度时被调用。<br><br>触发 deviceTurned() 的旋转轴将被储存在 turnAxis 变量中。deviceTurned() 函数能被锁定在 X、Y 或 Z 以确保只有所定义的轴会导致函数被调用,您只需比较 turnAxis 变量和 'X'、'Y' 或 'Z' 字符串。",
        +      "description": "deviceTurned() 함수는 기기가 90도 이상을 계속해서 회전할 때 호출됩니다.<br>deviceTurned() 메소드를 트리거하는 축이 turnAxis 변수에 저장됩니다. turnAxis 변수를 X,Y,Z와 비교하여, 메소드를 트리거할 축을 정하고 해당 설정을 잠글 수 있습니다.",
               "returns": ""
             },
             "deviceShaken": {
        -      "description": "deviceShaken() 函数将在设备的 accelerationX 及 accelerationY 加速度值改变超过阈值。默认阈值为 30。",
        +      "description": "deviceShaken() 함수는 accelerationX와 accelerationY의 전체 가속도 변화량이 임계값보다 클 때 호출됩니다. 기본 임계값은 30입니다. 임계값은 setShakeThreshold()로 변경할 수 있습니다.",
               "returns": ""
             },
               
        @@ -1550,33 +1556,33 @@
               
               
             "keyIsPressed": {
        -      "description": "keyIsPressed 布尔系统变量将会在任何键被按下时为真(true)而没键被按下时为假(false)。",
        +      "description": "불리언 시스템 변수 keyIsPressed입니다. 자판키를 누르면 참(true)을, 누르지 않을 때 거짓(false)을 반환합니다.",
               "returns": ""
             },
             "key": {
        -      "description": "key 系统变量将会储存上一个被键入的键盘键值。以获得正确的大小写,最好在 keyTyped() 内使用。至于非 ASCII 值的键,请使用 keyCode 变量。",
        +      "description": "시스템 변수 key는 가장 마지막으로 입력된 자판키값을 담습니다. keyTyped() 함수를 통해 대소문자를 반영할 수 있습니다. ASCII 자판키가 아닌 경우, keyCode 변수를 사용하세요.",
               "returns": ""
             },
             "keyCode": {
        -      "description": "keyCode 变量可用来探测特别键如 BACKSPACE、DELETE、ENTER、RETURN、TAB、ESCAPE、SHIFT、CONTROL、OPTION、ALT、UP_ARROW、DOWN_ARROW、LEFT_ARROW、RIGHT_ARROW 是否被按下。您也可以使用特别网站如 <a href='http://keycode.info/'>keycode.info</a> 以找出自定义键的 keyCode。",
        +      "description": "다음의 keyCode 변수로 특수키 입력을 감지할 수 있습니다: BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. <a href='http://keycode.info/'>keycode.info</a>에서 원하는 자판키의 keyCode를 확인할 수 있습니다.",
               "returns": ""
             },
             "keyPressed": {
        -      "description": "keyPressed() 函数将会在每一次任何键被按下时被调用。被按下的键的 keyCode 将被储存在 keyCode 变量内。<br><br>对于非 ASCII 值的键,请使用 keyCode 变量。您能查看 keyCode 是否等于 BACKSPACE、DELETE、ENTER、RETURN、TAB、ESCAPE、SHIFT、CONTROL、OPTION、ALT、UP_ARROW、DOWN_ARROW、LEFT_ARROW、RIGHT_ARROW。<br><br>至于 ASCII 键值它们的值会被储存在 key 变量内。不过,它并不会分辨大小写。因此,建议使用 keyTyped() 以读取 key 变量,因为其大小写在这里会被分辨出来。<br><br>取决于操作系统如何处理按键重复,按住一个键可能使 keyTyped() (及 keyReleased())被调用多过一次。重复的速度应操作系统及该电脑的设置而定。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "keyPressed() 함수는 자판을 누를 때마다 한 번씩 호출됩니다. 누른 키의 keyCode는 keyCode 변수에 저장됩니다. <br><br>ASCII 자판키가 아닌 경우, keyCode 변수를 사용하세요. keyCode가 BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW에 해당하는지의 여부를 확인할 수 있습니다.<br><br>ASCII 자판키의 경우, 가장 마지막으로 누른 자판키값이 key 변수에 저장되나, 대소문자가 구분되지 않습니다. 대소문자 구분을 원할 경우, keyTyped()를 통해 key 변수를 받을 수 있습니다.<br><br>컴퓨터 운영 체제의 자판키 입력 반복 처리 방식으로 인해, 자판키를 계속 누르면 keyTyped()를 여러 번 호출하는 경우가 발생할 수 있습니다. 반복 속도는 운영 체제와 컴퓨터 구성 방식마다 다릅니다.<br><br>자판키 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "keyReleased": {
        -      "description": "keyReleased() 函数将会在每一次任何键被释放时被调用。请查看 key 及 keyCode 以知更多详情。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "keyReleased() 함수는 자판을 놓을 때마다 한 번씩 호출됩니다. 자세한 내용은 <a href='https://p5js.org/reference/#/p5/key'>key</a>와 <a href='https://p5js.org/reference/#/p5/keyCode'>keyCode</a>를 참고하세요.<br><br>자판키 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "keyTyped": {
        -      "description": "keyTyped() 函数将会在每一次任何键被按下时被调用,可是会忽略操作键如 Ctrl、Shift 及 Alt。被按下的键的 keyCode 将被储存在 keyCode 变量内。<br><br>取决于操作系统如何处理按键重复,按住一个键可能使 keyTyped() (及 keyReleased())被调用多过一次。重复的速度应操作系统及该电脑的设置而定。<br><br>不同浏览器可能会有不同附属于个别键盘事件的默认行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "keyTyped() 함수는 자판을 누를 때마다 한번씩 호출되지만, 백스페이즈, 딜리트, 컨트롤, 쉬프트, 알트키는 무시됩니다. 언급된 자판키 입력 감지를 원할 경우, keyPressed() 함수를 사용하면 됩니다. 가장 마지막으로 입력된 자판키값이 key 변수에 저장됩니다.<br><br>컴퓨터 운영 체제의 자판키 입력 반복 처리 방식으로 인해, 자판키를 계속 누르면 keyTyped()를 여러 번 호출하는 경우가 발생할 수 있습니다. (keyReleased()도 마찬가지 입니다.) 반복 속도는 운영 체제와 컴퓨터 구성 방식마다 다릅니다.<br><br>자판키 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "keyIsDown": {
        -      "description": "keyIsDown() 函数将查看被提供的键是否正被按下。它能在当您需要使用多个不同的键同时用来移动一个物件时使用(如将一个图像往斜移动)。您能给予任何代表该键的 keyCode 会任何<a href='http://p5js.org/zh-Hans/reference/#p5/keyCode'>此页</a>的 keyCode 变量名为参数。",
        -      "params": ["数字:该查看的键"],
        -      "returns": ""
        +      "description": "keyIsDown() 함수는 키가 현재 내려가있는지, 즉 눌리는지의 여부를 확인합니다. 이미지를 대각선으로 움직일 때처럼, 동시에 여러 자판키가 객체의 이동 방향에 영향을 주도록 설정할 때 사용됩니다. <a href='http://p5js.org/zh-Hans/reference/#p5/keyCode'>여기</a>에 나열된 keyCode 변수 이름이나 keyCode 숫자를 넣을 수 있습니다.",
        +      "params": "숫자: 확인할 자판키",
        +      "returns": "자판을 눌렀는지 아닌지의 여부"
             },
               
               
        
        From 1feaa06e8eaa3a1271bce7d7278e35de76129243 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Sat, 23 May 2020 18:47:24 +0900
        Subject: [PATCH 29/36] updates as of May 23 6 47 pm
        
        ---
         src/data/reference/ko.json | 191 +++++++++++++++++++++++++++----------
         1 file changed, 139 insertions(+), 52 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index b9de623e2b..55d6faeca5 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -1588,80 +1588,88 @@
               
         // Events > Mouse
               
        -      
        +    "movedX": {
        +      "description": "movedX 변수는 직전 프레임 이후의 마우스 수평 이동을 담습니다.",
        +      "returns": ""
        +    },
        +    "movedX": {
        +      "description": "movedY 변수는 직전 프레임 이후의 마우스 수직 이동을 담습니다.",
        +      "returns": ""
        +    },
             "mouseX": {
        -      "description": "mouseX 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的横向位置。如果使用的是触动而不是滑鼠的话,mouseX 将会储存上一个触动点的 x 值。",
        +      "description": "시스템 변수 mouseX는 캔버스 (0,0)에 대한 마우스의 현재 수평 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 마우스 입력 대신 터치가 사용될 경우, mouseX는 가장 마지막 터치 지점의 x좌표값을 담습니다.",
               "returns": ""
             },
             "mouseY": {
        -      "description": "mouseY 系统变量将会储存当时的鼠标相对于画布 (0, 0) 位置的的直向位置。如果使用的是触动而不是滑鼠的话,mouseY 将会储存上一个触动点的 y 值。",
        +      "description": "시스템 변수 mouseY는 캔버스 (0,0)에 대한 마우스의 현재 수직 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 마우스 입력 대신 터치가 사용될 경우, mouseY는 가장 마지막 터치 지점의 y좌표값을 담습니다.",
               "returns": ""
             },
             "pmouseX": {
        -        "description": "pmouseX 系统变量将会储存上一个影格鼠标或触动点相对于画布 (0, 0) 位置的的横向位置。",
        +        "description": "시스템 변수 pmouseX는 직전 프레임에서의 캔버스 (0,0)에 대한 마우스 및 터치 수평 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 참고: pmouseX는 매 터치 이벤트가 시작할 때마다 현재의 mouseX값으로 리셋됩니다.",
                 "returns": ""
             },
             "pmouseY": {
        -      "description": "pmouseY 系统变量将会储存上一个影格鼠标或触动点相对于画布 (0, 0) 位置的的直向位置。",
        +      "description": "시스템 변수 pmouseY는 직전 프레임에서의 캔버스 (0,0)에 대한 마우스 및 터치 수직 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 참고: pmouseY는 매 터치 이벤트가 시작할 때마다 현재의 mouseY값으로 리셋됩니다.",
               "returns": ""
             },
             "winMouseX": {
        -      "description": "winMouseX 系统变量将会储存当时鼠标相对于窗口 (0, 0) 位置的横向位置。",
        +      "description": "시스템 변수 winMouseX는 캔버스 (0,0)에 대한 마우스의 현재 수평 위치를 담습니다.",
               "returns": ""
             },
             "winMouseY": {
        -      "description": "winMouseY 系统变量将会储存当时鼠标相对于窗口 (0, 0) 位置的直向位置。",
        +      "description": "시스템 변수 winMouseY는 캔버스 (0,0)에 대한 마우스의 현재 수직 위치를 담습니다.",
               "returns": ""
             },
             "pwinMouseX": {
        -      "description": "pwinMouseX 系统变量将会储存上一个影格鼠标相对于窗口 (0, 0) 位置的横向位置。",
        +      "description": "시스템 변수 pwinMouseX는 직전 프레임에서의 캔버스 (0,0)에 대한 마우스 수평 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 참고: pwinMouseX는 매 터치 이벤트가 시작할 때마다 현재의 winMouseX값으로 리셋됩니다.",
               "returns": ""
             },
             "pwinMouseY": {
        -      "description": "pwinMouseY 系统变量将会储存上一个影格鼠标相对于窗口 (0, 0) 位置的直向位置。",
        +      "description": "시스템 변수 pwinMouseY는 직전 프레임에서의 캔버스 (0,0)에 대한 마우스 수직 위치를 담습니다. 2D상 (0,0)은 좌측 상단, WebGL상에서는 (-너비/2, 높이/2)를 의미합니다. 참고: pwinMouseY는 매 터치 이벤트가 시작할 때마다 현재의 winMouseY값으로 리셋됩니다.",
               "returns": ""
             },
             "mouseButton": {
        -      "description": "p5 将自动记录滑鼠键是否被按下及哪个键被按下。mouseButton 系统变量的值可能是 LEFT、RIGHT 或 CENTER,取决于上一个被按下的滑鼠键。请注意:不同的浏览器可能记录不同的 mouseButton 值。",
        +      "description": "p5는 마우스 버튼을 눌렀는 지의 여부와 어떤 버튼을 눌렀는지를 자동으로 추적합니다. 시스템 변수 mouseButton의 값은 마지막으로 누른 버튼에 따라 LEFT, RIGHT, 또는 CENTER로 처리됩니다. 경고: 브라우저에 따라 마우스 버튼을 다르게 추적할 수 있습니다.",
               "returns": ""
             },
             "mouseIsPressed": {
        -      "description": "mouseIsPressed 系统变量将会在滑鼠键被按下时为真(true),而没按下时为假(false)。",
        +      "description": "불리언 시스템 변수 mouseIsPressed는 마우스가 눌렸을 경우 참(true)이고 그렇지 않을 경우 거짓(false)로 처리됩니다.",
               "returns": ""
             },
             "mouseMoved": {
        -      "description": "mouseMoved() 函数将在每次鼠标移动而滑鼠键没有被按下的时候被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "mouseMoved() 함수는 마우스 버튼이 눌리지 않은 상태에서 움직일 때마다 한 번씩 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "mouseDragged": {
        -      "description": "mouseDragged() 函数将在每次鼠标移动及滑鼠键正被按下的时候被调用。如果 mouseDragged() 函数并未有被定义,touchMoved() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "mouseDragged() 함수는 마우스 버튼이 눌린 상태에서 움직일 때마다 한 번씩 호출됩니다. mouseDragged() 함수가 정의되지 않고, touchMoved() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "mousePressed": {
        -      "description": "mousePressed() 函数将在每次滑鼠键被按下时被调用。mouseButton 函数(请参考其文献)可以被用来探测哪一个滑鼠键刚被按下。如果 mousePressed() 函数并未有被定义,touchStarted() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "mousePressed() 함수는 마우스 버튼이 눌릴 때마다 한 번씩 호출됩니다. 이 때, mouseButton 변수(관련 레퍼런스 참고)를 통해 어떤 마우스 버튼이 눌렸는지 확인할 수 있습니다. mousePressed() 함수가 정의되지 않고, touchStarted() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "mouseReleased": {
        -      "description": "mouseReleased() 函数将在每次滑鼠键被释放时被调用。如果 mouseReleased() 函数并未有被定义,touchEnded() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "mouseReleased() 함수는 마우스 버튼이 놓일 때마다 한 번씩 호출됩니다. mouseReleased() 함수가 정의되지 않고, touchEnded() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "mouseClicked": {
        -      "description": "mouseClicked() 函数将在滑鼠键被按下然后被释放后被调用。<br><br>不同浏览器处理滑鼠点击的方式不大一样,所以这函数只有在滑鼠左键被点击时才保证会被触发。如果想要处理其他滑鼠键的点击或释放事件,请参考 mousePressed() 或 mouseReleased()。<br><br>不同浏览器可能有不同附属于个别滑鼠事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        +      "description": "mouseClicked() 함수는 마우스 버튼이 눌리고 놓일 때마다 한 번씩 호출됩니다.<br>이 함수는 마우스 왼쪽 버튼을 클릭할 때 실행되며, 브라우저마다 마우스 클릭을 다르게 처리하는 점에 유의하세요. 클릭하거나 놓을 여타 마우스 버튼을 처리하려면 mousePressed() 또는 mouseReleased()를 참고하세요.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "returns": ""
             },
             "doubleClicked": {
        -      "description": "doubleClicked() 函数将在 dblclick 事件被触发式被调用,dblclick 时间是 DOM L3 规范的一部分。doubleClicked 将在滑鼠键(通常为左键)连续两次在同样一个元素上点击时被触发。以知更多详情请参考 Mozilla 的参考文献:<a href='https://developer.mozilla.org/en-US/docs/Web/Events/dblclick'>https://developer.mozilla.org/en-US/docs/Web/Events/dblclick</a>。"
        +      "description": "doubleClicked() 함수는 이벤트 리스너가 DOM L3 사양 중 하나인 더블 클릭(dbclick)을 감지할 때마다 실행됩니다. doubleClicked 이벤트는 포인팅 장치의 버튼(보통, 마우스 기본 버튼)을 특정 요소 위에서 두 번 연속 클릭시 시작합니다. dbclick 이벤트에 대한 자세한 정보는 <a href='https://developer.mozilla.org/en-US/docs/Web/Events/dblclick'>Mozilla 문서</a>에서 확인하세요.",
        +      "params":"객체: MouseEvent 콜백 인수 (선택 사항)"
             },
             "mouseWheel": {
        -      "description": "mouseWheel() 函数将在每次直向滑鼠滚轮事件被触发式被调用,可以由实际的滑鼠滚轮或摸板触发。<br><br>event.delta 属性将返回滑鼠滚轮所滚动的量。这值可以是正数或负数,取决于滚动的方向(在 OS X 如果启用“自然”滚屏方向,正反方向将相反)。",
        -      "returns": ""
        +      "description": "mouseWheel() 함수는 실제 마우스 휠 또는 터치 패드상의 수직 마우스 휠 이벤트를 감지할 때마다 실행됩니다. <br><br>event.delta 속성은 마우스 휠이 스크롤된 양을 값으로 반환합니다. 값은 스크롤 방향에 따라 양수 또는 음수 부호와 함께 표기됩니다. ('자연' 스크롤이 활성화된 OS X의 경우, 부호가 반전됩니다.)<br><br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.<br><br> 현재 Safari의 경우 'wheel' 이벤트를 지원하는 관계로, 메소드에 \"return false\"를 포함해야 함수가 예상대로 작동할 수 있습니다.",
        +      "params":"객체: WheelEvent 콜백 인수 (선택 사항)"
             },
             "requestPointerLock": {
        -      "description": "",
        +      "description": "requestPointerLock() 함수는 포인터를 현재 위치로 잠그고 숨깁니다. movedX와 movedY를 사용하여 draw() 함수의 마지막 호출 이후에 마우스가 이동한 값을 가져올 수 있습니다.<br><br>모든 브라우저가 이 기능을 지원하지는 않습니다.<br><br>이 함수를 사용하면 마우스를 특정 방향으로 계속 움직여도 화면 밖으로 벗어나지 않도록 처리할 수 있습니다. 1인칭 시점 구현 등에 용이합니다.",
               "returns": ""
             },
             "exitPointerLock": {
        -      "description": "",
        +      "description": "exitPointerLock() 함수는 이전에 설정된 <a href ='https://p5js.org/reference/#/p5/requestPointerLock'>포인터 잠금</a>을 종료합니다. UI 요소 활성화 등을 위해 사용됩니다.",
               "returns": ""
             },
               
        @@ -2300,38 +2308,17 @@
               
               
         // Lights, Camera > Interaction
        -      
        -    "camera": {
        -      "description": "定义在一个三维绘图内相机的位置。此函数的行为与 gluLookAt 相似,不过它会覆盖原有的模型视图矩阵而不会在原有的模型视图上添加任何变形。当没有给予任何参数时,此函数将定义默认相机为 camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);",
        -      "params": ["数字:相机在 x 轴的位置",
        -                 "数字:相机在 y 轴的位置",
        -                 "数字:相机在 z 轴的位置",
        -                 "数字:代表绘图中心点的 x 坐标",
        -                 "数字:代表绘图中心点的 y 坐标",
        -                 "数字:代表绘图中心点的 z 坐标",
        -                 "数字:相机向上方向量的 x 分量",
        -                 "数字:相机向上方向量的 y 分量",
        -                 "数字:相机向上方向量的 z 分量"],
        -      "returns": ""
        +    "orbitControl":{
        +        
             },
        -    "perspective": {
        -      "description": "定义透视相机。当没有给予任何参数时,此函数将定义默认相机为 perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0) 其中 cameraZ 为 ((height/2.0) / tan(PI60.0/360.0));",
        -      "params": ["数字:相机视锥的垂直视野,使用角度模式单位定义视野底部到顶部的角度",
        -                 "数字:相机视锥的长宽比",
        -                 "数字:视锥近平面的长度",
        -                 "数字:视锥远平面的长度"],
        -      "returns": ""
        +    "debugMode":{
        +        
             },
        -    "ortho": {
        -      "description": "定义正射相机。",
        -      "params": ["数字:相机视锥的左平面",
        -                 "数字:相机视锥的右平面",
        -                 "数字:相机视锥的底平面",
        -                 "数字:相机视锥的顶平面",
        -                 "数字:相机视锥的近平面",
        -                 "数字:相机视锥的远平面"],
        -      "returns": ""
        +    "noDebugMode":{
        +        
             },
        +// Lights, Camera > Lights
        +      
             "ambientLight": {
               "description": "使用所定义的颜色创造一个环境光。",
               "params": ["数字:红彩值或色调值,需在被定义的范围内",
        @@ -2344,6 +2331,10 @@
                          "p5.Color:环境光色"],
               "returns": ""
             },
        +      
        +    "specularColor":{
        +        
        +    },
         
             "directionalLight": {
               "description": "使用所定义的颜色及方向创造一个定向光。",
        @@ -2369,6 +2360,23 @@
                          "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
               "returns": ""
             },
        +      
        +    "lights":{
        +        
        +    },
        +    "lightFalloff": {
        +      
        +    },
        +    "spotLight": {
        +      
        +    },
        +    "noLights": {
        +      
        +    },
        +      
        +      
        +// Lights, Camera > Material
        +      
             "loadShader": {
               "description": "从所定义的顶点及片断着色器文件路径加载自定的着色器。着色器是在背景异步加载的,因此此函数应该在 preload() 内使用。<br><br>现在为止有三种主要的着色器种类。只要相对的参数有在着色器内被定义,p5 将会自动提供相对的顶点、法线、颜色及灯光属性。",
               "params": ["字符串:存有顶点着色器源代码的文件的路径",
        @@ -2385,6 +2393,11 @@
               "description": "shader() 函数让其使用者提供自定的着色器以用于在 WEBGL 模式下渲染形状。使用这能使用 loadShader() 加载自定义的着色器。",
               "params": ["p5.Shader:欲用于渲染形状用的 p5.Shader"]
             },
        +      
        +    "resetShader":{
        +        
        +    },
        +      
             "normalMaterial": {
               "description": "形状的法线材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
               "returns": ""
        @@ -2394,6 +2407,19 @@
               "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
               "returns": ""
             },
        +    "textureMode": {
        +      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "returns": ""
        +    },
        +    "textureWrap": {
        +      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "returns": ""
        +    },
        +      
        +      
        +      
             "ambientMaterial": {
               "description": "使用所给予颜色定义形状的环境材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
               "params": ["数字:红彩值或色调值,需在被定义的范围内",
        @@ -2403,6 +2429,15 @@
                          "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
               "returns": ""
             },
        +    "emissiveMaterial": {
        +      "description": "使用所给予颜色定义形状的环境材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        +                 "数字:绿彩值或饱和度值",
        +                 "数字:蓝彩值或亮度值",
        +                 "数字:透明度",
        +                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "returns": ""
        +    },
             "specularMaterial": {
               "description": "使用所给予颜色定义形状的镜面材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
               "params": ["数字:红彩值或色调值,需在被定义的范围内",
        @@ -2412,7 +2447,11 @@
                          "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
               "returns": ""
             },
        -    "p5.RendererGL": {
        +    "shininess": {
        +      "description": "TODO",
        +      "returns": "p5: 该 p5 物件"
        +    },
        +    "p5.Geometry": {
               "description": "TODO",
               "returns": "p5: 该 p5 物件"
             },
        @@ -2422,8 +2461,56 @@
               "String: código fuente para el vertex shader (en forma de string)",
               "String: código fuente para el fragment shader (en forma de string)"],
               "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."]
        +    },
        +   
        +//Lights, Camera > Camera
        +      
        +    "camera": {
        +      "description": "定义在一个三维绘图内相机的位置。此函数的行为与 gluLookAt 相似,不过它会覆盖原有的模型视图矩阵而不会在原有的模型视图上添加任何变形。当没有给予任何参数时,此函数将定义默认相机为 camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);",
        +      "params": ["数字:相机在 x 轴的位置",
        +                 "数字:相机在 y 轴的位置",
        +                 "数字:相机在 z 轴的位置",
        +                 "数字:代表绘图中心点的 x 坐标",
        +                 "数字:代表绘图中心点的 y 坐标",
        +                 "数字:代表绘图中心点的 z 坐标",
        +                 "数字:相机向上方向量的 x 分量",
        +                 "数字:相机向上方向量的 y 分量",
        +                 "数字:相机向上方向量的 z 分量"],
        +      "returns": ""
        +    },
        +    "perspective": {
        +      "description": "定义透视相机。当没有给予任何参数时,此函数将定义默认相机为 perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0) 其中 cameraZ 为 ((height/2.0) / tan(PI60.0/360.0));",
        +      "params": ["数字:相机视锥的垂直视野,使用角度模式单位定义视野底部到顶部的角度",
        +                 "数字:相机视锥的长宽比",
        +                 "数字:视锥近平面的长度",
        +                 "数字:视锥远平面的长度"],
        +      "returns": ""
        +    },
        +    "ortho": {
        +      "description": "定义正射相机。",
        +      "params": ["数字:相机视锥的左平面",
        +                 "数字:相机视锥的右平面",
        +                 "数字:相机视锥的底平面",
        +                 "数字:相机视锥的顶平面",
        +                 "数字:相机视锥的近平面",
        +                 "数字:相机视锥的远平面"],
        +      "returns": ""
        +    },
        +      
        +    "frustrum":{
        +        
        +    },
        +    "createCamera":{
        +        
        +    },
        +    "p5.Camera":{
        +        
        +    },
        +    "setCamera":{
        +        
             }
        -  },
        +      
        +  }
         
           
         }
        \ No newline at end of file
        
        From f53aae58fa20c134aa446b6309d42628a37d61b8 Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Sun, 24 May 2020 00:29:38 +0900
        Subject: [PATCH 30/36] updates as of May 24 00:29 am
        
        ---
         src/data/ko.yml            |   4 +-
         src/data/reference/ko.json | 150 +++++++++++++++++++------------------
         2 files changed, 78 insertions(+), 76 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 9a58e6b7a5..072123f17c 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -32,8 +32,8 @@ tagline6: "프로세싱의 강력함에 자바스크립트의 범용성을 곱
         home:
           start-creating: "p5 에디터로 프로젝트 시작하기"
           p1xh1: "안녕하세요!"
        -  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 특히, 예술가, 디자이너, 교육자, 초심자, 그리고 모두에게 접근성이 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공됩니다. 이는 소프트웨어와 그 학습 도구들이 누구에게나 열려있어야 한다는 생각에 기반합니다."
        -  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 오브젝트를 사용할 수 있습니다."
        +  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 특히, 예술가, 디자이너, 교육자, 초심자, 그리고 모두에게 접근성이 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공되며, 이는 소프트웨어와 학습 도구가 모두에게 열려있어야 한다는 생각에 기반합니다."
        +  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 요소를 사용할 수 있습니다."
           p2xh2: "커뮤니티"
           p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
           p2x2: "p5.js는 프로세싱 "
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 55d6faeca5..fb442c338f 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -920,7 +920,7 @@
           },
           "createCapture": {
             "description": "웹캠의 오디오/비디오 피드를 담는 <video> 요소를 생성합니다. 이 요소는 캔버스와는 별개로 작동합니다. '화면에 나타내기'가 기본값으로 주어지며, .hide()를 사용하여 화면으로부터 숨길 수 있습니다. image() 함수를 사용하여 피드를 캔버스에 그릴 수 있습니다. loadedmetadata 속성을 사용하여 요소가 완전히 로드된 시점을 감지할 수 있습니다. (2번째 예제 참고)<br><br> 피드의 구체적인 속성은 제약 조건(Constraints) 객체를 전달할 수 있습니다. 속성 및 제약 조건 객체와 관련해서는 <a href = 'https://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'>W3C 사양</a>을 참고하세요. 모든 브라우저가 이 기능을 지원하지 않는 점에 유의하세요.<br><br>보안 정보: 최신 브라우저 보안 사양은 createCapture() 이면의 getUserMedia() 메소드가 로컬 또는 HTTPS에서 코드 실행시에만 작동할 것을 요구합니다. 자세한 사항은 <a href = 'https://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>여기</a>와 <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>여기</a>서 확인하세요. ",
        -    "params": ["문자열|상수|객체: 캡쳐 유형, VIDEO 또는 AUDIO 중 하나로 지정 가능. 별도의 매개 변수가 지정되지 않을 경우 기본값으로 둘 다 또는 제약 조건 객체",
        +    "params": ["문자열|상수|객체: 캡처 유형, VIDEO 또는 AUDIO 중 하나로 지정 가능. 별도의 매개 변수가 지정되지 않을 경우 기본값으로 둘 다 또는 제약 조건 객체",
                        "함수: 스트림 로드 완료 후 1번 호출되는 함수 (선택 사항)"],
             "returns": ""
           },
        @@ -1005,7 +1005,7 @@
               "returns": "p5.Graphics: 화면 밖 그래픽 버퍼"
             },
             "blendMode": {
        -      "description": "지정된 모드에 따라 디스플레이 화면상의 픽셀들을 혼합합니다. 소스 픽셀 (A)를 디스플레이 화면 (B)상에 있는 픽셀과 혼합하기 위해 다음 모드를 선택할 수 있습니다:<br><ul><li><code>BLEND</code> - 색상 선형 보간:C = (A)\*계수 + (B). 기본 혼합 모드입니다.</li><li><code>ADD</code> - (A)와 (B)의 합</li><li><code>DARKEST</code> - 가장 어두운 색상만 혼합됩니다:C = min(A*계수, B).</li><li><code>LIGHTEST </code> - 가장 밝은 색상만 혼합됩니다.:C = max(A*계수, B).</li><li><code>DIFFERENCE</code> - 기본 이미지에서 색상값을 뺄셈합니다.</li><li><code>EXCLUSION</code> - DIFFERENCE와 유사하지만 덜 극적입니다.</li><li><code>MULTIPLY</code> - 색상을 곱하는 것으로, 결과값은 좀 더 어둡습니다.</li><li><code>SCREEN</code> - MULTIPLY와 반대로 색상의 반전된 값을 사용합니다.</li><li><code>REPLACE</code> - 픽셀이 다른 픽셀을 완전히 대체하며 알파값(투명도)를 사용하지 않습니다.</li><li><code>OVERLAY</code> - MULTIPLY와 SCREEN의 혼합으로, 어두운 값을 곱하고 밝은 값의 반전된 값을 사용합니다. (2D)</li><li><code>HARD_LIGHT</code> - 회색값이 50%보다 높으면 SCREEN로, 낮으면 MULTIPLY로 처리합니다. (2D)</li><li><code>SOFT_LIGHT</code> - DARKEST와 LIGHTEST 혼합으로, OVERLAY처럼 작동하나 덜 강합니다. (2D)</li><li><code>DODGE</code> - 밝은 색조를 더 밝게 처리하고 대비를 높이며, 어두운 영역은 무시합니다. (2D)</li><li><code>BURN</code> - 어두운 영역이 적용되어 대비가 증가하고 밝기는 무시됩니다. (2D)</li><li><code>SUBTRACT</code> - (A)와 (B)의 나머지(3D)</li></ul><br><br>(2D)는 2D 렌더러에서만 작동하는 혼합 모드를 뜻합니다.<br>(3D)는 WEBGL 렌더러에서만 작동하는 혼합 모드를 뜻합니다.",
        +      "description": "사용자가 지정한 모드에 따라 디스플레이 화면상의 픽셀들을 혼합합니다. 소스 픽셀 (A)를 디스플레이 화면 (B)상에 있는 픽셀과 혼합하기 위해 다음 모드를 선택할 수 있습니다:<br><ul><li><code>BLEND</code> - 색상 선형 보간:C = (A)\*계수 + (B). 기본 혼합 모드입니다.</li><li><code>ADD</code> - (A)와 (B)의 합</li><li><code>DARKEST</code> - 가장 어두운 색상만 혼합됩니다:C = min(A*계수, B).</li><li><code>LIGHTEST </code> - 가장 밝은 색상만 혼합됩니다.:C = max(A*계수, B).</li><li><code>DIFFERENCE</code> - 기본 이미지에서 색상값을 뺄셈합니다.</li><li><code>EXCLUSION</code> - DIFFERENCE와 유사하지만 덜 극적입니다.</li><li><code>MULTIPLY</code> - 색상을 곱하는 것으로, 결과값은 좀 더 어둡습니다.</li><li><code>SCREEN</code> - MULTIPLY와 반대로 색상의 반전된 값을 사용합니다.</li><li><code>REPLACE</code> - 픽셀이 다른 픽셀을 완전히 대체하며 알파값(투명도)를 사용하지 않습니다.</li><li><code>OVERLAY</code> - MULTIPLY와 SCREEN의 혼합으로, 어두운 값을 곱하고 밝은 값의 반전된 값을 사용합니다. (2D)</li><li><code>HARD_LIGHT</code> - 회색값이 50%보다 높으면 SCREEN로, 낮으면 MULTIPLY로 처리합니다. (2D)</li><li><code>SOFT_LIGHT</code> - DARKEST와 LIGHTEST 혼합으로, OVERLAY처럼 작동하나 덜 강합니다. (2D)</li><li><code>DODGE</code> - 밝은 색조를 더 밝게 처리하고 대비를 높이며, 어두운 영역은 무시합니다. (2D)</li><li><code>BURN</code> - 어두운 영역이 적용되어 대비가 증가하고 밝기는 무시됩니다. (2D)</li><li><code>SUBTRACT</code> - (A)와 (B)의 나머지(3D)</li></ul><br><br>(2D)는 2D 렌더러에서만 작동하는 혼합 모드를 뜻합니다.<br>(3D)는 WEBGL 렌더러에서만 작동하는 혼합 모드를 뜻합니다.",
               "params": ["상수:캔버스에 설정되는 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD, REMOVE 또는 SUBTRACT 중 하나"]
               "returns": ""
             },
        @@ -1679,20 +1679,20 @@
               
               
             "touches": {
        -      "description": "touches[] 系统变量将储存一个含有现在所有触动点相对于画布 (0, 0) 位置的位置数组,及分辨个别触动点移动时的 ID。数组内的每个元素都会有 x、y 及 id 属性。<br><br>touches[] 数组并不受 Safari 及 IE 移动设备(包括手提电脑)所支持。",
        +      "description": "시스템 변수 touches[]는 캔버스 (0,0)에 대한 현재의 모든 터치 포인트 위치, 그리고 터치를 식별하는 고유 ID를 담습니다.배열 속 요소들은 각각 x, y, 그리고 id 속성을 갖는 객체들입니다.<br><br>touch[] 배열은 터치 기반 데스크톱 및 노트북상의 Safari나 Internet Explorer에서 지원되지 않습니다.",
               "returns": ""
             },
             "touchStarted": {
        -      "description": "touchStarted() 函数将在每次触动事件被触发时被调用。如果 touchStarted() 函数并未有被定义,mousePressed() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        -      "returns": ""
        +      "description": "touchStarted() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. touchStarted() 함수가 정의되지 않고, mousePressed() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
        +      "params": "객체: TouchEvent 콜백 인수 (선택 사항)"
             },
             "touchMoved": {
        -      "description": "touchMoved() 函数将在每次触点移动事件被触发时被调用。如果 touchMoved() 函数并未有被定义,mouseDragged() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        -      "returns": ""
        +      "description": "touchMoved() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. touchMoved() 함수가 정의되지 않고, mouseDragged() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
        +      "params": "객체: TouchEvent 콜백 인수 (선택 사항)"
             },
             "touchEnded": {
        -      "description": "touchEnded() 函数将在每次触动结束时被调用。如果 touchEnded() 函数并未有被定义,mouseReleased() 函数有被定义的话将会被调用。<br><br>不同浏览器可能有不同附属于个别触动事件的行为。以防止这些默认行为发生,只需在函数尾端加 “return false”。",
        -      "returns": ""
        +      "description": "touchEnded() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. touchEnded() 함수가 정의되지 않고, mouseReleased() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
        +      "params": "객체: TouchEvent 콜백 인수 (선택 사항)"
             },
               
         
        @@ -1701,25 +1701,25 @@
               
               
             "createImage": {
        -      "description": "创造一个新的 p5.Image 物件(储存图像的数据类型)。这将提供一个全新的像素缓冲供您使用。缓冲区的大小将由所提供的宽度和高度参数决定。<br><br>.pixels 将提供一个含有所有像素资料的数组。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。请参考 .pixels 文献。您也能使用更简单的 set() 或 get()。<br><br>在获取一个图像的像素之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。",
        -      "params": ["整数:像素宽度",
        -                 "整数:像素宽度"],
        -      "returns": "p5.Image:p5.Image 物件"
        +      "description": "새로운 p5.Image(이미지 저장을 위한 데이터 유형)를 생성합니다. 이 함수는 새 픽셀 버퍼를 제공합니다. 너비 및 높이 매개 변수로 버퍼 크기를 설정하세요. <br><br>.pixels를 통해 디스플레이 화면의 모든 픽셀값이 담긴 배열에 접근합니다. 픽셀값은 숫자로 표현됩니다. 배열은 디스플레이 화면의 4배 크기(픽셀 밀도에 대한 인수 포함)로, 각 픽셀에 대한 R, G, B, A값을 나타냅니다. 배열은 행의 좌에서 우로, 그 다음 열로 내려가는 순으로 채워집니다. 자세한 내용은 .pixels 레퍼런스를 참고하세요. 몇몇 경우에서는 set() 및 get() 함수를 사용하는 편이 더 편리할 수 있습니다.<br><br>이미지의 픽셀에 접근하기에 앞서, loadPixels() 함수를 통해 픽셀을 불러와야 합니다. 또한, 배열 데이터를 수정한 후에는 updatePixels()로 수정된 내용을 반영해야 합니다.",
        +      "params": ["정수: 픽셀 단위 너비값",
        +                 "정수: 픽셀 단위 높이값"],
        +      "returns": "p5.Image: p5.Image 객체"
             },
             "saveCanvas": {
        -      "description": "将现有的画布储存成图像。In Safari, this will open the image in the window and the user must provide their own filename on save-as. Other browsers will either save the file immediately, or prompt the user with a dialogue window.",
        -      "params": ["p5.Element|HTMLCanvasElement:una variable representando un canvas HTML5 específico (opcional)",
        -                 "字符串",
        -                 "字符串:'jpg' 或 'png'"],
        +      "description": "현재 캔버스를 이미지로 저장합니다. 브라우저에 따라 파일을 즉시 저장하거나 사용자에게 대화 상자를 표시합니다. ",
        +      "params": ["p5.Element|HTMLCanvasElement: 특정 HTML5 캔버스를 나타내는 변수 (선택 사항)",
        +                 "문자열: (선택 사항)",
        +                 "문자열: 'jpg' 또는 'png' (선택 사항)"],
               "returns": ""
             },
             "saveFrames": {
        -      "description": "捕捉一系列可用于制作影响的影格图像。接受回调函数。比如说,您可能想要将影格传送至伺服器以方便储存或转变成影像。如果回调函数没有被提供,浏览器将弹出储存文件对话框以尝试下载所有刚被创造的图像。如果提供回调函数,图像资料默认上并不会被储存而是以物件数组的形式被转送至回调函数做参数,数组大小为储存影格的总数。",
        -      "params": ["字符串",
        -                 "字符串:'jpg' 或 'png'",
        -                 "数字:该捕捉的影格的秒数",
        -                 "数字:捕捉影格的帧率",
        -                 "函数(数组):一个用来处理图像资料的回调函数。此函数将会被给予一个数组为参数。此数组将会储存所定义的捕捉影格物件。每一个物件都会有三个属性:imageData - 为 image/octet-stream 类型、filename 及 extension。"],
        +      "description": "동영상 제작에 사용되는 일련의 프레임을 캡처합니다. 콜백을 허용하는 함수로, 프레임을 서버로 보내 저장하거나 동영상으로 변환할 수 있습니다. 콜백을 지정하지 않으면, 생성된 모든 이미지 다운로드를 위한 대화 상자가 브라우저에 팝업창으로 나타납니다. 콜백을 지정할 경우 이미지 데이터를 자동 저장하는 대신, 총 프레임 수와 동일한 갯수의 크기를 갖는 객체 배열을 콜백 함수에 인수로서 전달합니다.<br><br>saveFrames() 함수는 애니메이션의 처음 15개의 프레임만 저장합니다. 재생 시간이 더 긴 애니메이션을 내보내려면 <a href='https://github.com/spite/ccapture.js/'>ccapture.js</a>와 같은 라이브러리를 확인하세요.",
        +      "params": ["문자열:",
        +                 "문자열: 'jpg' 또는 'png'",
        +                 "숫자: 프레임을 저장할 시간(초)",
        +                 "숫자: 저장할 프레임 속도",
        +                 "함수(배열): 이미지 데이터를 처리하는 콜백 함수. 이 함수는 배열을 인수로만 받습니다. 지정된 개수의 객체 프레임이 배열에 포함됩니다. 각 객체는 다음의 3가지 속성을 가집니다: imageData - 이미지/옥텟 스트림, 파일명, 파일 확장자 (선택 사항)"],
               "returns": ""
             },
               
        @@ -1728,47 +1728,49 @@
               
         
             "loadImage": {
        -      "description": "설정한 경로에서 이미지를 불러오고 p5.Image를 생성합니다. 이미지를 불러온 후 바로 렌더링이 가능하지 않은 경우도 있습니다. 이를 피하려면 loadImage()를 preload()에서 호출하거나, 이미지가 준비된 후 다른 명령을 하도록 하는 콜백 함수를 이용하세요. 이미지 경로는 스케치에 링크된 HTML 파일을 기준으로 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는데에 문제가 생길 수 있습니다.",
        +      "description": "사용자가 지정한 경로로부터 이미지를 불러오고 p5.Image를 생성합니다. <br><br>이미지를 불러와도 곧바로 렌더링되지 않는 경우가 있습니다. 여타 작업을 수행하기에 앞서 이미지 로드를 완료하려면, loadImage()를 preload() 함수 안에서 호출하면 됩니다. 또는, 로드가 완료된 이미지 처리를 위한 콜백 함수를 지정할 수 있습니다. <br><br>이미지 경로는 스케치에 링크된 HTML 파일에 대한 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는 데에 문제가 생길 수 있습니다.",
               "params": ["문자열: 불러올 이미지 경로",
        -      "함수(p5.Image): 이미지를 불러온 후 호출할 함수",
        -      "함수(Event): 이미지 불러오기를 실패하는 경우에 호출할 함수"]
        +      "함수(p5.Image): 이미지 불러오기 후 호출되는 함수로, p5.Image가 전달됩니다. (선택 사항)",
        +      "함수(Event): 이미지 불러오기 실패시 이벤트 에러와 함께 호출되는 함수 (선택 사항)"],
        +       "returns": "p5.Image: p5.Image 객체"  
             },
        +      
             "image": {
        -      "description": "p5.js 캔버스에 이미지를 배치합니다. 본 함수를 사용하는 몇가지 방법을 소개하자면 다음과 같습니다. (1) 가장 간단한 방법은 img, x, y 세 개의 변수를 사용하는 방법입니다. x, y는 이미지의 위치를 지정합니다. (2) 이미지의 크기를 설정하려면 img, x, y와 더불어 이미지의 너비와 높이를 설정하는 두개의 변수를 추가로 사용합니다. (3) 여덟개의 변수를 사용하는 방법입니다. 먼저, 각 변수들을 구별하기 위해 p5.js에서 사용하는 용어를 배워봅시다. 첫번째 용어는 '목적지 사각형(destination rectagle)로, dx, dy 등의 변수가 이에 해당합니다. 두번째 용어는 '원본 이미지(source image)'로, sx, sy등의 변수가 이에 해당합니다. '원본 이미지'의 크기를 설정하면 해당 이미지의 일부만을 디스플레이할 때 유용합니다. 자세한 사항은 아래 도식을 참고하세요.",
        -      "params": ["p5.Image, p5.Element: 디스플레이할 이미지",
        -      "숫자: 왼쪽 위 모서리의 x 좌표",
        -      "숫자: 왼쪽 위 모서리의 y 좌표",
        -      "숫자: 이미지 너비 설정",
        -      "숫자: 이미지 높이 설정",
        -      "숫자: 원본 이미지를 배치할 목적지 사각형의 x 좌표",
        -      "숫자: 원본 이미지를 배치할 목적지 사각형의 y 좌표",
        -      "숫자: 목적지 사각형의 너비",
        -      "숫자: 목적지 사각형의 높이",
        -      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 x좌표",
        -      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표",
        -      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비",
        -      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이"]
        +      "description": "p5.js 캔버스에 이미지를 그립니다.<br> image() 함수의 사용 방법은 다음과 같습니다. (1) 가장 간단한 방법은 img, x, y 3개의 변수를 사용하는 방법입니다. x, y는 이미지의 (x,y) 좌표값 위치입니다. (2) img, x, y에 더해 이미지의 너비와 높이를 설정하는 2개의 변수를 추가로 사용합니다. (3) 8개의 변수를 사용합니다. 먼저, 변수 구별을 위해 p5.js에서 사용하는 용어를 배워봅시다. 첫 번째 용어는 '목적지 사각형(destination rectagle)'으로, dx, dy 등의 변수가 이에 해당합니다. 두 번째 용어는 '원본 이미지(source image)'로, sx, sy등의 변수가 이에 해당합니다. '원본 이미지'의 크기 설정을 통해 이미지의 일부만을 화면상 나타나게할 수 있습니다. 자세한 사항은 아래 도식을 참고하세요.",
        +      "params": ["p5.Image, p5.Element: 화면에 나타낼 이미지",
        +      "숫자: 왼쪽 위 모서리의 x좌표값",
        +      "숫자: 왼쪽 위 모서리의 y좌표값",
        +      "숫자: 이미지 너비값 (선택 사항)",
        +      "숫자: 이미지 높이값 (선택 사항)",
        +      "숫자: 원본 이미지를 배치할 목적지 사각형의 x좌표값",
        +      "숫자: 원본 이미지를 배치할 목적지 사각형의 y좌표값",
        +      "숫자: 목적지 사각형의 너비값",
        +      "숫자: 목적지 사각형의 높이값",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 x좌표값",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 y좌표값",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 너비값 (선택 사항)",
        +      "숫자: 목적지 사각형에 배치할 원본 이미지 일부의 높이값 (선택 사항)"]
             },
             "tint": {
        -      "description": "定义显示图像的填色值。图像能着色成所定义的颜色或提供透明度值以使其透明化。<br><br>如想是图像透明化但不想影响其颜色,可使用白色为着色值并定义透明度值。比如说,tint(255, 128) 将会使一个图像成为 50% 透明(假设为默认透明度范围 0-255,可使用 colorMode() 调整)。<br><br>灰阶值参数必须低于或等于当时 colorMode() 所定义的最高值。默认最高值为 255。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值,需在被定义的范围内",
        -                 "数字:蓝彩值或亮度值,需在被定义的范围内",
        -                 "数字:",
        -                 "字符串:颜色字符串",
        -                 "数字:灰阶值",
        -                 "数字[]:一个有红、绿、蓝及透明度值的数组",
        -                 "p5.Color:着色色值"],
        +      "description": "화면에 나타날 이미지의 면채우기 값을 설정합니다. 이미지에 색조를 입히거나 알파값을 통해 투명도를 조정할 수 있습니다.<br><br>이미지 본래의 색상을 유지하면서 투명도를 적용하려면, 흰색 색조에 알파값을 지정하면 됩니다. 예를 들어 tint(255, 128)는 이미지를 50% 투명하게 만듭니다. (기본 알파 범위 0-255를 가정, 범위는 colorMode()로 조정 가능)<br><br>회색값 매개 변수는 현재 colorMode()에 따른 최대값보다 작거나 같아야합니다. 기본 최대값은 255입니다.",
        +      "params": ["숫자: 현재 색상 범위에 대한 빨강색값 또는 색조값",
        +                 "숫자: 현재 색상 범위에 대한 초록색값 또는 채도값",
        +                 "숫자: 현재 색상 범위에 대한 파랑색값 또는 밝기값"",
        +                 "숫자: (선택 사항)",
        +                 "문자열: 색상 문자열",
        +                 "숫자: 회색값",
        +                 "숫자 배열[]: 색상의 R, G, B & 알파값을 담는 배열",
        +                 "p5.Color: 입힐 색조의 색상],
               "returns": ""
             },
             "noTint": {
        -      "description": "移除当时显示图像的填色值并将其恢复成显示图形的原色调。",
        +      "description": "화면에 나타날 이미지의 현재 면채우기 값을 제거하고 이미지의 본래 색상으로 되돌아갑니다.",
               "returns": ""
             },
             "imageMode": {
        -      "description": "定义图像模式。更改 image() 解读参数的方式以更改图像开始绘制的位置。默认模式为 imageMode(CORNER),此模式将解读第二及第三个参数为图像的左上角位置。如果加多两个参数,它们则被用来定义图像的宽度和高度。<br><br>imageMode(CORNERS) 将使 image() 函数解读第二及第三个参数为一个角落的位置,而第四个第五个参数为对面角落的位置。<br><br>imageMode(CENTER) 将使 image() 函数解读第二及第三个参数为图像的中心点。如果提供多两个参数,它们将被用来定义图像的宽度和高度。",
        +      "description": "이미지의 모드를 설정합니다. image()의 매개 변수가 해석되는 방식을 변경하여 이미지가 그려지는 위치를 수정합니다. 기본 모드는 imageMode(CORNER)이며, image()의 2번째 및 3번째 매개 변수를 이미지의 좌측 상단 모퉁이의 좌표값으로 해석합니다. 추가 매개 변수 2개를 통해 이미지의 너비와 높이도 설정할 수 있습니다.<br><br>imageMode(CORNERS)는 image()의 2번째 및 3번째 매개 변수를 모퉁이 한 개의 좌표값으로 해석합니다. 그리고, 4번째 및 5번째 매개 변수를 그 반대편 모퉁이의 좌표값으로 해석합니다.<br><br>imageMode(CENTER)는 2번째 및 3번째 매개 변수를 이미지의 중심점 좌표값으로 해석합니다. 추가 매개 변수 2개를 통해 이미지의 너비와 높이도 설정할 수 있습니다.",
               "params": ["常量:CORNER、CORNERS 或 CENTER"],
        -      "returns": ""
        +      "params": "상수: CORNER, CORNERS, CENTER 중 하나"
             },
               
               
        @@ -1776,34 +1778,34 @@
               
               
             "pixels": {
        -      "description": "此数组为一个储存显示窗口内所有像素值的 Uint8ClampedArray。这些值都为数字。这数组的大小为(同时考虑像素密度)显示窗口的大小 x4,分别代表每个像素由左到右,上到下的 R、G、B、A 值。视网膜显示及其他高密度显示器将会有更多像素(pixelDensity^2 倍)。比如说,如果图像为 100x100 像素,总共会有 40,000 个元素在 pixels[] 数组内。而在一个视网膜显示,将会有 160,000 个元素。<br><br>数组内最初四个值(指数 0-3)将会是在坐标 (0, 0) 的像素的 R、G、B、A 值。下四个值(指数 4-7)将会是在坐标 (1, 0) 的像素的 R、G、B、A 值。一般上,如果要设置像素 (x, y) 的值: <pre>CODE BLOCK PENDING</pre> 虽然以上的方式有点复杂,它能提供足够的弹性以应对任何像素密度的显示。注意 set() 将会自动处理设定所有在任何像素密度下 (x, y) 坐标在 pixels[] 内的值,不过程序性能可能在像素数组被更改很多次时时不佳。<br><br>在使用这个数组之前,像素资料必须先使用 loadPixels() 函数加载。在数组资料被修改后,updatePixels() 函数必须被调用以更新图像资料。<br><br>注意这不是个普通的 Javascript 数组。这表示 Javascript 数组函数如 <code>slice()</code> 或 <code>arrayCopy()</code> 将不会有效果。",
        +      "description": "디스플레이 화면의 모든 픽셀값을 담는 <a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray'>Uint8ClampedArray</a>입니다. 픽셀값은 숫자로 표현됩니다. 배열은 디스플레이 화면의 4배 크기(픽셀 밀도에 대한 인수 포함)로, 각 픽셀에 대한 R, G, B, A값을 나타냅니다. 배열은 행의 좌에서 우로, 그 다음 열로 내려가는 순으로 채워집니다. Retina를 비롯한 기타 고밀도 디스플레이는 (pixelDensity^2 계수로 인해) 크기가 더 큰 픽셀 배열[]을 갖기도 합니다. 일반 디스플레이 화면상 이미지가 100x100 픽셀이고 그 배열이 40,000이라면, Retina에서 배열은 160,000이 됩니다. <br><br>배열상 처음 4개의 값들(즉, 인덱스 0-3)은 (0,0) 픽셀에서의 R, G, B, A값을, 그 다음 4개의 값들(즉, 인덱스 4-7)은 (1,0) 픽셀에서의 R, G, B, A값을 담습니다. 특정 좌표 (x,y)에서의 픽셀값을 설정하는 방법은 아래의 예제와 같습니다.<br><br>다소 복잡해보이는 예제지만, 모든 픽셀 밀도(pixelDensity)를 사용할 수 있을정도로 유연합니다. set()은 임의의 pixelDensity에서 주어진 (x,y)에 대한 픽셀 배열[]의 모든 값들을 자동으로 설정합니다. 배열을 여러 차례 수정할 경우, 성능이 느려질 수 있습니다.<br><br>이 레퍼런스는 표준 자바스크립트 배열이 아니고, 따라서 slice()나 arrayCopy()와 같은 표준 자바스크립트 함수가 작동하지 않는 점에 유의하세요.  ",
               "returns": ""
             },
             "blend": {
        -      "description": "将一个图像内一个区域的像素复制去另一个图像,同时使用所定义的混合模式执行复制。",
        -      "params": ["p5.Image:原图像",
        -                 "整数:原图像的左上角 x 坐标",
        -                 "整数:原图像的左上角 y 坐标",
        -                 "整数:原图像的宽度",
        -                 "整数:原图像的高度",
        -                 "整数:终点图像左上角的 x 坐标",
        -                 "整数:终点图像左上角的 y 坐标",
        -                 "整数:终点图像的宽度",
        -                 "整数:终点图像的高度",
        -                 "常量:混合模式。BLEND、DARKEST、LIGHTEST、DIFFERENCE、MULTIPLY、EXCLUSION、SCREEN、REPLACE、OVERLAY、HARD_LIGHT、SOFT_LIGHT、DODGE、BURN、ADD 或 NORMAL。"],
        +      "description": "사용자가 지정한 혼합 모드를 사용하여, 한 이미지의 픽셀 영역을 다른 이미지로 복사합니다.",
        +      "params": ["p5.Image: 원본 이미지",
        +                 "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        +                 "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        +                 "정수: 원본 이미지 너비값",
        +                 "정수: 원본 이미지 높이값",
        +                 "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        +                 "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        +                 "정수: 대상 이미지 너비값",
        +                 "정수: 대상 이미지 높이값",
        +                 "상수: 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD or NORMAL 중 하나"],
               "returns": ""
             },
             "copy": {
        -      "description": "将画布内一个区域的像素复制去画布内另外一个区域同时也复制一个由 srcImg 参数所定义的图像内一个区域的像素去定义 srcImage 的画布上,这将是原图像。如果原图像与重点区域的大小不同,它将会自动缩放原图像的像素以符合所定义的终点区域。",
        -      "params": ["p5.Image:原图像",
        -                 "整数:原图像的左上角 x 坐标",
        -                 "整数:原图像的左上角 y 坐标",
        -                 "整数:原图像的宽度",
        -                 "整数:原图像的高度",
        -                 "整数:终点图像左上角的 x 坐标",
        -                 "整数:终点图像左上角的 y 坐标",
        -                 "整数:终点图像的宽度",
        -                 "整数:终点图像的高度"],
        +      "description": "캔버스의 한 영역을 다른 영역에 복사하고, srcImg 매개 변수로 사용되는 한 이미지의 픽셀 영역을 캔버스에 복사합니다. srcImage는 원본 이미지로, 사용자가 지정합니다. 원본과 복사 대상 영역의 크기가 같지 않을 경우, 원본 픽셀 영역의 크기를 대상 영역의 크기에 맞게 자동으로 재조정합니다.",
        +      "params": ["p5.Image|p5 요소: 원본 이미지",
        +                 "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        +                 "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        +                 "정수: 원본 이미지 너비값",
        +                 "정수: 원본 이미지 높이값",
        +                 "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        +                 "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        +                 "정수: 대상 이미지 너비값",
        +                 "정수: 대상 이미지 높이값"],
               "returns": ""
             },
             "filter": {
        
        From 5d7204613af4b9fbbf2a1e458e3df90eda3db8de Mon Sep 17 00:00:00 2001
        From: Inhwa Yeom <yinhwa.erica@gmail.com>
        Date: Sun, 24 May 2020 00:56:12 +0900
        Subject: [PATCH 31/36] quick update as of May 24 00:56 am
        
        ---
         src/data/reference/ko.json | 6 +++---
         1 file changed, 3 insertions(+), 3 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index fb442c338f..1be3e5ac7c 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -1809,9 +1809,9 @@
               "returns": ""
             },
             "filter": {
        -      "description": "在画布上使用过滤器。<br><br>预设选择为:<br><br>THRESHOLD 将图像转换成黑与白像素,取决于它们是否高于或低于所定义的 level 参数值。参数值必须在 0.0(黑色)与 1.0(白色)之间。如果并没有提供参数的话,默认将设为 0.5。<br><br>GRAY 将图像内的颜色转换成灰阶色。不使用任何参数。<br><br>OPAQUE 设置所有透明度值成完全不透明。不使用任何参数。<br><br>INVERT 设置每个像素成其反值。不使用任何参数。<br><br>POSTERIZE 将限制每个图像的彩色通道至参数所定义的颜色数。参数值可以介于 2 至 255 之间,但是效果会在较低值是比较明显。<br><br>BLUR 将使用 level 参数所定义的模糊度执行高斯模糊。如果没有提供参数,模糊度为高斯模糊半径为 1。越大的值越模糊。<br><br>ERODE 减少亮区。不使用任何参数。<br><br>DILATE 增加亮区。不使用任何参数。",
        -      "params": ["常量:THRESHOLD、GRAY、OPAQUE、INVERT、POSTERIZE、BLUR、ERODE、DILATE 或 BLUR。",
        -                 "数字:每个过滤器独有的可选性参数,请看以上"],
        +      "description": "캔버스에 필터를 적용합니다.<br><br>GRAY: 이미지의 모든 색상을 그레이 스케일로 변환합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>OPAQUE: 알파 채널을 완전히 불투명하게 설정합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>INVERT: 각 픽셀을 그 역의 값으로 설정합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>POSTERIZE: 이미지의 각 채널을 매개 변수로 지정한 색상 수로 제한합니다. 매개 변수는 2부터 255사이의 값으로 설정 가능하나, 낮은 범위에서 가장 두드러진 결과를 볼 수 있습니다.<br><br>BLUR: 블러 범위를 설정하는 level 매개 변수를 사용하여 가우시안 블러를 실행합니다. 별도의 매개 변수를 지정하지 않으면, 반경 1의 가우시안 블러와 동일한 효과가 됩니다. 값이 클수록 흐림 정도가 증가합니다.<br><br>ERODE: 밝은 영역을 줄입니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>DILATE: 밝은 영역을 증가시킵니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>WebGL 모드에서는 filter()가 작동하지 않으나, 커스텀 셰이더를 사용하여 유사한 효과를 얻을 수 있습니다. 아담 페리스(Adam Ferriss)가 작성한 <a href='https://github.com/aferriss/p5jsShaderExamples'>셰이더 예제</a> 중, filter()와 유사한 효과를 나타내는 예제들이 있으니 참고하세요.",
        +      "params": ["상수: THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE, DILATE, BLUR 중 하나. 각 필터에 대한 문서는 Filters.js를 참조.",
        +                 "숫자: 각 필터 고유의 선택적 매개 변수 (선택 사항)"],
               "returns": ""
             },
             "get": {
        
        From c83f5efa495e20ee6d99c19f8ac4227aab9b7f43 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Sun, 24 May 2020 20:31:06 +0900
        Subject: [PATCH 32/36] updates as of May 24 20:31 pm
        
        ---
         src/data/reference/ko.json | 608 +++++++++++++++++++++----------------
         1 file changed, 350 insertions(+), 258 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 1be3e5ac7c..d84656ae4b 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -109,7 +109,7 @@
               "returns": "밝기값"
             },
             "color": {
        -      "description": "색상 함수를 이용해 색상 데이터의 매개변수를 저장해보세요. 이 때, 매개변수는 colorMode()의 설정에 따라 RGB 또는 HSB 값으로 처리됩니다. 기본 모드인 RGB값은 0부터 255까지이며, 따라서 color(255,204,0)와 같은 함수는 밝은 노랑색을 반환하게 됩니다. <br><br>         만약에 color() 함수에 매개변수가 1개만 적히면, 회색 음영(grayscale)값으로 처리됩니다. 여기에 추가되는 두번째 변수는 투명도를 설정할 수 있는 알파값으로서 처리됩니다. 세번째 변수가 추가되었을 때 비로소 RGB나 HSB값으로 처리되지요. RGB나 HSB값을 정하는 3개의 변수가 존재할 때 추가되는 네번째 변수는 알파값으로 적용됩니다. <br><br> 나아가, p5는 RGB, RGBA, Hex CSS 색상 문자열과 모든 색상명 문자열 역시 지원합니다. 그 경우, 알파값은 괄호 내 2번째 매개변수 추가를 통해서가 아닌, RGBA 형식에 따라 지정될 수 있습니다.",
        +      "description": "색상 함수를 이용해 색상 데이터의 매개 변수를 저장해보세요. 이 때, 매개 변수는 colorMode()의 설정에 따라 RGB 또는 HSB 값으로 처리됩니다. 기본 모드인 RGB값은 0부터 255까지이며, 따라서 color(255,204,0)와 같은 함수는 밝은 노랑색을 반환하게 됩니다. <br><br>         만약에 color() 함수에 매개 변수가 1개만 적히면, 회색 음영(grayscale)값으로 처리됩니다. 여기에 추가되는 두번째 변수는 투명도를 설정할 수 있는 알파값으로서 처리됩니다. 세번째 변수가 추가되었을 때 비로소 RGB나 HSB값으로 처리되지요. RGB나 HSB값을 정하는 3개의 변수가 존재할 때 추가되는 네번째 변수는 알파값으로 적용됩니다. <br><br> 나아가, p5는 RGB, RGBA, Hex CSS 색상 문자열과 모든 색상명 문자열 역시 지원합니다. 그 경우, 알파값은 괄호 내 2번째 매개 변수 추가를 통해서가 아닌, RGBA 형식에 따라 지정될 수 있습니다.",
               "params": ["숫자: 흑과 백 사이의 값 지정",
               "숫자: 현재 색상 범위(기본값: 0-255)에 대한 알파값)",
               "숫자: 현재 색상 범위 내 빨강색(R) 또는 색조값 지정",
        @@ -130,7 +130,7 @@
               "returns": "색조"
             },
             "lerpColor": {
        -      "description": "두 가지 색상을 혼합하고, 그 사이에 존재하는 제 3의 색상을 찾습니다. 여기서 amt 매개변수는 두 개의 값 사이를 선형적으로 보간합니다. 예를 들어, 0.0은 첫 번째 값과 동일한 색상값을, 0.1은 첫 번째 값에 매우 가까운 색상값을, 0.5는 두 값 사이의 중간 색상값을 나타내는 식입니다. 이 때, 0 미만의 값은 0으로, 1이상의 값은 1로 자동 변환됩니다. 이 점에서 lerpColor()는 lerp()와 다르게 작동하는 셈인데, 이처럼 lerpColor()는 색상값을 0과 1사이로 조정하여 지정된 범위를 벗어난 색상 생성을 방지합니다. 또한, 색상이 보간되는 방식은 현재 지정된 색상 모드에 따라 달라집니다.",
        +      "description": "두 가지 색상을 혼합하고, 그 사이에 존재하는 제 3의 색상을 찾습니다. 여기서 매개 변수 amt는 두 개의 값 사이를 선형적으로 보간합니다. 예를 들어, 0.0은 첫 번째 값과 동일한 색상값을, 0.1은 첫 번째 값에 매우 가까운 색상값을, 0.5는 두 값 사이의 중간 색상값을 나타내는 식입니다. 이 때, 0 미만의 값은 0으로, 1이상의 값은 1로 자동 변환됩니다. 이 점에서 lerpColor()는 lerp()와 다르게 작동하는 셈인데, 이처럼 lerpColor()는 색상값을 0과 1사이로 조정하여 지정된 범위를 벗어난 색상 생성을 방지합니다. 또한, 색상이 보간되는 방식은 현재 지정된 색상 모드에 따라 달라집니다.",
               "params": ["이 색상으로부터 선형 보간",
               "이 색상을 향해 선형 보간",
               "숫자: 0과 1 사이의 숫자"],
        @@ -173,7 +173,7 @@
               "returns": "p5 객체"
             },
             "colorMode": {
        -      "description": "colorMode()는 p5.js가 색상 데이터를 해석하는 방식을 결정합니다. 기본값으로, fill(), stroke(), background(), color()의 매개변수는 RGB 색상 모드에서 처리되며, 그 범위는 0부터 255까지입니다. 이 기본값은 colorMode(RGB, 255)와 동일한 효과를 지닙니다. colorMode(HSB)로 설정을 변경하면 HSB 색상 시스템을 사용할 수 있습니다. HSB 색상 시스템은 그 기본값으로 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 색상 모드는 HSL로도 설정가능합니다. <br>참고: 모든 색상 객체들은 생성 당시에 지정된 색상 모드를 반영합니다. 따라서, 이미 생성된 색상 객체 중 일부에만 적용되는 색상 모드를 지정할 수도 있습니다.",
        +      "description": "colorMode()는 p5.js가 색상 데이터를 해석하는 방식을 결정합니다. 기본값으로, fill(), stroke(), background(), color()의 매개 변수는 RGB 색상 모드에서 처리되며, 그 범위는 0부터 255까지입니다. 이 기본값은 colorMode(RGB, 255)와 동일한 효과를 지닙니다. colorMode(HSB)로 설정을 변경하면 HSB 색상 시스템을 사용할 수 있습니다. HSB 색상 시스템은 그 기본값으로 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 색상 모드는 HSL로도 설정가능합니다. <br>참고: 모든 색상 객체들은 생성 당시에 지정된 색상 모드를 반영합니다. 따라서, 이미 생성된 색상 객체 중 일부에만 적용되는 색상 모드를 지정할 수도 있습니다.",
               "params": ["상수: RGB(빨강Red/초록Green/파랑색Blue), HSB(색조Hue/채도Saturation/밝기Brightness), HSL(색조Hue/채도Saturation/명도Lightness) 중 하나",
               "숫자: 모든 값들의 범위 (선택 사항)",
               "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        @@ -412,7 +412,7 @@
               "returns": ""
             },
             "curveTightness": {
        -      "description": "curve()와 curveVertex() 함수를 사용하여 모양을 변경합니다. 곡선의 팽팽함(tightness)을 지정하는 매개변수 t는, 두 꼭지점 사이에 곡선이 들어맞는 정도를 결정합니다. 값 0.0은 곡선의 팽팽함에 대한 기본값이며(이 값을 통해 곡선을 캣멀롬 스플라인으로 정의), 값 1.0은 모든 점을 직선 상태로 연결하게 됩니다. -5.0와 5.0 사이의 값들은 화면상 인식 가능한 범위 내에서 값의 크기에 비례하여 곡선을 변형합니다.",
        +      "description": "curve()와 curveVertex() 함수를 사용하여 모양을 변경합니다. 곡선의 팽팽함(tightness)을 지정하는 매개 변수 t는, 두 꼭지점 사이에 곡선이 들어맞는 정도를 결정합니다. 값 0.0은 곡선의 팽팽함에 대한 기본값이며(이 값을 통해 곡선을 캣멀롬 스플라인으로 정의), 값 1.0은 모든 점을 직선 상태로 연결하게 됩니다. -5.0와 5.0 사이의 값들은 화면상 인식 가능한 범위 내에서 값의 크기에 비례하여 곡선을 변형합니다.",
               "params": ["숫자: 원래 꼭지점으로부터 변형된 정도의 양"],
               "returns": ""
             },
        @@ -1815,30 +1815,30 @@
               "returns": ""
             },
             "get": {
        -      "description": "返回任何像素值的一个为 [R,G,B,A] 的数组或捕捉图像的一部分。如果没有提供任何参数,将会返回整个图像。可使用 x 及 y 参数以取得一个像素的值。多加定义 w 及 h 参数可取的显示窗口的一部分。当在取得图像时,x 及 y 参数将定义图像的左上角坐标值,无论当时的图像模式为何。<br><br>如果欲取得的像素在图像外,将返回 [0,0,0,255]。以取得根据当时的颜色值范围及颜色模式的数字,请使用 getColor 而不是 get。<br><br>使用 get(x, y) 以取得一个像素的颜色相对来说简单,但是其速度并没有直接从 pixels[] 数组获取数据来的快。与使用 get(x, y) 有相同的效果但使用 pixels[] 及像素密度 d 的范例如下 <code>var x, y, d; // 设置这为坐标 var off = (y width + x) d * 4; var components = [ pixels[off], pixels[off + 1], pixels[off + 2], pixels[off + 3] ]; print(components);</code><br><br>请参考 pixels[] 文献以知更多详情。",
        -      "params": ["数字:像素的 x 坐标",
        -                 "数字:像素的 y 坐标",
        -                 "数字:宽度",
        -                 "数字:高度"],
        -      "returns": "数字[]|p5.Image:在 x,y 的像素值数组或 p5.Image"
        +      "description": "지정된 픽셀 영역 또는 단일 픽셀을 캔버스로부터 받아옵니다.<br><br>특정 픽셀에 대한 [R,G,B,A] 값의 배열이나, 이미지의 한 영역을 반환합니다. 별도의 매개 변수를 지정하지 않는 경우, 전체 이미지를 반환합니다. 매개 변수 x, y를 통해 특정 픽셀의 좌표값을 받아올 수 있습니다. 추가 매개 변수 w, h를 통해 디스플레이 창의 한 영역을 지정할 수도 있습니다. 이미지를 받아올 때, 매개 변수 x와 y는 현재 imageMode()와 관계없이 좌측 상단 모퉁이의 좌표값을 정의합니다. <br><br>get(x,y) 함수로 픽셀 1개의 색상을 받아오는 것은 쉬운 방법이지만, pixels[] 배열로부터 직접 데이터를 받아오는 것만큼 빠르진 않습니다. pixels[] 배열과 픽셀 밀도 매개 변수 d를 사용하여 get(x,y)과 동일한 효과를 나타낼 수 있고, 구체적인 명령문은 다음의 예제와 같습니다.<br><br>더 많은 정보는 pixels[] 레퍼런스를 확인하세요.<br>p5.Image 객체의 하위 이미지로부터 색상 배열을 추출하는 방법은 p5.Image.get()에서 참고하세요.",
        +      "params": ["숫자: 픽셀의 x좌표값",
        +                 "숫자: 픽셀의 y좌표값",
        +                 "숫자: 너비",
        +                 "숫자: 높이"],
        +      "returns": "p5.Image: 직사각형 p5.Image"
             },
             "loadPixels": {
        -      "description": "将显示窗口的像素资料加载到 pixels[] 数组里。这函数必须在读写 pixels[] 之前被调用。注意只有使用 set() 或直接修改 pixels[] 的改变会发生。",
        +      "description": "디스플레이 창의 픽셀 데이터를 pixels[] 배열에 불러옵니다. 이 함수는 pixels[] 배열을 작성하거나 읽어오기 전에 호출되어야 합니다. set() 함수 또는 pixels[] 배열 직접 조작을 통한 변경 사항만 반영합니다.",
               "returns": ""
             },
             "set": {
        -      "description": "改变任何像素的颜色,或直接在显示窗口内绘画一个图像。<br><br>x 及 y 参数用于定义该改变的像素而 c 参数用于定义颜色值。这可以是一个 p5.Color 物件或一个 [R, G, B, A] 像素数组。它也能是一个灰阶值。在设定一个图像时,x 及 y 参数将定义图像左上角的坐标值,无论当时的图像模式为何。<br><br>在使用 set() 后,您必须调用 updatePixels() 以使您的改变生效。这应该在所有像素都被设定后才被调用,而且也必须在调用 get() 或绘制图像之前调用。<br><br>使用 set(x, y) 设置一个像素的颜色相对来说简单,但使其速度并没有直接将数据写在 pixels[] 数组里来的快。直接使用 pixels[] 设置像素值可能在使用视网膜显示器时比较复杂,不过它会在每一个循环有很多像素需要被设定时表现得更好。<br><br>请参考 pixels[] 文献以知更多详情。",
        -      "params": ["数字:像素的 x 坐标",
        -                 "数字:像素的 y 坐标",
        -                 "数字|数字[]|物件:插入一个灰阶值 | 一个像素数组 | 一个 p5.Color 物件 | 一个用于复制的 p5.Image"],
        +      "description": "특정 픽셀의 색상을 변경하거나, 디스플레이 창에 이미지를 직접 작성합니다.<br><br>매개 변수 x와 y는 변경할 픽셀을 지정하고, 매개 변수 c는 색상값을 지정합니다. 색상값으로는 p5.Color 객체, [R,G,B,A] 베열, 또는 단일 그레이 스케일값을 사용할 수 있습니다. 이미지 설정시, 매개 변수 x와 y는 현재 imageMode()와 관계없이 좌측 상단 모퉁이의 좌표값을 정의합니다.<br><br>set() 함수 사용 후에는 반드시 updatePixels()를 호출하여 변경 사항을 반영해야 합니다. 호출 시점은 픽셀 설정을 완료한 이후이면서 동시에, .get() 또는 그리기 함수 호출 이전이어야 합니다.<br><br>set(x,y) 함수로 픽셀 1개의 색상을 받아오는 것은 쉬운 방법이지만, pixels[] 배열로부터 직접 데이터를 받아오는 것만큼 빠르진 않습니다. 레티나 디스플레이에선 pixels[] 배열값을 직접 설정하는 것이 복잡할 수 있으나, 많은 양의 픽셀들이 반복 실행되도록 설정된 경우 그 작업 성능이 향상됩니다.<br><br>자세한 내용은 pixels[]를 참고하세요. ",
        +      "params": ["숫자: 픽셀의 x좌표값",
        +                 "숫자: 픽셀의 y좌표값",
        +                 "숫자|숫자 배열[]|객체: 그레이스케일 값 기입|픽셀 배열|p5.Color객체|복사할p5.Image"],
               "returns": ""
             },
             "updatePixels": {
        -      "description": "使用 pixels[] 数组内的资料更新显示窗口。通常与 loadPixels() 一起使用。如果您只需从该数组中读取像素资料,您不需要调用 updatePixels() — 更新只有在进行更改时需要被调用。updatePixels() 应该在像素数组被更改或 set() 被调用时使用,只有使用 set() 或直接修改 pixels[] 的改变会发生。",
        -      "params": ["数字:欲更新的区域的左上角 x 坐标",
        -                 "数字:欲更新的区域的左上角 y 坐标",
        -                 "数字:欲更新的区域的宽度",
        -                 "数字:欲更新的区域的高度"],
        +      "description": "pixels[] 배열의 데이터로 디스플레이 창을 업데이트합니다. loadPixels()와 함께 사용하세요. 배열로부터 픽셀값을 읽어오기만 할 경우, updatePixels()를 사용할 필요가 없습니다. 업데이트는 배열값 변경 사항을 적용하는 데에만 필요합니다. updatePixels()는 픽셀 배열을 수정하거나 set() 함수를 호출할 때마다 매번 호출되어야하며, set() 함수 또는 pixels[] 배열 직접 조작을 통한 변경 사항만 반영합니다.,
        +      "params": ["숫자: 업데이트할 영역의 좌측 상단 모퉁이 x좌표값 (선택 사항)",
        +                 "숫자: 업데이트할 영역의 좌측 상단 모퉁이 y좌표값 (선택 사항)",
        +                 "숫자: 업데이트할 영역의 너비값 (선택 사항)",
        +                 "숫자: 업데이트할 영역의 높이값 (선택 사항)"],
               "returns": ""
             },
               
        @@ -1848,77 +1848,95 @@
               
               
             "loadJSON": {
        -      "description": "从一个文件或网址加载一个 JSON 文件,将返回一个物件。注意如果该 JSON 文件内涵一个数组,此函数仍然会返回一个以数字为指数的物件。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。JSONP 功能支持是由填充工具所提供而您可以使用第二个参数来定义一个有 JSON 回调定义的物件,只需跟从这里的<a href='https://github.com/camsong/fetch-jsonp'>指示</a>。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "物件:关于 jsonp 设置的设置物件",
        -                 "字符串:\"json\" 或 \"jsonp\"",
        -                 "函数:在 loadJSON() 完成后该执行的函数,返回的数据将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": "物件:JSON 数据"
        +      "description": "파일 또는 URL로부터 JSON 파일을 불러오고, 객체를 반환합니다. JSON 파일에 배열이 포함된 경우, 인덱스 번호를 키(key)로 사용하여 객체를 반환할 수 있습니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. JSONP는 polyfill을 통해 지원되며, <a href ='https://github.com/camsong/fetch-jsonp'>여기</a>의 구문에 따라 JSON 콜백 함수가 정의한 객체를 2번째 인수로 전달할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "객체: jsonp 관련 설정을 위한 객체 (선택 사항)",
        +                 "문자열: \"json\" 또는 \"jsonp\"",
        +                 "함수: loadJSON()이 완료된 이후 실행될 함수, 데이터를 1번재 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "객체|배열: JSON 데이터"
             },
        +      
             "loadStrings": {
        -      "description": "读取一个文件的内容并使用个别字行创造一个字符串数组。如果文件名被用作第一个参数,如以上范例,该文件必须被储存在绘图文件夹内。<br><br>除此之外,该文件也能从本地电脑任何位置加载,只需使用绝对路径(任何在 Unix 及 Linux 内由 / 开始的路径,或在 Windows 内由驱动器符号开始的路径),又或者任何在网络上的文件网址也能用来当作 filename 参数。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "函数:在 loadStrings() 完成后该执行的函数,返回的数组将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": "字符串[]:字符串数组"
        +      "description": "파일의 내용을 읽어와 개별 행에 대한 문자열 배열을 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadStrings() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "함수: loadStrings()이 완료된 이후 실행될 함수, 배열을 1번째 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "문자열 배열[]: 문자열들의 배열"
             },
        +      
             "loadTable": {
        -      "description": "读取一个文件的内容并使用其内容创造一个 p5.Table 物件。如果文件名被用作第一个参数,该文件必须被储存在绘图文件夹内。文件名参数也能是一个在网络上的文件的网址。默认上,该文件被假定为以逗号分隔(格式为 CSV)。该表格只会在 ‘header’ 设置被使用时才会寻找标签。<br><br>可使用的设置包括:<ul><li>csv - 将表格解析为逗号分隔值</li><li>tsv - 将表格解析为制表符分隔值</li><li>header - 这表格有标签行</li></ul><br><br>当使用多个设置时,您只需将他们分为个别的参数并使用逗号分隔。例如:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>所有加载及储存的文件都需使用 UTF-8 编码。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。在 preload() 内调用 loadTable() 将保证加载工作会在 setup() 及 draw() 被调用前完成<br><br>在 preload() 外,您可以提供一个回调函数以处理加载物件。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "字符串:\"header\" \"csv\" \"tsv\"",
        -                 "函数:在 loadTable() 完成后该执行的函数,返回的 Table 物件将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": "物件:含有数据的 Table 物件"
        +      "description": "파일 또는 URL의 내용을 읽어와 그 값으로 p5.Table 객체를 만듭니다. 특정 파일을 지정하려면, 해당 파일이 'data' 폴더 안에 있어야 합니다. 매개 변수 filename는 온라인 파일 URL로도 지정 가능합니다. 기본값으로, 파일 내용이 쉼표 단위로 구분된 것(CSV 형식)으로 간주합니다. 'header' 옵션이 포함된 경우, 헤더 행만 찾습니다.<br><br>가능한 옵션은 다음과 같습니다:<ul><li>csv - 테이블을 쉼표로 구분된 값으로서 구문 분석</li><li>tsv - 테이블을 탭으로 구분된 값으로서 구문 분석</li><li>header - 테이블에 헤더 행이 있음을 표기</li></ul><br><br>여러 옵션을 사용할 경우, 매개 변수들을 쉼표로 구분하여 전달할 수 있습니다. 예를 들면 다음과 같습니다:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>불러오기 및 저장된 모든 파일은 UTF-8 인코딩을 사용합니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadTable() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "문자열: \"header\" \"csv\" \"tsv\"",
        +                 "함수: loadTable()이 완료된 이후 실행될 함수, 성공시 Table 객체를 1번째 인수로 전달 (선택 사항)",
        +                "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "객체: 데이터를 포함한 Table 객체"
             },
             "loadXML": {
        -      "description": "读取一个文件的内容并使用其内容创造一个 XML 物件。如果文件名被用作第一个参数,该文件必须被储存在绘图文件夹内。<br><br>除此之外,该文件也能从本地电脑任何位置加载,只需使用绝对路径(任何在 Unix 及 Linux 内由 / 开始的路径,或在 Windows 内由驱动器符号开始的路径),又或者任何在网络上的文件网址也能用来当作 filename 参数。<br><br>这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。在 preload() 内调用 loadTable() 将保证加载工作会在 setup() 及 draw() 被调用前完成<br><br>在 preload() 外,您可以提供一个回调函数以处理加载物件。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "函数:在 loadXML() 完成后该执行的函数,返回的 XML 物件将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": "物件:含有数据的 XML 物件"
        +      "description": "파일의 내용을 읽어와 그 값으로 XML 객체를 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다. <br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadXML() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "함수: loadXML()이 완료된 이후 실행될 함수, XML 객체를 1번째 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "객체: 데이터를 포함한 XML 객체"
             },
             "loadBytes": {
        -      "description": "",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "函数:在 load() 完成后该执行的函数",
        -                 "函数:在发生错误时该执行的函数"],
        -      "returns": "物件:一个 ‘bytes’ 属性将为被加载的缓冲区的物件"
        +      "description": "이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "함수: loadBytes()가 완료된 이후 실행될 함수 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수 (선택 사항)"],
        +      "returns": "객체: 'bytes' 속성을 로드 완료된 버퍼로서 갖는 객체"
             },
             "httpGet": {
        -      "description": "执行 HTTP GET 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。这和调用 httpDo(path, 'GET') 的效果一样。‘binary’ 数据类型将会返回一个 Blob 物件,而 ‘arrayBuffer’ 数据类型将会返回一个 ArrayBuffer 并可用来创造类型化数组(如 Uint8Array)。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "字符串:\"json\"、\"jsonp\"、\"binary\"、\"arrayBuffer\"、\"xml\"或\"text\"",
        -                 "物件|布尔值:与请求一起传送的参数资料",
        -                 "函数:在 httpGet() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": ""
        +      "description": "HTTP GET 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다. 이는 httpDo(path, 'GET')을 호출하는 것과 동일한 효과를 갖습니다. ‘binary’ 데이터 형식은 Blob 객체를, ‘arrayBuffer’ 데이터 형식은 지정된 형식의 배열(예: Uint8Array)을 초기화할 ArrayBuffer를 반환합니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\"",
        +                 "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                 "함수: httpGet()이 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부."
             },
             "httpPost": {
        -      "description": "执行 HTTP POST 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。这和调用 httpDo(path, 'POST') 的效果一样。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "字符串:\"json\"、\"jsonp\"、\"xml\" 或 \"text\"。如果不提供此参数,httpPost() 将尝试猜",
        -                 "物件|布尔值:与请求一起传送的参数资料",
        -                 "函数:在 httpPost() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数"],
        -      "returns": ""
        +      "description": "HTTP POST 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다. 이는 httpDo(path, 'POST')를 호출하는 것과 동일한 효과를 갖습니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\". 생략할 경우, httpPost()가 임의로 가정합니다.",
        +                 "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                 "함수: httpPost()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +      "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부"
             },
             "httpDo": {
        -      "description": "执行 HTTP 请求的函数。如果数据类型(datatype)没有被定义的话,p5 将会尝试根据网址猜返回数据的类型,默认为文字。<br><br>如果需要更高等的使用法,您可以在第一个参数给予路径而第二个参数给予一个物件,物件内容设置与 Fetch API 规范的一样。",
        -      "params": ["字符串:该加载的文件名或网址",
        -                 "字符串:\"GET\"、\"POST\" 或 \"PUT\",默认为 \"GET\"",
        -                 "字符串:\"json\"、\"jsonp\"、\"xml\" 或 \"text\"",
        -                 "物件|布尔值:与请求一起传送的参数资料",
        -                 "函数:在 httpDo() 完成后该执行的函数,返回的资料物件将会是函数第一个参数",
        -                 "函数:在发生错误时该执行的函数,回复将会是函数第一个参数",
        -                 "物件:Request 物件,请参考 “fetch” API <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>文献</a>以了解可使用设置"],
        -      "returns": ""
        +      "description": "HTTP 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다.<br><br>고급 응용 단계에서는 경로를 1번째 인수로, 객체를 2번째 인수로 전달할 수 있습니다. 서명은 Fetch API 사양을 따릅니다. 이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "문자열: \"GET\", \"POST\", \"PUT\" 중 하나, 기본값은 \"GET\"",
        +                 "문자열: \"json\", \"jsonp\", \"xml\" 또는 \"text\" (선택 사항)",
        +                 "객체: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                 "함수: httpDo()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)",
        +                 "객체: <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>Fetch API 레퍼런스</a>에 따른 요청(request) 객체 옵션"],
        +      "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부"
             },
               
             "p5.XML":{
        -        "description":"",
        -        "params":["",
        -                  "",]
        +        "description":"XML은 XML 코드를 구문 분석할 수 있는 XML 객체의 표현입니다. loadXML()을 사용하여 외부 XML 파일을 불러와 XML 객체를 생성합니다.",
        +        "methods":["요소 부모의 복사본을 가져와, 부모를 또다른 p5.XML 객체로 반환합니다.",
        +                  "요소의 전체 이름을 가져와 문자열로 반환합니다.",
        +                  "문자열로 설정된 요소 이름을 지정합니다.",
        +                  "요소의 자식 유무 여부를 확인하고, 그 결과를 불리언으로 반환합니다.",
        +                  "모든 요소의 자식 이름을 가져와 그 값들을 문자열 배열로 반환합니다. 이는 각 자식 요소마다 getName()을 호출하는 것과 동일한 효과를 갖습니다.",
        +                  "요소의 모든 자식을 p5.XML 객체 배열로 반환합니다. 이름 매개 변수를 지정할 경우, 해당 변수명과 일치하는 모든 자식을 반환합니다.",
        +                  "이름 매개 변수 또는 지정된 인덱스의 자식과 일치하는 요소의 1번째 자식을 반환합니다. 일치하는 자식을 찾지 못하는 경우, 'undefined'를 반환합니다.",
        +                  "요소에 새로운 자식을 추가합니다. 자식은 문자열로 지정될 수 있으며, 이는 새로운 태그명 또는 기존 p5.XML 객체에 대한 레퍼런스로서 사용할 수 있습니다. 새로 추가된 자식에 대한 레퍼런스는 p5.XML 객체로 반환됩니다. ",
        +                  "이름 또는 인덱스로 지정된 요소를 제거합니다.",
        +                  "지정된 요소의 속성 개수를 숫자로 반환합니다.",
        +                  "지정된 요소의 모든 속성을 가져와 문자열 배열로 반환합니다.",
        +                  "요소가 지정된 속성을 갖는지 여부를 확인합니다.",
        +                  "요소의 속성값을 숫자로 반환합니다. 매개 변수 defaultValue가 지정되고 속성이 존재하지 않으면 defaultValue를 반환합니다. 매개 변수 defaultValue가 지정되지 않고 속성이 존재하지 않으면 값 0을 반환합니다.",
        +                  "요소의 속성값을 문자열로 반환합니다. 매개 변수 defaultValue가 지정되고 속성이 존재하지 않으면 'defaultValue'를 반환합니다. 매개 변수 defaultValue가 지정되지 않고 속성이 존재하지 않으면 null을 반환합니다.",
        +                  "요소 속성의 내용을 설정합니다. 1번째 매개 변수는 속성명을, 2번째 매개 변수는 새로운 내용을 지정합니다.",
        +                  "요소의 내용을 반환합니다. 매개 변수 defaultValue가 지정되고 내용이 존재하지 않으면 'defaultValue'를 반환합니다. 매개 변수 defaultValue가 지정되지 않고 내용이 존재하지 않으면 null을 반환합니다.",
        +                  "요소의 내용을 설정합니다.",
        +                  "요소를 문자열로 직렬화합니다. 요소의 내용을 http 요청으로 전송하거나 파일 저장을 준비할 때 사용됩니다."]
             },  
               
               
        @@ -1926,42 +1944,46 @@
               
             "createWriter": {
               "description": "",
        -      "params": ["字符串:该创造的文件的名",
        -                 "字符串:"]
        +      "params": ["문자열: 생성될 파일의 이름",
        +                 "문자열: (선택 사항)"],
        +      "returns": "p5.PrintWriter"
             },
               
             "p5.PrintWriter":{
                 "description":"",
        -        "params":["",
        -                  ""]
        +        "methods":["PrintWriter 스트림에 데이터를 작성합니다.",
        +                   "PrintWriter 스트림에 데이터를 작성하고, 마지막에 새로운 한 줄을 추가합니다.",
        +                   "PrintWriter 객체에 이미 작성된 데이터를 제거합니다.",
        +                  "PrintWriter를 종료합니다."]
             }, 
                     
             "save": {
        -      "description": "储存一个图像、文字、JSON、csv、wav 或 html 文件。将提示客户电脑下载文件。<b>注意 save() 函数不建议在正在循环执行的 draw 函数内使用,因为每一次被调用 save() 函数将会弹出一个储存对话框。</b><br><br>默认上此函数将储存画布成一个图像。您也可以选择定义一个文件名。例如:<pre>CODE BLOCK PENDING</pre>除此之外,第一个参数也能是个画布 p5.Element 的对象、字符串数组、JSON 数组、JSON 物件、p5.Table、p5.Image 或 p5.SoundFile(需要 p5.sound)。第二个参数为文件名(包括扩展名)。第三个参数适用于特别给这一类物件的设定。这函数将会储存一个符合给予的参数的文件。例如:<pre>CODE BLOCK PENDING</pre>",
        -      "params": ["物件|字符串:如果所提供的是文件名,此函数将会使用该文件名加上 png 或 jpg 文件扩展名来储存画布为一个图像。如果所提供的是物件,此函数则会一物件所定义的方式储存文件(请参考以上范例)。",
        -                 "字符串:如果所提供的第一个参数为物件,那第二个参数则定义文件名,同时必须包括适当的文件扩展名(请参考以上范例)。",
        -                 "布尔值|字符串:依文件类型而定的设定。比如说,在储存 JSON 时,true 表示输出文件将会针对文件大小进行优化,而同时牺牲可读性。"],
        +      "description": "이미지, 텍스트, json, csv, wav, 또는 html을 저장합니다. 클라이언트 컴퓨터에 다운로드 대화 상자가 뜹니다. <b>save() 함수는 매 프레임마다 새로운 저장 대화 상자를 엽니다. 따라서, 반복 실행되는 함수인 draw() 안에서 save()를 호출하지 않는 것을 권장합니다.</b><br><br>기본 동작은 캔버스를 이미지로 저장하는 것입니다. 선택적으로 파일명을 지정할 수 있습니다. 예를 들면 다음과 같습니다:<pre>CODE BLOCK PENDING</pre> 또는, 1번째 매개 변수를 캔버스 p5.Element애 대한 포인터, JSON 배열, JSON 객체, p5.Table, p5.Image, p5.SoundFile(p5.sound 필요)로 지정할 수 있습니다. 2번째 매개 변수로 파일명(확장자 포함)을 지정합니다. 3번째는 객체 유형에 따른 옵션을 설정합니다. 이 메소드는 사용자가 지정한 매개 변수에 따라 파일을 저장합니다. 예를 들면, 다음과 같습니다:<pre>CODE BLOCK PENDING</pre>",
        +      "params": ["객체|문자열: 지정된 파일명에 따라 캔버스를 png 또는 jpg 확장자 이미지로 저장합니다. 객체 지정시, 객체와 파일명에 따라 저장합니다. (위의 예제 참고) (선택 사항)",
        +                 "문자열: 객체를 1번째 매개 변수로 지정할 경우, 2번째 매개 변수는 파일명을 지시하게 되며, 이 경우 적절한 파일 확장자를 포함해야 합니다. (위의 예제 참고) (선택 사항) ",
        +                 "불리언|문자열: 파일 유형에 따른 추가 옵션. 예를 들어 JSON을 저장할 경우, 참(true)은 결과물의 가독성이 아닌, 결과물 파일 크기의 최적화를 뜻합니다. (선택 사항)"],
               "returns": ""
             },
             "saveJSON": {
        -      "description": "将一个数组或 JSON 物件的内容写进一个 .json 文件内。文件的储存方式及地点在不同浏览器之间有所不同。",
        -      "params": ["数组|物件:",
        -                 "字符串:",
        -                 "布尔值:如果为 true,将移除输出文件内的换行符及空格以优化文件大小(但牺牲可读性)"],
        +      "description": "배열 또는 JSON 객체의 내용을 .json 파일에 작성합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
        +      "params": ["배열|객체:",
        +                 "문자열:",
        +                 "불리언: 참(true)일 경우, 출력 파일상 줄바꿈과 공백을 제거하여 파일 크기를 최적화합니다. (가독성은 최적화 제외) (선택 사항)"],
               "returns": ""
             },
             "saveStrings": {
        -      "description": "将一个字符串数组写进一个文字文件内,每一行为每一组字符串。文件的储存方式及地点在不同浏览器之间有所不同。",
        -      "params": ["字符串[]:该输出的字符串数组",
        -                 "字符串:输出文件的名字",
        -                 "字符串:文件扩展名"],
        +      "description": "문자열 배열을 문자열당 1줄 단위로 텍스트 파일에 작성합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
        +      "params": ["문자열 배열[]: 작성할 문자열 배열",
        +                 "문자열: 결과값을 위한 파일명",
        +                 "문자열: filename의 확장자 (선택 사항)",
        +                 "불리언: 참(true)일 경우, 줄바꿈을 CRLF로 변환 (선택 사항)"],
               "returns": ""
             },
             "saveTable": {
        -      "description": "将一个表格(Table)物件的内容写进一个文件内。默认将储存为逗号分隔值('csv')的文字文件但也可以使用制表符分隔('tsv')或生成一个 HTML 表格('html')。文件的储存方式及地点在不同浏览器之间有所不同。",
        -      "params": ["p5.Table:该储存在文件内的表格物件",
        -                 "字符串:储存表格文件的名字",
        -                 "字符串:可以是 \"tsv\"、\"csv\" 或 \"html\""],
        +      "description": "테이블(Table) 객체의 내용을 파일에 작성합니다. 쉼표 단위로 값을 구분하는 텍스트 파일('csv')이 기본값으로 설정되지만, 탭 구분('tsv') 또는 HTML 테이블('html')도 생성가능합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
        +      "params": ["p5.Table: 파일에 저장할 Table 객체",
        +                 "문자열: Table을 저장할 파일명",
        +                 "문자열: 可以是 \"tsv\", \"csv\", \"html\" 중 하나 (선택 사항)"],
               "returns": ""
             },
               
        @@ -1970,15 +1992,46 @@
               
               
             "p5.Table": {
        -      "description": "Los objetos Table almacenan datos con múltiples filas y columnas, tal como una hoja de cálculo tradicional. Los objetos Table pueden ser generados desde cero, dinámicamente, o usando datos desde un archivo existente.",
        -      "params": ["Arreglo: un arreglo de objetos p5.TableRow"],
        -      "returns": "p5.Table: 该 p5 物件.Table generado"
        +      "description": "테이블 객체는 기존의 스프레트 시트처럼 복수의 행과 열에 데이터를 저장합니다. 동적으로 새로운 테이블을 생성하거나, 기존 파일 데이터를 사용하여 생성할 수 있습니다.",
        +      "params": "p5.TableRow 배열[]: p5.TableRow 객체의 배열 (선택 사항)",
        +      "fields": ["테이블의 행명을 담는 배열. 테이블의 헤더(header)를 함께 불러올 경우, header 매개 변수.",
        +                 "테이블의 행을 채우는 p5.TableRow 객체의 배열. getRows() 호출과 동일한 결과를 갖습니다."],
        +      "methods":["addRow()를 사용하여 p5.Table 객체에 새로운 행 데이터를 추가할 수 있습니다. 기본값으로 빈 행이 생성됩니다. 일반적으로, TableRow 객체에 있는 새로운 행에 레퍼런스를 저장하고 (위의 예제 중 newRow 참고), set()을 사용하여 각각의 개별값을 설정합니다. p5.TableRow 객체를 매개 변수로 지정할 경우, 행을 복제하여 테이블에 추가합니다.",
        +                 "테이블 객체에서 행을 제거합니다.",
        +                 "지정된 p5.TableRow에 레퍼런스를 반환합니다. 반환된 레퍼런스는 지정된 행의 값을 받아오거나 설정할 때 사용할 수 있습니다.",
        +                 "테이블의 모든 행을 받아옵니다. p5.TableRow 배열들을 반환합니다.",
        +                 "지정된 값을 포함하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 여러 개의 행들이 지정된 값을 포함하더라도, 오직 1번째 행만 반환됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                 "지정된 값을 포함하는 테이블 행들을 검색하고, 해당 행들의 레퍼런스를 반환합니다. 반환된 배열은 위의 예제처럼 모든 행을 반복 처리하는 데에 사용됩니다.ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                 "지정된 정규 표현식과 매칭하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 반환된 배열은 모든 행을 반복 처리하는 데에 사용됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                 "특정 열의 모든 값들을 가져와 배열로 반환합니다. 열은 그 ID 또는 제목(title)으로 지정가능합니다.",
        +                 "테이블로부터 모든 행을 제거합니다. 모든 행들이 제거되어도 열과 열 제목은 유지됩니다.",
        +                 "addColumn()을 사용하여 p5.Table 객체에 새로운 열 데이터를 추가할 수 있습니다. 일반적으로 열 제목을 설정하여 이후 쉽게 참조되도록 합니다. (별도의 제목을 지정하지 않는 경우, 새로운 열의 제목은 null이 됩니다.)",
        +                 "테이블의 전체 열 개수를 반환합니다.",
        +                 "테이블의 전체 행 개수를 반환합니다.",
        +                 "지정된 문자(또는 '토큰')을 제거합니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        +                 "문자열 테이블 값에서 스페이스나 탭과 같은 선행 및 후행 공백을 자릅니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        +                 "removeColumn()을 사용하여 테이블 객체로부터 특정 열을 제거합니다. 제거될 열은 그 제목(문자열) 또는 인덱스 값(정수)로 식별할 수 있습니다. removeColumn(0)은 1번째 열을, removeColumn(1)은 2번째 열을 제거합니다.",
        +                 "테이블 중 지정된 행과 열에 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "테이블 중 지정된 행과 열에 실수(float)값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "테이블 중 지정된 행과 열에 문자열 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "테이블 중 지정된 행과 열에 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "이블 중 지정된 행과 열에 실수(float)값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "테이블 중 지정된 행과 열에 문자열 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",",
        +                 "모든 테이블 데이터를 받아와 객체로 반환합니다. 열 이름이 전달될 경우, 각 행 객체는 해당 속성을 제목으로 저장합니다.",
        +                 "모든 테이블 데이터를 받아와 다차원 배열로 반환합니다."
        +                 ] 
             },
        +      
             "p5.TableRow": {
        -      "description": "Un objeto TableRow representa una única fila de datos, grabados en columnas, de una tabla. Un objeto TableRow contiene tanto un arreglo ordenado, como un objeto JSON desordenado.",
        -      "params": ["String: opcional, puebla la fila con una serie de valores, separados por el separador",
        -      "String: por defecto, valores separados por coma (csv)"],
        -      "returns": "该 p5 物件"
        +      "description": "TableRow 객체는 테이블 중 열에 저장된 데이터 값들의 단일 행을 표현합니다.<br>테이블 행은 정렬된 배열과 정렬되지 않은 JSON 객체를 모두 포함합니다.",
        +      "params": ["문자열: 구분 기호로 분리된 문자열값으로 행 채우기 (선택 사항)",
        +      "문자열: 기본값은 쉼표 단위 구분(csv) (선택 사항)"],
        +      "methods": ["TableRow의 지정된 열에 값을 저장합니다. 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "TableRow의 지정된 열에 실수(float)값을 저장합니다. 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "TableRow의 지정된 열에 문자열 값을 저장합니다. 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "TableRow의 지정된 열로부터 값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다. ",
        +                  "TableRow의 지정된 열로부터 실수(float)값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다.",
        +                 "TableRow의 지정된 열로부터 문자열 값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다."]
             },
               
         
        @@ -1986,177 +2039,216 @@
               
               
             "day": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,day() 函数将返回当天的日期天数在 1 - 31 的范围内。",
        -      "returns": "整数:当天的日期天数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. day() 함수는 현재 날짜를 1부터 31에 해당하는 값으로 반환합니다.",
        +      "returns": "정수: 현재 날짜"
             },
             "hour": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,hour() 函数将返回当时时间的小时数在 0 - 23 的范围内。",
        -      "returns": "整数:当时时间的小时数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. hour() 함수는 현재 시를 0부터 23에 해당하는 값으로 반환합니다.",
        +      "returns": "정수: 현재 시"
             },
             "minute": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,minute() 函数将返回当时时间的分钟数在 0 - 59 的范围内。",
        -      "returns": "整数:当时时间的分钟数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. minute() 함수는 현재 분을 0부터 59에 해당하는 값으로 반환합니다.",
        +      "returns": "정수: 현재 분"
             },
             "millis": {
        -      "description": "返回自程序开始以来的毫秒(一秒的一千分之一)数。这资料一般可用于定时事件及动画序列。",
        -      "returns": "整数:自程序开始以来的毫秒数"
        +      "description": "스케치의 시작(즉, setup() 함수 호출 시점)이후의 시간을 밀리 세컨드(1/1000초)로 반환합니다. 주로 타이밍 이벤트나 애니메이션 시퀀스에 사용됩니다.",
        +      "returns": "숫자: 스케치의 시작 이후의 밀리 세컨드 단위 시간"
             },
             "month": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,month() 函数将返回当天的日期月数在 1 - 12 的范围内。",
        -      "returns": "整数:当时日期的月数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. month() 함수는 현재 월을 1부터 12에 해당하는 값으로 반환합니다.",
        +      "returns": "정수: 현재 월"
             },
             "second": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,second() 函数将返回当时时间的秒数在 0 - 59 的范围内。",
        -      "returns": "整数:当时时间的秒数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. second() 함수는 현재 초를 0부터 59에 해당하는 값으로 반환합니다.",
        +      "returns": "정수: 현재 초"
             },
             "year": {
        -      "description": "p5.js 将与您的电脑的时钟沟通,year() 函数将返回当天的日期年数为一个整数(2014、2015、2016等等)。",
        -      "returns": "整数:当时日期的年数"
        +      "description": "p5.js는 컴퓨터의 시계와도 통신합니다. second() 함수는 현재 년도를 정수로 반환합니다. (2014, 2015, 2016, 등)",
        +      "returns": "정수: 현재 년도"
             },
         
         // Math > Calculation      
               
             "abs": {
        -      "description": "计算一个数字的绝对值(大小值)。映射到 Math.abs()。一个数字的绝对值一定是个正数。",
        -      "params": ["数字:用于计算的数字"],
        -      "returns": "数字:被给予数字的绝对值"
        +      "description": "숫자의 절대값(크기)을 계산합니다. Math.abs()에 매핑합니다. 숫자의 절대값은 항상 양수입니다.",
        +      "params": ["숫자: 계산할 숫자"],
        +      "returns": "숫자: 지정된 숫자의 절대값"
             },
             "ceil": {
        -      "description": "计算最靠近并大于或等于参数值的整数。映射到 Math.ceil()。比如说,ceil(9.03) 将返回 10。",
        -      "params": ["数字:该取整的数字"],
        -      "returns": "整数:取整后的数字"
        +      "description": "매개 변수의 값보다 크거나 같은 수들 중, 가장 가까운 정수(int)값을 계산합니다. 예를 들어, Math.ceil()에 매핑합니다. 예를 들어, ceil(9.03)은 값 10을 반환합니다.",
        +      "params": ["숫자: 반올림할 숫자"],
        +      "returns": "정수: 반올림된 숫자"
             },
             "constrain": {
        -      "description": "限制一个数字于最低值与最高值之间。",
        -      "params": ["数字:该限制的数字",
        -                 "数字:最低值",
        -                 "数字:最高值"],
        -      "returns": "数字:被限制后的数字"
        +      "description": "값을 최소값과 최대값 사이에 제한합니다.",
        +      "params": ["수자: 제한할 숫자",
        +                 "숫자: 최소 한계",
        +                 "숫자: 최대 한계"],
        +      "returns": "숫자: 제한된 숫자"
             },
             "dist": {
        -      "description": "计算两点之间的距离。",
        -      "params": ["数字:第一个点的 x 坐标",
        -                 "数字:第一个点的 y 坐标",
        -                 "数字:第二个点的 x 坐标",
        -                 "数字:第二个点的 y 坐标",
        -                 "数字:第一个点的 z 坐标",
        -                 "数字:第二个点的 z 坐标"],
        -      "returns": "数字:两点之间的距离"
        +      "description": "2차원 또는 3차원 상 두 점 사이의 거리를 계산합니다.",
        +      "params": ["숫자: 1번째 점의 x좌표값",
        +                 "숫자: 1번째 점의 y좌표값",
        +                 "숫자: 2번째 점의 x좌표값",
        +                 "숫자: 2번째 점의 y좌표값",
        +                 "숫자: 1번째 점의 z좌표값",
        +                 "숫자: 2번째 점의 z좌표값"],
        +      "returns": "숫자: 두 점 사이의 거리"
             },
             "exp": {
        -      "description": "返回欧拉数 e (2.71828...)提升到由参数 n 定义的指数。映射到 Math.exp()。",
        -      "params": ["数字:该提升的指数"],
        -      "returns": "数字:e^n"
        +      "description": "매개 변수 n을 지수로 삼는 거듭 제곱 형식으로 오일러의 수 e(2.71828...)를 반환합니다. Math.exp()에 매핑합니다.",
        +      "params": ["숫자: 거듭 제곱의 지수"],
        +      "returns": "숫자: e^n"
             },
             "floor": {
        -      "description": "计算最靠近并小于或等于参数值的整数。映射到 Math.floor()。",
        -      "params": ["数字:该取整的数字"],
        -      "returns": "整数:取整后的数字"
        +      "description": "매개 변수의 값보다 작거나 같은 수들 중, 가장 가까운 정수(int)값을 계산합니다. Math.floor()에 매핑합니다.",
        +      "params": ["숫자: 반내림할 숫자"],
        +      "returns": "정수: 반내림된 숫자"
             },
             "lerp": {
        -      "description": "计算一个介于两个数字之间所定义的插值量位置的数字。amt 参数为两个值之间的插值量,0.0 为第一个值,0.1 为非常接近第一个值,0.5 为两者之间等等。lerp 函数可用来沿着直线制作动画及绘制虚线。",
        -      "params": ["数字:第一个值",
        -                 "数字:第二个值",
        -                 "数字:介于 0.0 与 1.0 之间的数字"],
        -      "returns": "数字:插值"
        +      "description": "지정된 증분(increment)을 통해 두 숫자 사이의 특정 숫자를 계산합니다. 여기서 매개 변수 amt는 두 개의 값 사이를 선형적으로 보간합니다. 예를 들어, 0.0은 첫 번째 값과 동일한 색상값을, 0.1은 첫 번째 값에 매우 가까운 색상값을, 0.5는 두 값 사이의 중간 색상값을 나타내는 식입니다. 이 때, 0 미만의 값과 1이상의 값은 지정된 2개의 숫자의 비율에 따라 자동 처리됩니다. lerp() 함수는 직선 경로를 따라 모션을 생성하고 점선을 그리는 데에 사용됩니다.",
        +      "params": ["숫자: 1번째 값",
        +                 "숫자: 2번째 값",
        +                 "숫자: 숫자"],
        +      "returns": "숫자: 선형보간된 값"
             },
             "log": {
        -      "description": "计算一个数字的自然对数(e 为底数的对数)。这函数需要 n 参数大于 0.0。映射到 Math.log()。",
        -      "params": ["数字:大于 0 的数字"],
        -      "returns": "数字:n 的自然对数"
        +      "description": "숫자의 자연 로그(밑이 e인 로그)를 계산합니다. 함수는 매개 변수 n을 0.0보다 큰 값으로 예측합니다. Math.log()에 매핑합니다",
        +      "params": ["숫자: 0보다 큰 숫자"],
        +      "returns": "숫자: n의 자연 로그"
             },
             "mag": {
        -      "description": "计算一个向量的大小(或长度)。向量为一个空间内的方向,通常用于电脑图形及线性代数。因为它没有“开始”位置,一个向量的大小可以被想成是 0,0 坐标与向量 x,y 坐标之间的距离。因此,mag() 是 dist(0, 0, x, y) 的缩写。",
        -      "params": ["数字:第一个值",
        -                 "数字:第二个值"],
        -      "returns": "数字:从 (0, 0) 至 (a, b) 的向量的大小"
        +      "description": "벡터의 크기(또는 길이)를 계산합니다. 벡터는 컴퓨터 그래픽과 선형 대수에서 일반적으로 사용되며, 공간 속 방향을 뜻합니다. 벡터에는 시작점 개념이 없으므로, 그 크기는 좌표 0,0에서 x,y값까지의 거리에 비유할 수 있습니다. 이 점에서 mag()는 dist(0, 0, x, y)와 동일한 효과를 갖고 보다 간단하게 표현한 셈입니다.",
        +      "params": ["숫자: 1번째 값",
        +                 "숫자: 2번째 값"],
        +      "returns": "숫자: (0,0)에서 (a,b)까지의 벡터 크기"
             },
             "map": {
        -      "description": "从一个范围内映射一个数字去另一个范围。<br><br>在以上第一个范例,25 被从 0 至 100 之间的范围映射去窗口最左方 (0) 至最右方 (width) 的范围内。",
        -      "params": ["数字:该转换的值",
        -                 "数字:现在值的最低值",
        -                 "数字:现在值的最低值",
        -                 "数字:目标值的最低值",
        -                 "数字:目标值的最高值",
        -                 "布尔值:限制目标值在最高及最低值之间"],
        -      "returns": "数字:映射后的数字"
        +      "description": "숫자의 범위를 다른 범위로 다시 매핑합니다.<br><br>첫 번째 예제의 숫자 25는 화면상 좌측 상단 모퉁이(0)부터 우측 변(너비)에 이르는 범위에 해당하는데, 이는 0부터 100 사이에 해당하는 본래 범위에서 변환된 것입니다.",
        +      "params": ["숫자: 변환할 값",
        +                 "숫자: 값의 현재 범위의 하한",
        +                 "숫자: 값의 현재 범위의 상한",
        +                 "숫자: 값의 대상 범위의 하한",
        +                 "숫자: 값의 대상 범위의 상한",
        +                 "불리언: 값을 새로 매핑된 범위에 제한 (선택 사항)"],
        +      "returns": "숫자: 다시 매핑된 숫자"
             },
             "max": {
        -      "description": "找出一系列数字中最大的值,并返回该值。max() 能接受任何数量的数字参数,或是一个任何大小的数组。",
        -      "params": ["数字:用于比较的数字",
        -                 "数字:用于比较的数字",
        -                 "数字[]:用于比较的数字"],
        -      "returns": "数字:最高值的数字"
        +      "description": "일련의 숫자들 중, 가장 큰 값을 확인하고 이를 반환합니다. max() 함수는 매개 변수 Number로 지정된 모든 숫자 또는 모든 길의의 배열을 허용합니다.",
        +      "params": ["숫자: 비교할 숫자",
        +                 "숫자: 비교할 숫자",
        +                 "숫자 배열[]: 비교할 숫자"],
        +      "returns": "숫자: 최대 숫자"
             },
             "min": {
        -      "description": "找出一系列数字中最小的值,并返回该值。min() 能接受任何数量的数字参数,或是一个任何大小的数组。",
        -      "params": ["数字:用于比较的数字",
        -                 "数字:用于比较的数字",
        -                 "数字[]:用于比较的数字"],
        -      "returns": "数字:最低值的数字"
        +      "description": "일련의 숫자들 중, 가장 작은 값을 확인하고 이를 반환합니다. min() 함수는 매개 변수 Number로 지정된 모든 숫자 또는 모든 길의의 배열을 허용합니다.",
        +      "params": ["숫자: 비교할 숫자",
        +                 "숫자: 비교할 숫자",
        +                 "숫자 배열[]: 비교할 숫자"],
        +      "returns": "숫자: 최소 숫자"
             },
             "norm": {
        -      "description": "将一个数字由一个范围标准化成介于 0 及 1 之间的值。与 map(value, low, high, 0, 1) 的效果相同。在范围外的数字将不会被限制在 0 与 1 之间,因为范围外的值通常是有意及有用的。(参考以上第二个范例)",
        -      "params": ["数字:该标准化的值",
        -                 "数字:现在值的最低值",
        -                 "数字:现在值的最高值"],
        -      "returns": "数字:标准化后的数字"
        +      "description": "특정 범위 내의 숫자를 0과 1 범위의 값으로 정규화합니다. 이는 map(value, low, high, 0, 1)과도 동일한 효과를 갖습니다. 숫자가 0과 1 범위를 벗어나더라도, 사용자의 의도와 활용 가능성을 감안하여 0과 1 사이의 값으로 재고정하지 않습니다. (위의 예제를 참고하세요.)   ",
        +      "params": ["숫자: 정규화될 값",
        +                 "숫자: 값의 현재 범위 하한",
        +                 "숫자: 값의 현재 범위 상한"],
        +      "returns": "숫자: 정규화된 숫자"
             },
             "pow": {
        -      "description": "执行幂运算。pow() 函数是个能有效率地将数字大量乘于自己(或其倒数)的方式。比如说,pow(3, 5) 等同于 3*3*3*3*3 而 pow(3, -5) 等同于 1 / (3*3*3*3*3)。映射到 Math.pow()。",
        -      "params": ["数字:幂运算的底数",
        -                 "数字:幂运算的指数"],
        -      "returns": "数字:n^e"
        +      "description": "pow() 함수는 지수 식을 효율적으로 사용하는 한 방법으로, 특정 숫자(또는 그 역수)를 반복하여 곱할 수 있습니다. 예를 들어, pow(3,5)는 3 x 3 x 3 x 3 x 3과 같고, pow(3,-5)는 1 / 3 x 3 x 3 x 3 x 3과 같습니다. Math.pow()에 매핑합니다. ",
        +      "params": ["숫자: 지수 식의 밑",
        +                 "숫자: 거듭 제곱의 지수"],
        +      "returns": "숫자:n^e"
             },
             "round": {
        -      "description": "计算最靠近 n 参数的整数。比如说,round(133.8) 将返回 134。映射到 Math.round()。",
        -      "params": ["数字:该取整的数字"],
        -      "returns": "整数:取整后的数字"
        +      "description": "매개 변수 n에 가장 가까운 정수를 계산합니다. 예를 들어, round(133.8)은 값 134를 반환합니다. Math.round()에 매핑합니다.",
        +      "params": ["숫자: 반올림할 숫자",
        +                "숫자: 반올림할 소수점 자릿수, 기본값은 0 (선택 사항)"],
        +      "returns": "정수: 반올림된 숫자"
             },
             "sq": {
        -      "description": "平方一个数字(将数字乘于自己)。结果一定是个正数,因为将两个负数相乘一定会有一个正数结果。比如说 -1 * -1 = 1。",
        -      "params": ["数字:该平方的数字"],
        -      "returns": "数字:平方后的数字"
        +      "description": "숫자를 제곱합니다. (즉, 숫자 자신을 곱합니다.) 두 개의 음수를 곱하면 그 결과는 항상 양수로 나옵니다. 예를 들어, -1 * -1 = 1 처럼요.",
        +      "params": ["숫자: 제곱할 숫자"],
        +      "returns": "숫자: 제곱된 숫자"
             },
             "sqrt": {
        -      "description": "计算一个数字的平方根。一个数字的平方根一定是个正数,虽然也可能有正确的负数平方根。一个数字 a 的平方根 s 有以下属性 s*s = a。此函数为取平方的相反。映射到 Math.sqrt()。",
        -      "params": ["数字:该取平方根的非负数"],
        -      "returns": "数字:取平方根后的数字"
        +      "description": "숫자의 제곱근을 계산합니다. 유효한 음의 근이 있더라도 제곱근은 항상 양수가 됩니다. 숫자 a의 제곱근은 s * s = a와 같습니다. 제곱의 반대입니다. Math.sqrt()에 매핑됩니다.",
        +      "params": ["숫자: 음수가 아닌 제곱근"],
        +      "returns": "숫자: 숫자의 제곱근"
             },
             "fract()": {
        -        "description": "",
        +        "description": "숫자의 소수 부분을 계산합니다.",
        +        "params": "숫자: 소수 부분 파악이 필요한 숫자",
        +        "returns": "x의 소수 부분, 예: {x}"
             },
               
               
         // Math > Vector
         
             "createVector()": {
        -        "description": "",
        +        "description": "새로운 p5.Vector (벡터 저장을 위한 데이터 유형)를 생성합니다. 2차원 및 3차원 벡터, 그리고 유클리드(기하학) 벡터를 제공합니다. 벡터는 크기와 방향을 모두 지닌 개체입니다.",
        +        "params": ["숫자: 벡터의 x성분 (선택 사항)",
        +                   "숫자: 벡터의 y성분 (선택 사항)",
        +                   "숫자: 벡터의 z성분 (선택 사항)"],
        +        "returns": "p5.Vector"
             },
         
             "p5.Vector()": {
        -        "description": "",
        +        "description": "2차원 및 3차원 벡터, 특히 유클리드 (기하학) 벡터를 설명하는 클래스입니다. 벡터는 크기와 방향을 모두 지닌 개체입니다. 하지만, 그 데이터 유형은 벡터의 성분(2D의 경우 x와 y, 3D의 경우 x, y, z)을 저장합니다. 크기와 방향은 각각 mag() 및 heading() 메소드를 통해 접근할 수 있습니다.<br><br>p5.Vector는 위치, 속도, 가속을 다루는 수많은 p5.js 예제에서 사용됩니다. 예를 들어, 화면을 가로질러 움직이는 직사각형을 만들려면, 이 물체의 위치(원점에서 그 위치를 가리키는 벡터), 속도(단위 시간당 객체의 위치가 변하는 속도, 벡터로 표시), 그리고 가속도(단위 시간당 객체의 속도가 변하는 속도, 벡터로 표시)를 반드시 고려해야합니다.<br><br>벡터는 그룹화된 값들을 나타냅니다. 따라서, 전통적인 덧셈/곱셈 대신, p5.Vector 클래스 내부의 벡터 수학 메소드를 사용해서 계산해야 합니다.",
        +        "params":["숫자: 벡터의 x성분 (선택 사항)",
        +                   "숫자: 벡터의 y성분 (선택 사항)",
        +                   "숫자: 벡터의 z성분 (선택 사항)"],
        +        "fields":["벡터의 x성분",
        +                 "벡터의 y성분",
        +                 "벡터의 z성분"],
        +        "methods":["String(v) 또는 v.toString()을 호출하여 벡터 v의 문자열 표현을 반환합니다. 주로 콘솔창에서 벡터 로그를 확인할 때 사용됩니다.",
        +                  "두 세개의 개별 변수, p5.Vector 데이터, 또는 실수(float) 배열의 값들을 사용하여 벡터의 x, y, z성분을 설정합니다.",
        +                  "벡터의 복사본을 가져와 p5.Vector 객체를 반환합니다.",
        +                  "x, y, z성분을 벡터에 더하거나, 한 벡터를 다른 벡터에 더하거나, 또는 2개의 독립 벡터를 더합니다. 2개의 독립 벡터를 더하는 메소드는 정적 메소드에 해당하며, p5.Vector를 반환합니다. 다른 메소드들은 벡터에 직접 작용합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "한 벡터를 다른 벡터로 나눈 뒤의 나머지 벡터를 제공합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "x, y, z성분을 벡터에서 빼거나, 한 벡터에서 다른 벡터를 빼거나, 또는 2개의 독립 벡터를 뺍니다. 2개의 독립 벡터를 빼는 메소드는 정적 메소드에 해당하며, p5.Vector를 반환합니다. 다른 메소드들은 벡터에 직접 작용합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "벡터에 스칼라를 곱합니다. 정적 메소드인 경우 새로운 p5.Vector를 생성하는 반면, 정적 메소드가 아닌 경우 벡터에 직접 작용합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "벡터를 스칼라로 나눕니다. 정적 메소드인 경우 새로운 p5.Vector를 생성하는 반면, 정적 메소드가 아닌 경우 벡터에 직접 작용합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "벡터의 크기(길이)를 계산하고 그 결과를 실수(float)으로 반환합니다. (이는 수식 sqrt(x*x + y*y + z*z)과도 같습니다.)",
        +                  "벡터의 제곱 크기를 계산하고 그 결과를 실수(float)로 반환합니다. (이는 수식 sqrt(x*x + y*y + z*z)과도 같습니다.) 벡터를 비교하는 등의 경우에서 실제 길이를 포함하지 않으면 더 빠르게 계산됩니다.",
        +                  "두 벡터의 내적을 계산합니다. 2개의 독립 벡터의 내적을 계산하는 메소드는 정적 메소드에 해당합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "두 벡터의 외적으로 구성된 벡터를 계산하고 반환합니다. 정적 및 비정적 메소드 모두 새로운 p5.Vector를 반환합니다. 자세한 내용은 예제를 참고하세요.",
        +                  "두 점 사이의 유클리드 거리를 계산합니다 (점을 벡터 객체로 간주).",
        +                  "벡터를 길이 1로 정규화합니다. (단위 벡터로 만듭니다.)",
        +                  "벡터의 크기를 매개 변수 <b>max</b>의 값으로 제한합니다.",
        +                  "벡터의 크기를 매개 변수 <b>len</b>의 값으로 제한합니다.",
        +                  "벡터의 회전 각도를 계산합니다. (2D 벡터만 해당)",
        +                  "벡터를 특정 각도로 회전하되(2D 벡터만 해당), 크기는 동일하게 유지합니다.",
        +                  "두 벡터 사이의 각도(부채각, radian)를 계산하고 반환합니다.",
        +                  "한 벡터와 다른 벡터를 선형적으로 보간합니다.",
        +                  "2D 선 또는 3D 평면의 법선에 들어오는 벡터를 반영합니다. 이 메소드는 벡터에 직접 작용합니다.",
        +                  "벡터의 표현을 실수 배열로 반환합니다. 이는 일시적으로만 사용됩니다. 다른 경우에도, p5.Vector.copy() 메소드를 통해 배열에 내용을 복사해야 합니다.",
        +                  "p5.Vector에 대한 평등 검사",
        +                  "특정 각도에서 새로운 2D 벡터를 생성합니다.",
        +                  "임의의 각도에서 새로운 2D 단위 벡터를 생성합니다.",
        +                  "새로운 임의의 3D 단위 벡터를 생성합니다."],
             },
         
         
         // Math > Noise
               
             "noise": {
        -      "description": "返回所定义坐标的柏林噪声值。柏林噪声是个用来生成比 random() 所能生成更自然及更谐波的随机数字系列。在 1980 年代有 Ken Perlin 所发明,柏林噪声至今常被用在图形应用程序中生成程序纹理、自然运动、形状、地形等等。<br><br>柏林噪声与 random() 函数最主要的不同点在于前者是在一个无限的 n 维空间内定义的,这空间内每一对坐标都相对于一个固定的半随机值(只有在程序进行时为固定的;请参考 noiseSeed() 函数)。p5.js 能计算 1 维、2 维及 3 维噪声,这取决于所给予的坐标数。返回的值一定会在 0.0 至 1.0 之间。噪音值可以通过在噪音空间内移动以制成动画,如以上范例所示。第二及第三个空间维度也能被解读成时间。<br><br>所生成的噪音结构上和一般音频信号相似,尤其是此函数的频率。与物理学上谐波的概念相似,泊林噪音也是在计算几个八度后再将其结果加起来以得到最后的结果。<br><br>另外一个控制返回随机数系列的特征的方法是控制输入坐标值的大小。因为此函数能在无限之的空内内应用,输入坐标的值并不重要,只有个别坐标之间的距离需要被注意(如在循环内使用 noise() 时)。一般来说坐标之间的距离越小,生成噪声随机数列将会越平滑。介于 0.005-0.03 之间的距离应该适合大多数应用场合,不过这可能因应用需求而变。",
        -      "params": ["数字:噪声空间的 x 坐标",
        -                 "数字:噪声空间的 y 坐标",
        -                 "数字:噪声空间的 z 坐标"],
        -      "returns": "数字:柏林噪声在特定坐标的值(介于 0 与 1 之间)"
        +      "description": "지정된 좌표에서의 펄린 노이즈(Perlin noise)값을 반환합니다. 일반 random() 함수에 비해, 펄린 노이즈는 고조파 연속 숫자를 보다 자연스러운 시퀀스로 생성합니다. 켄 펄린(Ken Perlin)이 1980년대에 발명하였으며, 그래픽 응용 프로그램상 절차적 텍스처, 자연스러운 모션, 형상, 지형 등을 생성하는 데에 사용됩니다.<br><br><b>random()</b> 함수와의 주요 차이점은, 펄린 노이즈가 반-무작위 값을 갖는 고정 좌표쌍을 n차원의 무한 공간에서 정의한다는 점에 있습니다. (이는 프로그램의 수명 동안에만 고정되며, 관련해서는 noiseSeed()함수를 참고하세요.) p5.js는 사용자가 지정한 좌표 개수에 따라 1D, 2D, 3D 노이즈를 계산할 수 있습니다. 결과값은 항상 0.0과 1.0 사이입니다. 위의 예제처럼, 노이즈값은 공간 이동을 통해 애니메이션화 될 수 있습니다. 2차원 및 3차원 역시 시간으로 해석될 수 있습니다.<br><br>노이즈 함수의 주파수 사용은 실제 오디오 신호와 유사하게 구성됩니다. 물리학에서의 고조파 개념과 마찬가지로, 펄린 노이즈는 여러 옥타브에 걸쳐 계산되며, 최종 결과 생성을 위해 모든 옥타브를 합칩니다. <br><br>입력 좌표값의 크기를 통해서도 결과 시퀀스의 문자를 조정할 수 있습니다. 함수는 무한 공간 속에서 작동하기 때문에 좌표값이 크게 중요하지 않지만, 연속된 좌표들 사이의 거리만큼은 중요합니다 (예: 반복문 내에서 noise()를 실행하는 경우). 일반적으로, 좌표들 간의 거리차가 적을수록 노이즈 시퀀스가 더 매끄러워집니다. 0.0005부터 0.03 사이의 단계가 대부분의 응용 프로그램에서 사용하기에 가장 적합하나, 사용에 따라 달라질 수 있습니다.",
        +      "params": ["숫자: 노이즈 공간 속 x좌표값",
        +                 "숫자: 노이즈 공간 속 y좌표값",
        +                 "숫자: 노이즈 공간 속 z좌표값"],
        +      "returns": "숫자: 지정된 좌표에서의 펄린 노이즈 값 (0과 1 사이)"
             },
             "noiseDetail": {
        -      "description": "调整柏林噪声函数所生成的噪声特征及细节度。与物理学上谐波的概念相似,泊林噪音也是在计算几个八度后才得到最后的结果。越低的八度将会影响输出信号值越多因此同时会定义噪音的整体强度,而较高的八度将会在噪音系列中制作更精细的细节。<br><br>默认上,此噪音将使用四个八度计算而每个八度将有其前者一半的影响力,第一个八度的影响力为 50% 。这衰退值能通过加多一个参数而改变。比如说如果衰退因数为 0.75 那表示每个八度将会有其前者的 75% 的影响力(减少 25%)。任何介于 0.0 与 1.0 的值都能被接受,不过注意高于 0.5 的值可能会造成 noise() 函数会返回大于 1.0 的值。<br><br>通过改变这些参数,noise() 函数所生成的信号可适应于非常特别的需求或特点。",
        -      "params": ["数字:噪音该使用的八度数",
        -                 "数字:每个八度的衰退因数"],
        +      "description": "펄린 노이즈 함수로 생성되는 문자와 세부 레벨을 조정합니다. 물리학의 고조파처럼, 노이즈 역시 여러 옥타브에 걸쳐 계산됩니다. 낮은 옥타브는 출력 신호에 더 많이 기여함으로써 노이즈의 전체 강도를 정의하는 반면, 높은 옥타브는 노이즈 시퀀스에서 세밀한 디테일을 만듭니다.<br><br>기본값으로, 노이즈는 4 옥타브 이상으로 계산되고 각 옥타브는 이전 옥타브의 정확히 절반을 기여하도록 설정됩니다. 즉, 2번째 옥타브는 1번째 옥타브의 강도 50%에서 시작하는 식입니다. 이러한 감소량은 추가 매개 변수를 통해 변경할 수 있습니다. 예: 감소 계수 0.75는 각 옥타브가 이전 하위 옥타브의 75%만큼 영향(25% 감소)을 받는다는 것을 뜻합니다. 0.0과 1.0 사이의 모든 값이 유효하나, 0.5보다 큰 값은 noise()에 의해 반환된 1.0보다 더 큰 결과값을 가질 수 있는 점에 유의하세요.<br><br>이처럼 매개 변수를 변경하여, noise() 함수가 생성한 신호를 매우 구체적인 요구와 특성에 맞게 조정할 수 있습니다.",
        +      "params": ["숫자: 노이즈가 사용한 옥타브 개수",
        +                 "숫자: 각 옥타브에 대한 감소 계수"],
               "returns": ""
             },
             "noiseSeed": {
        -      "description": "定义 noise() 使用的随机种子值。默认上,noise() 将在每一次改程序被执行时生成不同的结果。只需定义 value 参数至一个常量就能确保每一次软件执行时都会返回一样的随机数列。",
        -      "params": ["数字:随机种子值"],
        +      "description": "noise()의 시드(seed) 값을 설정합니다. 기본적으로, noise()는 소프트웨어 프로그램이 실행될 때마다 매번 다른 결과를 생성합니다. 매 실행마다 동일한 유사-난수(random)를 반환하려면 매개 변수 value를 상수로 설정하세요.",
        +      "params": ["숫자: 시드값"],
               "returns": ""
             },
         
        @@ -2164,76 +2256,76 @@
               
         
             "randomSeed": {
        -      "description": "定义 random() 使用的随机种子值。<br><br>默认上,random() 将在每一次改程序被执行时生成不同的结果。只需定义 seed 参数至一个常量就能确保每一次软件执行时都会返回一样的伪随机数。",
        -      "params": ["数字:随机种子值"],
        +      "description": "random() 함수의 시드(seed) 값을 설정합니다.<br>기본적으로, random()은 소프트웨어 프로그램이 실행될 때마다 매번 다른 결과를 생성합니다. 매 실행마다 동일한 유사-난수(random)를 반환하려면 매개 변수 value를 상수로 설정하세요. ",
        +      "params": ["숫자: 시드값"],
               "returns": ""
             },
             "random": {
        -      "description": "返回一个随机的浮点数。<br><br>可使用 0、1 或 2 个参数。<br><br>如果并没有定义任何参数,将返回一个介于 0 与 1(但不包括 1)的随机数。<br><br>如果只定义一个参数并且该参数为数字,将返回一个介于 0 与 该数字(但不包括该数字)的随机数。<br><br>如果值定义一个参数并且该参数为数组,将返回该数组中随机一个元素。<br><br>如果定义两个参数,将返回一个介于第一个参数与第二个参数(但不包括第二个参数)的随机数。",
        -      "params": ["数字:最低值(包括此值)",
        -                 "数字:最高值(不包括此值)",
        -                 "数组:供选择的数组"],
        -      "returns": "数字:随机数"
        +      "description": "임의의 부동 소수점 숫자, 즉 실수(float)를 반환합니다.<br>0, 1, 또는 2개의 인수를 사용합니다.<br>별도의 인수를 지정하지 않을 경우, 0부터 1미만 사이의 난수(random)를 반환합니다.<br>1개의 인수를 숫자로 지정한 경우, 0부터 해당 숫자 미만 사이의 난수를 반환합니다.<br>1개의 인수를 배열로 지정한 경우, 해당 배열로부터 임의의 요소를 반환합니다.<br>2개의 인수를 지정한 경우, 1번째 인수에서 2번째 인수 미만 사이의 난수를 반환합니다.",
        +      "params": ["숫자: (해당 숫자를 포함한) 하한 (선택 사항)",
        +                 "숫자: (해당 숫자를 제외한) 상한 (선택 사항)",
        +                 "배열: 요소를 골라올 배열"],
        +      "returns": "숫자: 난수"
             },
             "randomGaussian": {
        -      "description": "返回一个符合高斯,或正态,分布的随机数。理论上 randomGaussian() 没有最高或最低返回值。不过,差均值很多的值被返回的机率将会很低;而接近均质的值被返回的机率将会相对较高。<br><br>可使用 0、1 或 2 个参数。<br>如果并没有定义任何参数,将使用均值为 0 与 标准差为 1。<br>如果只定义一个参数,该参数将为均值(标准差为 1)。<br>如果定义两个参数,第一个参数为均值,第二个参数为标准差。",
        -      "params": ["数字:均值",
        -                 "数字:标准偏差"],
        -      "returns": "数字:随机数"
        +      "description": "가우스 및 정규 분포에 맞는 난수를 반환합니다. randomGaussian()이 반환할 수 있는 최소값이나 최대값 개념은 이론상 없습니다. 평균으로부터 멀리 떨어진 값이 반환될 확률은 매우 낮고, 평균 근처의 숫자가 반환될 확률이 높습니다. <br><br> 0, 1, 또는 2개의 인수를 사용합니다.<br>별도의 인수를 지정하지 않을 경우, 평균으로 0을, 표준 편차로 1을 반환합니다.<br>1개의 인수를 지정한 경우, 해당 인수가 평균입니다. (표준 편차는 1)<br>2개의 인수를 지정한 경우, 1번째 인수는 평균, 2번째 인수는 표준 편차입니다.",
        +      "params": ["숫자: 평균",
        +                 "숫자: 표준 편차"],
        +      "returns": "숫자: 난수"
             },
               
               
         // Math > Trigonometry
               
             "acos": {
        -      "description": "cos() 的反值,将返回一个值的反余弦值。此函数接受介于 -1 与 1 之间的值并将返回介于 0 与 PI(3.1415927)之间的值。",
        -      "params": ["数字:该取反余弦值的值"],
        -      "returns": "数字:该值的反余弦值"
        +      "description": "cos()함수의 역으로, 값의 아크 코사인을 반환합니다. 이 함수는 -1부터 1까지 범위 내의 값을 예상하고, 0부터 PI(3.1415927)까지 범위 내의 값을 반환합니다.",
        +      "params": "숫자: 아크 코사인으로 반환될 값",
        +      "returns": "숫자: 지정된 값의 아크 코사인"
             },
             "asin": {
        -      "description": "sin() 的反值,将返回一个值的反正弦值。此函数接受介于 -1 与 1 之间的值并将返回介于 -PI/2 与 PI/2 之间的值。",
        -      "params": ["数字:该取反正弦值的值"],
        -      "returns": "数字:该值的反正弦值"
        +      "description": "sin()함수의 역으로, 값의 아크 사인을 반환합니다. 이 함수는 -1부터 1까지 범위 내의 값을 예상하고, -PI/2부터 PI/2까지 범위 내의 값을 반환합니다.",
        +      "params": "숫자: 아크 사인으로 반환될 값",
        +      "returns": "숫자: 지정된 값의 아크 사인"
             },
             "atan": {
        -      "description": "tan() 的反值,将返回一个值的反正切值。此函数接受介于 -Infinity 与 Infinity(包括 Infinity)之间的值并将返回介于 -PI/2 与 PI/2 之间的值。",
        -      "params": ["数字:该取反正切值的值"],
        -      "returns": "数字:该值的反正切值"
        +      "description": "tan()함수의 역으로, 값의 아크 탄젠트를 반환합니다. 이 함수는 -무한부터 무한 미만까지 범위 내의 값을 예상하고, -PI/2부터 PI/2까지 범위 내의 값을 반환합니다.",
        +      "params": "숫자: 아크 탄젠트로 반환될 값",
        +      "returns": "숫자: 지정된 값의 아크 탄젠트"
             },
             "atan2": {
        -      "description": "计算从一个被定义的点到坐标原点的弧度,并由正 x 轴开始计算。将返回介于 PI 与 -PI 之间的浮点数。atan2() 函数通常用于定向几何图形至鼠标的位置。<br><br>注意:第一个参数为 y 坐标,而第二个参数为 x 坐标,这是为了适应计算正切值的结构。",
        -      "params": ["数字:该点的 y 坐标",
        -                 "数字:该点的 x 坐标"],
        -      "returns": "数字:该点的反正切值"
        +      "description": "양의 x축상의 특정 좌표로부터 좌표 원점을 향한 각도(부채각, radian)를 계산합니다. 값은 PI부터 -PI까지 범위 내의 실수(float)로 반환됩니다. atan2() 함수는 기하도형을 커서 위치에 맞추는 데에 자주 사용됩니다.<br><br>참고: 접선 계산 방식에 따라 1번째 매개 변수를 점의 y좌표로, 2번째 매개 변수를 x좌표로 지정합니다.",
        +      "params": ["숫자: 점의 y좌표값",
        +                 "숫자: 점의 x좌표값"],
        +      "returns": "지정된 점의 아크 탄젠트"
             },
             "cos": {
        -      "description": "计算一个角度的余弦值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        -      "params": ["数字:角度"],
        -      "returns": "数字:该角度的余弦值"
        +      "description": "각도의 코사인을 계산합니다. 이 함수는 현재 설정된 angleMode를 반영합니다. 값은 -1부터 1까지의 범위 내에서 반환됩니다.",
        +      "params": "숫자: 각도",
        +      "returns": "숫자: 각도의 코사인"
             },
             "sin": {
        -      "description": "计算一个角度的正弦值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        -      "params": ["数字:角度"],
        -      "returns": "数字:该角度的正弦值"
        +      "description": "각도의 사인을 계산합니다. 이 함수는 현재 설정된 angleMode를 반영합니다. 값은 -1부터 1까지의 범위 내에서 반환됩니다.",
        +      "params": "숫자: 각도",
        +      "returns": "숫자: 각도의 사인"
             },
             "tan": {
        -      "description": "计算一个角度的正切值。此函数将使用当时的角度模式。返回值将介于 -1 与 1 之间的值。",
        -      "params": ["数字:角度"],
        -      "returns": "数字:该角度的正切值"
        +      "description": "각도의 탄젠트를 계산합니다. 이 함수는 현재 설정된 angleMode를 반영합니다. 모든 실수 범위 내에서의 값을 반환됩니다.",
        +      "params": "숫자: 각도",
        +      "returns": "숫자: 각도의 탄젠트"
             },
             "degrees": {
        -      "description": "将一个弧度值转换成其相对的角度值。弧度和角度为两个测量同样一个东西的方法。一个圆形里有 360 度而也有 2*PI 个弧度。比如说,90° = PI/2 = 1.5707964。此函数将不会使用当时的角度模式。",
        -      "params": ["数字:由弧度转换成角度的值"],
        -      "returns": "数字:转换后的角度值"
        +      "description": "부채각(radian) 측정값을 도(degree) 단위에 해당하는 값으로 변환합니다. 부채각과 도는 같은 것을 측정하는 2개의 다른 단위입니다. 원은 360도이면서 동시에 2*PI 부채각이기도 합니다. 또, 90° = PI/2 = 1.5707964 가 성립합니다. 이 함수는 현재 설정된 angleMode를 반영하지 않습니다.",
        +      "params": "숫자: 도 단위로 변환할 부채각값",
        +      "returns": "숫자: 변환된 각도"
             },
             "radians": {
        -      "description": "将一个角度值转换成其相对的弧度值。弧度和角度为两个测量同样一个东西的方法。一个圆形里有 360 度而也有 2*PI 个弧度。比如说,90° = PI/2 = 1.5707964。此函数将不会使用当时的角度模式。",
        -      "params": ["数字:由角度转换成弧度的值"],
        -      "returns": "数字:转换后的角度值"
        +      "description": "도(degree) 측정값을 부채각(radian) 단위에 해당하는 값으로 변환합니다. 부채각과 도는 같은 것을 측정하는 2개의 다른 단위입니다. 원은 360도이면서 동시에 2*PI 부채각이기도 합니다. 또, 90° = PI/2 = 1.5707964 가 성립합니다. 이 함수는 현재 설정된 angleMode를 반영하지 않습니다",
        +      "params": "숫자: 부채각 단위로 변환할 도 값",
        +      "returns": "숫자: 변환된 각도",
             },
             "angleMode": {
        -      "description": "定义当时 p5 的角度模式。默认模式为 RADIANS(弧度)。",
        -      "params": ["常量:RADIANS 或 DEGREES"],
        +      "description": "p5의 현재 모드를 설정합니다. 기본 모드는 RADIANS(부채각) 입니다.",
        +      "params": ["상수: RADIANS 또는 DEGREES 중 하나"],
               "returns": ""
             },
               
        @@ -2241,38 +2333,38 @@
         // Typography > Attributes
               
             "textAlign": {
        -      "description": "定义绘制问题的对齐方向。使用两个参数:horizAlign(LEFT、CENTER 或 RIGHT)及 vertAlign(TOP、BOTTOM、CENTER 或 BASELINE)。<br><br>horizAlign 参数为 text() 函数的 x 值,而 vertAlign 参数为 y 值。<br><br>因此如果您使用 textAlign(LEFT),您将会使文字最左方对齐 text() 函数所使用的 x 参数。如果您使用 textAlign(RIGHT, TOP),您将会使文字最右方对齐 x 值而文字最上方对齐 y 值。",
        -      "params": ["常量:水平对齐,LEFT、CENTER 或 RIGHT",
        -                 "常量:垂直对齐,TOP、BOTTOM、CENTER 或 BASELINE"],
        +      "description": "텍스트 그리기에 대한 현재 정렬을 설정합니다. horizAlign(LEFT, CENTER, 또는 RIGHT)와 vertAlign(TOP, BOTTOM, CENTER, 또는 BASELINE)이라는 2개의 인수를 받습니다.<br><br>매개 변수 horizAlign은 text() 함수의 x값을, 매개 변수 vertAlign은 y값을 참조합니다.<br><br>따라서, textAlign(LEFT)는 텍스트의 왼쪽 가장자리를 text()에서 지정된 x값에 정렬합니다. textAlign(RIGHT, TOP)은 텍스트의 오른쪽 가장자리를 x값에, 텍스트의 가장자리 위쪽을 y값에 정렬합니다.",
        +      "params": ["상수: 가로 정렬, LEFT, CENTER, 또는 RIGHT 중 하나",
        +                 "상수: 세로 정렬, TOP, BOTTOM, CENTER, 또는 BASELINE 중 하나"],
               "returns": ""
             },
             "textLeading": {
        -      "description": "定义或获取行与行之间的像素距离。此设置将会在所有接下来的 text() 函数调用时生效。",
        -      "params": ["数字:行与行之间的像素距离"],
        +      "description": "텍스트 줄 사이의 간격을 픽셀 단위로 받아오거나 설정(get/set)합니다. 이 설정은 text() 함수 이후에 호출되는 모든 함수들에 적용됩니다.",
        +      "params": ["숫자: 픽셀 단위의 행간 간격"],
               "returns": ""
             },
             "textSize": {
        -      "description": "定义或获取当时的字体大小。这大小将会在所有接下来的 text() 函数调用时生效。字形大小是使用像素定义。",
        -      "params": ["数字:字体的像素大小"],
        +      "description": "현재 폰트 크기를 받아오거나 설정(get/set)합니다. 설정된 크기는 text() 함수 이후에 호출되는 모든 함수들에 적용됩니다. 폰트 크기는 픽셀 단위로 측정됩니다.",
        +      "params": ["숫자: 픽셀 단위의 폰트 크기"],
               "returns": ""
             },
             "textStyle": {
        -      "description": "定义或获取系统字体的风格,可以是 NORMAL、ITALIC 或 BOLD。注意:这可能被 CSS 风格所覆盖。至与非系统字体(opentype、truetype 等)请直接加载已风格化的字体。",
        -      "params": ["常量:字体的风格,可以是 NORMAL、ITALIC 或 BOLD"],
        +      "description": "시스템 글꼴의 텍스트 스타일을 NORMAL, ITALIC, BOLD, 또는 BOLD ITALIC으로 받아오거나 설정(get/set)합니다. 참고: 해당 설정은 CSS 스타일에 의해 재정의될 수 있습니다. 시스템 글꼴이 아닌 글꼴(opentype, truetype 등)을 사용할 경우, 스타일이 지정된 글꼴을 대신 불러오세요.",
        +      "params": ["상수: 글꼴 설정, NORMAL, ITALIC, 또는 BOLD 중 하나"],
               "returns": ""
             },
             "textWidth": {
        -      "description": "计算及返回任何字符或字符串的宽度。",
        -      "params": ["字符串:该测量的字符串"],
        -      "returns": "数字"
        +      "description": "문자 또는 텍스트 문자열의 너비를 계산하고 반환합니다.",
        +      "params": ["문자열: 측정할 문자열"],
        +      "returns": "숫자"
             },
             "textAscent": {
        -      "description": "返回当时字体在当时所定的大小的整体高度。这高度代表从基准线算起至最高字体的顶点的距离。",
        -      "returns": "数字"
        +      "description": "폰트의 현재 크기를 증가한 값을 반환합니다. 증가값은 기준선에서 가장 높이 뻗어있는 문자까지의 거리를 픽셀 단위로 나타냅니다.",
        +      "returns": "숫자:"
             },
             "textDescent": {
        -      "description": "返回当时字体在当时所定的大小的下端线高度。",
        -      "returns": "数字"
        +      "description": "폰트의 현재 크기를 감소한 값을 반환합니다. 감소값은 기준선에서 가장 아래까지 뻗어있는 문자까지의 거리를 픽셀 단위로 나타냅니다.",
        +      "returns": "숫자:"
             },
               
               
        
        From 235cf4dc83c78845d3a6f3071dc8d55c97697f55 Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Tue, 26 May 2020 00:47:53 +0900
        Subject: [PATCH 33/36] updates as of May 26 00:47 am
        
        ---
         src/data/reference/ko.json | 444 ++++++++++++++++++++++---------------
         1 file changed, 263 insertions(+), 181 deletions(-)
        
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index d84656ae4b..c9a45053fe 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -99,9 +99,9 @@
               "returns": "알파값"
             },
             "blue": {
        -      "description": "색상 또는 픽셀 배열로부터 파랑색값 추출합니다.",
        +      "description": "색상 또는 픽셀 배열로부터 파랑값 추출합니다.",
               "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        -      "returns": "파랑색값"
        +      "returns": "파랑값"
             },
             "brightness": {
               "description": "색상 또는 픽셀 배열로부터 HSB 밝기값 추출합니다.",
        @@ -120,9 +120,9 @@
             },
         
             "green": {
        -      "description": "색상 또는 픽셀 배열로부터 초록색값 추출합니다.",
        +      "description": "색상 또는 픽셀 배열로부터 초록값 추출합니다.",
               "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        -      "returns": "초록색값"
        +      "returns": "초록값"
             },
             "hue": {
               "description": "색상 또는 픽셀 배열로부터 색조를 추출합니다. 색조는 HSB와 HSL상 모두 존재합니다. 이 함수는 HSB 색상 객체를 사용할 경우(또는 HSB 색상 모드로 지정된 픽셀 배열을 사용할 경우) HSB로 표준화된 색조 값을 반환합니다. 기본값으로는 HSL로 표준화된 색조를 반환합니다. (단, 최대 색조를 별도 지정한 경우 다른 값을 반환합니다.)",
        @@ -141,9 +141,9 @@
               "returns": "숫자: 명도"
             },
             "red": {
        -      "description": "색상 또는 픽셀 배열로부터 빨강색값 추출합니다.",
        +      "description": "색상 또는 픽셀 배열로부터 빨강값 추출합니다.",
               "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
        -      "returns": "숫자: 빨강색값"
        +      "returns": "숫자: 빨강값"
             },
             "saturation": {
               "description": "색상 또는 픽셀 배열로부터 채도값 추출합니다. 채도값은 HSB와 HSL에서 각각 다르게 측정됩니다. 이 함수는 HSL 채도를 기본값으로 제공합니다. 하지만, HSB 색상 객체가 제공 될 때 (또는 색상 모드가 HSB이면서 픽셀 배열이 제공될 때) HSB 채도값을 반환합니다.",
        @@ -161,10 +161,10 @@
                        "문자열, 지원되는 문자열 형식: 색상 문자열, 정수의 rgb()나 rgba(), 백분율의 rgb()나 rgba(), 3자리 숫자의 hex, 6자리 숫자의 hex",
                        "숫자: 현재 색상 범위에 따른 배경색 투명도 (기본값은 0-255) (선택 사항)",
                        "숫자: 흑과 백 사이의 값 지정",
        -               "숫자: 빨강색값 또는 색조값 (현재 색상 모드에 따라 상이),
        -               "숫자: 초록색값 또는 채도값 (현재 색상 모드에 따라 상이)",
        -               "숫자: 파랑색값 또는 밝기값 (현재 색상 모드에 따라 상이)",
        -               "숫자 배열[]: 빨강색값, 초록색값, 파랑색값, 알파값을 포함한 배열",
        +               "숫자: 빨강값 또는 색조값 (현재 색상 모드에 따라 상이),
        +               "숫자: 초록값 또는 채도값 (현재 색상 모드에 따라 상이)",
        +               "숫자: 파랑값 또는 밝기값 (현재 색상 모드에 따라 상이)",
        +               "숫자 배열[]: 빨강값, 초록값, 파랑값, 알파값을 포함한 배열",
                        "p5.Image: loadImage()나 createImage()로 생성된 이미지를 배경 이미지로 설정하는 경우 (스케치 화면과 반드시 동일한 사이즈일 것)"],
               "returns": "p5 객체"
             },
        @@ -176,20 +176,20 @@
               "description": "colorMode()는 p5.js가 색상 데이터를 해석하는 방식을 결정합니다. 기본값으로, fill(), stroke(), background(), color()의 매개 변수는 RGB 색상 모드에서 처리되며, 그 범위는 0부터 255까지입니다. 이 기본값은 colorMode(RGB, 255)와 동일한 효과를 지닙니다. colorMode(HSB)로 설정을 변경하면 HSB 색상 시스템을 사용할 수 있습니다. HSB 색상 시스템은 그 기본값으로 colorMode(HSB, 360, 100, 100, 1)와 같이 설정됩니다. 색상 모드는 HSL로도 설정가능합니다. <br>참고: 모든 색상 객체들은 생성 당시에 지정된 색상 모드를 반영합니다. 따라서, 이미 생성된 색상 객체 중 일부에만 적용되는 색상 모드를 지정할 수도 있습니다.",
               "params": ["상수: RGB(빨강Red/초록Green/파랑색Blue), HSB(색조Hue/채도Saturation/밝기Brightness), HSL(색조Hue/채도Saturation/명도Lightness) 중 하나",
               "숫자: 모든 값들의 범위 (선택 사항)",
        -      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        -      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록값 또는 채도값",
               "숫자: 알파값의 범위 (선택 사항)"],
               "returns": "p5 객체"
             },
             "fill": {
               "description": "도형의 면을 채울 색상을 지정합니다. 예를 들어, fill(204, 102, 0) 함수를 실행하면, 이 명령어 다음에 그려진 모든 도형들이 주황색으로 칠해집니다. 이 때, 색상값은 colorMode()로 지정된 현재의 색상 모드에 따라 RGB 또는 HSB로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) 알파값의 기본 제공 범위 역시 0부터 255까지입니다. <br>단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다.",
        -      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        -      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        -      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑색값 또는 밝기값",
        +      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록값 또는 채도값",
        +      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑값 또는 밝기값",
               "숫자: (선택 사항)",
               "문자열: 색상 문자열",
               "숫자: 회색값",
        -      "숫자 배열[]: 색상의 빨강색값, 초록색값, 파랑색값, 그리고 알파값을 포함한 배열",
        +      "숫자 배열[]: 색상의 빨강값, 초록값, 파랑값, 그리고 알파값을 포함한 배열",
                "p5.Color: 면채우기 색상" ],
               "returns": "p5 객체"
             },
        @@ -202,14 +202,14 @@
               "returns": "p5 객체"
             },
             "stroke": {
        -      "description": "그려질 선 또는 도형의 테두리 색상을 설정합니다. 이 때, 색상값은 colorMode()로 지정된 현재의 색상 모드에 따라 RGB 또는 HSB로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) <br>단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다.<br> p5.Color 객체를 통해 선의 색상을 설정할 수 있습니다.",
        -      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강색값 또는 색조값",
        -      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록색값 또는 채도값",
        -      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑색값 또는 밝기값",
        +      "description": "그려질 선 또는 도형 윤곽선 색상을 설정합니다. 이 때, 색상값은 colorMode()로 지정된 현재의 색상 모드에 따라 RGB 또는 HSB로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) <br>단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다.<br> p5.Color 객체를 통해 선의 색상을 설정할 수 있습니다.",
        +      "params": ["숫자: 현재 지정된 색상 모드의 색상 범위에 따른 빨강값 또는 색조값",
        +      "숫자: 현재 지정된 색상 모드의 색상 범위에 따른 초록값 또는 채도값",
        +      "숫자:현재 지정된 색상 모드의 색상 범위에 따른 파랑값 또는 밝기값",
               "숫자: (선택 사항)",
               "문자열: 색상 문자열",
               "숫자: 회색값",
        -      "숫자 배열[]: 색상의 빨강색값, 초록색값, 파랑색값, 그리고 알파값을 포함한 배열",
        +      "숫자 배열[]: 색상의 빨강값, 초록값, 파랑값, 그리고 알파값을 포함한 배열",
               "p5.Color: 선의 색상"],
               "returns": "p5 객체"
             },
        @@ -227,7 +227,7 @@
               "숫자: 부채각(radians)에 따른, 호의 시작점 각도값",
               "숫자: 부채각(radians)에 따른, 호의 끝점 각도값",
               "상수: 호를 그리는 방식들로, CHORD, PIEC, OPEN 중 선택 가능 (선택 사항)",
        -      "숫자: WebGL 모드를 위한 선택적 변수로, 호의 테두리를 구성하는 꼭지점 개수를 지정. 기본값은 25. (선택 사항)"],
        +      "숫자: WebGL 모드를 위한 선택적 변수로, 호의 윤곽선 구성하는 꼭지점 개수를 지정. 기본값은 25. (선택 사항)"],
               "returns": "p5 객체"
             },
             "ellipse": {
        @@ -319,7 +319,7 @@
               "returns": ""
             },
             "noSmooth": {
        -      "description": "모든 그래픽의 가장자리를 울퉁불퉁하게 처리합니다. smooth() 함수는 2D 모드상 언제나 기본값으로 활성화되며, 그래픽을 부드럽게 처리합니다. 따라서, noSmooth() 함수를 호출해야만 기하, 이미지, 폰트 등의 부드러운 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 처리가 가능합니다.",
        +      "description": "모든 그래픽의 가장자리를 울퉁불퉁하게 처리합니다. smooth() 함수는 2D 모드상 언제나 기본값으로 활성화되며, 그래픽을 부드럽게 처리합니다. 따라서, noSmooth() 함수를 호출해야만 도형, 이미지, 폰트 등의 부드러운 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 처리가 가능합니다.",
               "returns": ""
             },
             "rectMode": {
        @@ -328,7 +328,7 @@
               "returns": ""
             },
             "smooth": {
        -      "description": "모든 그래픽을 부드럽게 처리하며, 불러온 이미지 또는 크기가 재조정된 이미지의 화질을 향상합니다. smooth()는 2D 모드상 언제나 기본값으로 활성화되며. 따라서, noSmooth() 함수를 호출해야만 기하, 이미지, 폰트 등의 부드러운 그래픽 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 그래픽 처리가 가능합니다.",
        +      "description": "모든 그래픽을 부드럽게 처리하며, 불러온 이미지 또는 크기가 재조정된 이미지의 화질을 향상합니다. smooth()는 2D 모드상 언제나 기본값으로 활성화되며. 따라서, noSmooth() 함수를 호출해야만 도형, 이미지, 폰트 등의 부드러운 그래픽 처리를 비활성화할 수 있습니다. 반면, 3D 모드에서는 noSmooth()가 기본값으로 활성화됩니다. 따라서, smooth() 함수를 호출해야만 부드러운 그래픽 처리가 가능합니다.",
               "returns": ""
             },
             "strokeCap": {
        @@ -342,7 +342,7 @@
               "returns": ""
             },
             "strokeWeight": {
        -      "description": "선, 점, 그리고 도형 테두리를 그릴 때 쓰이는 함수인 stroke()의 결과값 두께를 설정합니다. 모든 두께는 픽셀 단위로 지정됩니다.",
        +      "description": "선, 점, 그리고 도형 윤곽선을 그릴 때 쓰이는 함수인 stroke()의 결과값 두께를 설정합니다. 모든 두께는 픽셀 단위로 지정됩니다.",
               "params": ["숫자:선의 두께 (픽셀 단위)"],
               "returns": ""
             },
        @@ -440,7 +440,7 @@
               
               
             "beginContour": {
        -      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 테두리를 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
        +      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 윤곽선을 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
             },
             "beginShape": {
        @@ -469,7 +469,7 @@
               "returns": ""
             },
             "endContour": {
        -      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 테두리를 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
        +      "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 윤곽선을 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
             },
             "endShape": {
        @@ -1285,54 +1285,54 @@
             },
             "arrayCopy": {
               "description": "사용 불가: copyArray()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<br>배열(또는 그 일부)을 다른 배열에 복사합니다. src 배열이 dst 배열에 복사되며, srcPosition으로 지정된 위치에서 시작하여 dstPosition으로 지정된 위치를 향합니다. 복사할 요소의 개수는 배열의 길이로 결정됩니다. 값을 복사하면 대상 배열의 기존값을 덮어씁니다. 덮어쓰기없이 값을 추가하려면 concat()을 사용하세요.<br>",
        -      "params": ["数组:原数组",
        -                 "数字:在原数组内的开端指数",
        -                 "数组:终点数组",
        -                 "数字:在终点数组内的开端指数",
        -                 "数字:该复制的元素量"],
        +      "params": ["",
        +                 "",
        +                 "",
        +                 "",
        +                 ""],
               "returns": ""
             },
             "concat": {
        -      "description": "사용 불가: concat()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>를 대신 사용하세요.<br><br>串接两个数组,映射到 Array.concat()。将不会修改原有数组。",
        -      "params": ["数组:串接的第一个数组",
        -                 "数组:串接的第二个数组"],
        -      "returns": "数组:串接后的数组"
        +      "description": "사용 불가: concat()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>를 대신 사용하세요.<br><br>",
        +      "params": ["",
        +                 ""],
        +      "returns": ""
             },
             "reverse": {
        -      "description": "사용 불가: reverse()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>를 대신 사용하세요.<br><br>倒转数组内元素的次序,映射到 Array.reverse()。",
        -      "params": ["数组:该倒转的数组"],
        +      "description": "사용 불가: reverse()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse'>array.reverse()</a>를 대신 사용하세요.",
        +      "params": [""],
               "returns": ""
             },
             "shorten": {
        -      "description": "사용 불가: shorten()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>를 대신 사용하세요.<br><br>将数组减少一个元素并返回缩短后的数组,映射到 Array.pop()。",
        -      "params": ["数组:该缩短的数组"],
        -      "returns": "数组:缩短后的数组"
        +      "description": "사용 불가: shorten()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop'>array.pop()</a>를 대신 사용하세요.<br><br>",
        +      "params": [""],
        +      "returns": ""
             },
             "shuffle": {
               "description": "사용 불가: shuffle()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>를 대신 사용하세요.<br><br><a href = 'https://bost.ocks.org/mike/shuffle/'>피셔-예이츠(Fisher-Yates) 셔플 알고리즘</a>을 구현합니다.",
        -      "params": ["数组:该混洗的数组",
        -                 "布尔值:修改所给予的数组"],
        -      "returns": "数组:混洗后的数组"
        +      "params": ["",
        +                 ""],
        +      "returns": ""
             },
             "sort": {
        -      "description": "사용 불가: sort()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>를 대신 사용하세요. <br><br>将一个含有数字的数组有最小到最大值重新排列,或将一个含有文字的数组依字母顺序排列。原数组将不会被修改,而将会返回重新排列后的数组。count 参数定义该排列的元素量。比如说,如果数组内有 12 个元素而 count 被设为 5,只有数组内前五个元素将会被排列。",
        -      "params": ["数组:该排列的数组",
        -                 "整数:该排列的元素数,由 0 开始"],
        +      "description": "사용 불가: sort()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>를 대신 사용하세요. <br><br>",
        +      "params": ["",
        +                 ""],
               "returns": ""
             },
             "splice": {
        -      "description": "사용 불가: splice()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>를 대신 사용하세요.<br><br>在一个原有的数组内添加一个值或另一数组的值。第一个参数定义该修改的数组,而第二个参数定义该添加的资料。第三个参数为该添加元素的位置的数组指数。(记得数组指数从零开始,因此第一个位置为 0,而第二的位置为 1 等等。)",
        -      "params": ["数组:拼接进的数组",
        -                 "任何:欲拼接进数组的值",
        -                 "整数:数组内该添加该元素的位置"],
        +      "description": "사용 불가: splice()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>를 대신 사용하세요.<br><br>",
        +      "params": ["",
        +                 "",
        +                 ""],
               "returns": ""
             },
             "subset": {
        -      "description": "弃用:subset()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. 请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>를 대신 사용하세요.<br><br>从一个现有的数组中提取一数组的元素。list 参数定义该复制提取元素的数组,而 start 及 count 参数定义该提取哪一些元素。如果没有提供 count 参数,那将会提取数组由开头到结尾的元素。在定义 start 参数时,记得数组第一个指数为 0。这函数将不会修改原数组。",
        -      "params": ["数组:该提取元素的数组",
        -                 "整数:开始位置",
        -                 "整数:提取元素数"],
        -      "returns": "数组:提取出来的元素数组"
        +      "description": "弃用:subset()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. 请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>를 대신 사용하세요.<br><br>",
        +      "params": ["",
        +                 "",
        +                 ""],
        +      "returns": ""
             },
               
               
        @@ -1753,9 +1753,9 @@
             },
             "tint": {
               "description": "화면에 나타날 이미지의 면채우기 값을 설정합니다. 이미지에 색조를 입히거나 알파값을 통해 투명도를 조정할 수 있습니다.<br><br>이미지 본래의 색상을 유지하면서 투명도를 적용하려면, 흰색 색조에 알파값을 지정하면 됩니다. 예를 들어 tint(255, 128)는 이미지를 50% 투명하게 만듭니다. (기본 알파 범위 0-255를 가정, 범위는 colorMode()로 조정 가능)<br><br>회색값 매개 변수는 현재 colorMode()에 따른 최대값보다 작거나 같아야합니다. 기본 최대값은 255입니다.",
        -      "params": ["숫자: 현재 색상 범위에 대한 빨강색값 또는 색조값",
        -                 "숫자: 현재 색상 범위에 대한 초록색값 또는 채도값",
        -                 "숫자: 현재 색상 범위에 대한 파랑색값 또는 밝기값"",
        +      "params": ["숫자: 현재 색상 범위에 대한 빨강값 또는 색조값",
        +                 "숫자: 현재 색상 범위에 대한 초록값 또는 채도값",
        +                 "숫자: 현재 색상 범위에 대한 파랑값 또는 밝기값"",
                          "숫자: (선택 사항)",
                          "문자열: 색상 문자열",
                          "숫자: 회색값",
        @@ -1848,7 +1848,7 @@
               
               
             "loadJSON": {
        -      "description": "파일 또는 URL로부터 JSON 파일을 불러오고, 객체를 반환합니다. JSON 파일에 배열이 포함된 경우, 인덱스 번호를 키(key)로 사용하여 객체를 반환할 수 있습니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. JSONP는 polyfill을 통해 지원되며, <a href ='https://github.com/camsong/fetch-jsonp'>여기</a>의 구문에 따라 JSON 콜백 함수가 정의한 객체를 2번째 인수로 전달할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
        +      "description": "파일 또는 URL로부터 JSON 파일을 불러오고, 객체를 반환합니다. JSON 파일에 배열이 포함된 경우, 인덱스 번호를 키(key)로 사용하여 객체를 반환할 수 있습니다.<br><br>이는 비동기적 메소드으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. JSONP는 polyfill을 통해 지원되며, <a href ='https://github.com/camsong/fetch-jsonp'>여기</a>의 구문에 따라 JSON 콜백 함수가 정의한 객체를 2번째 인수로 전달할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
                          "객체: jsonp 관련 설정을 위한 객체 (선택 사항)",
                          "문자열: \"json\" 또는 \"jsonp\"",
        @@ -1858,7 +1858,7 @@
             },
               
             "loadStrings": {
        -      "description": "파일의 내용을 읽어와 개별 행에 대한 문자열 배열을 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadStrings() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
        +      "description": "파일의 내용을 읽어와 개별 행에 대한 문자열 배열을 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다.<br><br>이는 비동기적 메소드으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadStrings() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
                          "함수: loadStrings()이 완료된 이후 실행될 함수, 배열을 1번째 인수로 전달 (선택 사항)",
                          "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        @@ -1866,7 +1866,7 @@
             },
               
             "loadTable": {
        -      "description": "파일 또는 URL의 내용을 읽어와 그 값으로 p5.Table 객체를 만듭니다. 특정 파일을 지정하려면, 해당 파일이 'data' 폴더 안에 있어야 합니다. 매개 변수 filename는 온라인 파일 URL로도 지정 가능합니다. 기본값으로, 파일 내용이 쉼표 단위로 구분된 것(CSV 형식)으로 간주합니다. 'header' 옵션이 포함된 경우, 헤더 행만 찾습니다.<br><br>가능한 옵션은 다음과 같습니다:<ul><li>csv - 테이블을 쉼표로 구분된 값으로서 구문 분석</li><li>tsv - 테이블을 탭으로 구분된 값으로서 구문 분석</li><li>header - 테이블에 헤더 행이 있음을 표기</li></ul><br><br>여러 옵션을 사용할 경우, 매개 변수들을 쉼표로 구분하여 전달할 수 있습니다. 예를 들면 다음과 같습니다:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>불러오기 및 저장된 모든 파일은 UTF-8 인코딩을 사용합니다.<br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadTable() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "description": "파일 또는 URL의 내용을 읽어와 그 값으로 p5.Table 객체를 만듭니다. 특정 파일을 지정하려면, 해당 파일이 'data' 폴더 안에 있어야 합니다. 매개 변수 filename는 온라인 파일 URL로도 지정 가능합니다. 기본값으로, 파일 내용이 쉼표 단위로 구분된 것(CSV 형식)으로 간주합니다. 'header' 옵션이 포함된 경우, 헤더 행만 찾습니다.<br><br>가능한 옵션은 다음과 같습니다:<ul><li>csv - 테이블을 쉼표로 구분된 값으로서 구문 분석</li><li>tsv - 테이블을 탭으로 구분된 값으로서 구문 분석</li><li>header - 테이블에 헤더 행이 있음을 표기</li></ul><br><br>여러 옵션을 사용할 경우, 매개 변수들을 쉼표로 구분하여 전달할 수 있습니다. 예를 들면 다음과 같습니다:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>불러오기 및 저장된 모든 파일은 UTF-8 인코딩을 사용합니다.<br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadTable() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
                          "문자열: \"header\" \"csv\" \"tsv\"",
                          "함수: loadTable()이 완료된 이후 실행될 함수, 성공시 Table 객체를 1번째 인수로 전달 (선택 사항)",
        @@ -1874,7 +1874,7 @@
               "returns": "객체: 데이터를 포함한 Table 객체"
             },
             "loadXML": {
        -      "description": "파일의 내용을 읽어와 그 값으로 XML 객체를 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다. <br><br>이는 비동기적인 방법으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadXML() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
        +      "description": "파일의 내용을 읽어와 그 값으로 XML 객체를 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다. <br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadXML() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
                          "함수: loadXML()이 완료된 이후 실행될 함수, XML 객체를 1번째 인수로 전달 (선택 사항)",
                          "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        @@ -2293,7 +2293,7 @@
               "returns": "숫자: 지정된 값의 아크 탄젠트"
             },
             "atan2": {
        -      "description": "양의 x축상의 특정 좌표로부터 좌표 원점을 향한 각도(부채각, radian)를 계산합니다. 값은 PI부터 -PI까지 범위 내의 실수(float)로 반환됩니다. atan2() 함수는 기하도형을 커서 위치에 맞추는 데에 자주 사용됩니다.<br><br>참고: 접선 계산 방식에 따라 1번째 매개 변수를 점의 y좌표로, 2번째 매개 변수를 x좌표로 지정합니다.",
        +      "description": "양의 x축상의 특정 좌표로부터 좌표 원점을 향한 각도(부채각, radian)를 계산합니다. 값은 PI부터 -PI까지 범위 내의 실수(float)로 반환됩니다. atan2() 함수는 도형을 커서 위치에 맞추는 데에 자주 사용됩니다.<br><br>참고: 접선 계산 방식에 따라 1번째 매개 변수를 점의 y좌표로, 2번째 매개 변수를 x좌표로 지정합니다.",
               "params": ["숫자: 점의 y좌표값",
                          "숫자: 점의 x좌표값"],
               "returns": "지정된 점의 아크 탄젠트"
        @@ -2349,7 +2349,7 @@
               "returns": ""
             },
             "textStyle": {
        -      "description": "시스템 글꼴의 텍스트 스타일을 NORMAL, ITALIC, BOLD, 또는 BOLD ITALIC으로 받아오거나 설정(get/set)합니다. 참고: 해당 설정은 CSS 스타일에 의해 재정의될 수 있습니다. 시스템 글꼴이 아닌 글꼴(opentype, truetype 등)을 사용할 경우, 스타일이 지정된 글꼴을 대신 불러오세요.",
        +      "description": "시스템 글꼴의 텍스트 스타일을 NORMAL, ITALIC, BOLD, 또는 BOLD ITALIC으로 받아오거나 설정(get/set)합니다. 참고: 해당 설정은 CSS 스타일에 의해 재정의될 수 있습니다. 시스템 글꼴이 아닌 글꼴(개방형, 트루 타입 등)을 사용할 경우, 스타일이 지정된 글꼴을 대신 불러오세요.",
               "params": ["상수: 글꼴 설정, NORMAL, ITALIC, 또는 BOLD 중 하나"],
               "returns": ""
             },
        @@ -2363,7 +2363,7 @@
               "returns": "숫자:"
             },
             "textDescent": {
        -      "description": "폰트의 현재 크기를 감소한 값을 반환합니다. 감소값은 기준선에서 가장 아래까지 뻗어있는 문자까지의 거리를 픽셀 단위로 나타냅니다.",
        +      "description": "폰트의 현재 크기를 감소한 값을 반환합니다. 감소값은 기준선에서 가장 밑으로 뻗어있는 문자까지의 거리를 픽셀 단위로 나타냅니다.",
               "returns": "숫자:"
             },
               
        @@ -2371,236 +2371,318 @@
         // Typography > Loading & Displaying
               
             "loadFont": {
        -      "description": "从一个文件或网址加载一个 opentype 字形文件(.otf、.ttf),将返回一个 p5.Font 物件。这函数为异步进行,这表示它可能不会在您绘图的下一行代码执行前完成。<br><br>字形的路径应该相对于链接您的绘图的 HTML 文件。从其他 URL 或远程位置加载字形可能会被浏览器的内建安全模式阻止。",
        -      "params": ["字符串:该加载的字形名字或网址",
        -                 "函数:在 loadFont() 完成后该调用的函数",
        -                 "函数:在发生错误时该调用的函数"],
        -      "returns": "p5.Font:p5.Font 物件"
        +      "description": "파일 또는 URL로부터 폰트 파일(.otf, .ttf)을 불러오고, PFont 객체를 반환합니다. <br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>폰트의 경로는 스케치상 링크된 HTML 파일을 기준으로 합니다. 브라우저의 내장 보안으로 인해 URL 또는 다른 원격 경로에서 폰트를 불러오는 것이 차단될 수 있습니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
        +      "params": ["문자열: 불러올 파일명 또는 URL",
        +                 "함수: loadFont()가 완료된 이후 실행될 함수 (선택 사항)",
        +                 "함수: 에러 발생시 실행될 함수"],
        +      "returns": "p5.Font: p5.Font 객체"
             },
               
               
             "text": {
        -      "description": "将文字绘制在荧幕上。显示第一个参数内的资料在荧幕上由其他参数所定义的位置。将会使用默认字形除非使用 textFont() 函数定义使用其他字形同时也将使用默认大小除非使用 textSize() 定义文字大小。文字的颜色可使用 fill() 函数定义。可使用 stroke() 及 strokeWeight() 函数添加文字外形线。<br><br>文字显示将位于 textAlign() 函数所定义的位置,您可将文字绘制在坐标的左边、右边或中间。<br><br>x2 及 y2 参数将定义一个方形文字显示区而且只适用于字符串资料类型。当这两个参数被定义时,它们将使用当时的 rectMode() 设置被解读。不符合方形大小的文字将不会被绘制在荧幕上。",
        -      "params": ["字符串|物件|数组|数字|布尔值:该显示的字母数字符号",
        -                 "数字:文字的 x 坐标",
        -                 "数字:文字的 y 坐标",
        -                 "数字:默认上,文字格的宽度,请参考 rectMode()",
        -                 "数字:默认上,文字格的高度,请参考 rectMode()"],
        +      "description": "화면에 텍스트를 그립니다. 1번째 매개 변수로 지정된 정보를 추가 매개 변수로 지정한 화면 위치에 나타냅니다. textFont() 함수로 별도 폰트를 지정하지 않을 경우, 기본 폰트가 사용됩니다. textSize()로 별도의 글자 크기를 지정하지 않을 경우, 기본 글자 크기가 사용됩니다. fill() 함수로 텍스트의 색상을 변경할 수 있습니다. stroke() 및 strokeWeight() 함수로 텍스트의 윤곽선을 변경할 수 있습니다.<br><br>텍스트는 textAlign() 함수의 매개 변수에 따라 좌표를 기준으로 왼쪽, 오른쪽, 그리고 중심에서 텍스트를 그릴 수 있습니다.<br><br>매개 변수 x2와 y2는 화면에 나타날 텍스트 상자의 영역을 정의하며, 문자열 데이터에만 사용됩니다. 이 매개 변수들은 현재 rectMode() 설정에 따라 해석됩니다. 사용자가 지정한 텍스트 상자 크기에 맞지 않는 텍스트는 그려지지 않습니다. 별도의 x2와 y2를 지정하지 않을 경우, 기준선 정렬이 기본값으로 제공됩니다. 즉, 텍스트가 x와 y로부터 위쪽으로 그려집니다.<br><br>WebGL: 개방형(opentype)/트루 타입(truetype) 폰트만 지원됩니다. 반드시 loadFont() 메소드를 사용하여 폰트를 불러와야 합니다. (위의 예제 참고) stroke()는 현재 WebGL 모드에서 아무런 효과를 갖지 않습니다.",
        +      "params": ["문자열|객체|배열|숫자|불리언: 표시할 영숫자 기호",
        +                 "숫자: 텍스트의 x좌표값",
        +                 "숫자: 텍스트의 y좌표값",
        +                 "숫자: 기본값은 텍스트 상자의 너비, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)",
        +                 "숫자: 기본값은 텍스트 상자의 높이, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)"],
               "returns": ""
             },
             "textFont": {
        -      "description": "定义使用 text() 函数绘制文字时该使用的字形。",
        -      "params": ["物件|字符串:一个使用 loadFont() 加载的字形,或一个代表 Web 安全字体(一个所有系统都通用的字形)的字符串",
        -                 "数字:字形大小"],
        -      "returns": ""
        +      "description": "text() 함수로 그릴 현재 폰트를 설정합니다.<br><br>WebGL: loadFont()를 통해 불러온 폰트만 지원합니다.",
        +      "params": ["객체|문자열: loadFont()로 불러온 폰트 또는 <a href = 'https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Fundamentals#Web_safe_fonts'>웹 안전 폰트</a>(일반적으로 모든 시스템에서 사용가능한 폰트)를 나타내는 문자열",
        +                 "숫자: 사용할 폰트 크기 (선택 사항)"],
        +      "returns": "현재 폰트"
             },
             "p5.Font": {
        -      "description": "Clase base para manipulación de tipografía",
        -      "params": ["物件:puntero a la instancia p5"],
        -      "returns": "该 p5 物件"
        +      "description": "폰트 조정을 위한 기본 클래스",
        +      "params": "P5: p5 인스턴스 포인터 (선택 사항)",
        +      "fields": "기본 개방형 글꼴 구현",
        +      "methods": ["이 폰트로 지정된 텍스트 문자열에 대한 바운딩 박스를 반환합니다. (현재 텍스트 한 줄씩만 지원합니다.)",
        +                 "지정된 텍스트 경로를 따르는 점들의 배열을 계산합니다."]
             },
               
               
         // Lights, Camera > Interaction
             "orbitControl":{
        +        "description": "마우스 또는 트랙 패드로 3D 스케치 주위를 움직일 수 있습니다. 마우스 왼쪽 버튼을 클릭 후 드래그하면 스케치 중심을 기준으로 카메라 위치가 회전합니다. 마우스 오른쪽 버튼을 클릭 후 드래그하면 회전없이 카메라 위치가 이동합니다. 마우스 휠(스크롤)을 사용하면 카메라 위치가 스케치와 더 가까워지거나 멀어집니다. 함수 호출시, x축과 y축상의 마우스 이동에 대한 민감도를 매개 변수를 사용할 수 있습니다. 별도로 지정한 매개 변수없이 함수를 호출하면 orbitControl(1,1)과 동일한 효과를 갖습니다. 민감도 매개 변수를 음수로 입력하면 각 축의 이동 방향을 지정할 수 있습니다.",
        +        "params":["숫자: X축상의 마우스 이동에 대한 민감도 (선택 사항)",
        +                  "숫자: Y축상의 마우스 이동에 대한 민감도 (선택 사항)",
        +                  "숫자: Z축상의 마우스 이동에 대한 민감도 (선택 사항)"]
                 
             },
        +      
             "debugMode":{
        -        
        +        "description": "debugMode()는 3D 스케치 상의 '지면'을 표현하는 그리드와 더불어, +X, +Y, +Z 방향을 나타내는 좌표축 아이콘을 추가 시각화합니다. 별도로 지정한 매개 변수없이 함수를 호출하면, 기본 그리드와 좌표축 아이콘이 생성됩니다. 또는, 위의 예제처럼 별도의 매개 변수를 지정하여 그리드/좌표축의 위치와 크기를 조정할 수 있습니다. 그리드는 가장 마지막으로 사용된 윤곽선(stroke)의 색과 두께로 그려집니다. 선에 대한 매개 변수를 지정하려면, draw() 반복문이 끝나기 직전에 stroke() 함수와 strokeWeight() 호출하면 됩니다.<br><br>기본적으로, 그리드는 XZ 평면을 따라 스케치의 원점(0,0,0)을 통과하며, 좌표축 아이콘은 원점에서 상쇄(offset)됩니다. 그리드 및 좌표축 아이콘 모두 현재 캔버스 크기에 따라 그 크기가 조정됩니다. 그리드는 기본 카메라 뷰와 평행하게 실행됩니다. 따라서, 그리드를 전체적으로 조망하려면, debugMode와 orbitControl을 함께 사용하면 됩니다.",
        +        "params":["상수: GRID 또는 AXES 중 하나",
        +                  "숫자: 그리드 한 변의 크기 (선택 사항)",
        +                  "숫자: 그리드 분할 개수 (선택 사항)",
        +                  "숫자: 원점(0,0,0)으로부터의 X축 상쇄값 (선택 사항)",
        +                  "숫자: 원점(0,0,0)으로부터의 Y축 상쇄값 (선택 사항)",
        +                  "숫자: 원점(0,0,0)으로부터의 Z축 상쇄값 (선택 사항)",
        +                  "숫자: 좌표축 아이콘 크기 (선택 사항)",
        +                  "숫자: (선택 사항)",
        +                  "숫자: (선택 사항)",
        +                  "숫자: (선택 사항)",
        +                  "숫자: (선택 사항)",
        +                  "숫자: (선택 사항)",
        +                  "숫자: (선택 사항)"]
             },
        +      
             "noDebugMode":{
        -        
        +        "description": "3D 스케치의 debugMode() 실행을 종료합니다."
             },
         // Lights, Camera > Lights
               
             "ambientLight": {
        -      "description": "使用所定义的颜色创造一个环境光。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值,需在被定义的范围内",
        -                 "数字:蓝彩值或亮度值,需在被定义的范围内",
        -                 "数字:",
        -                 "字符串:颜色字符串",
        -                 "数字:灰阶值",
        -                 "数字[]:一个有红、绿、蓝及透明度值的数组",
        -                 "p5.Color:环境光色"],
        +      "description": "색상을 갖는 앰비언트 조명을 생성합니다. 앰비언트 조명은 별도의 광원없이 캔버스의 모든 영역에서 나오는 조명을 뜻합니다.",
        +      "params": ["숫자: 현재 색상 범위에 따른 빨강값 또는 색조값",
        +                 "현재 색상 범위에 따른 초록값 또는 채도값",
        +                 "현재 색상 범위에 따른 파랑값 또는 밝기값",
        +                 "숫자: 알파값 (선택 사항)",
        +                 "문자열: 색상 문자열",
        +                 "숫자: 회색값",
        +                 "숫자 배열[]: 색상의 R, G, B & 알파값 성분을 포함한 배열",
        +                 "p5.Color: 앰비언트 조명 색상"],
               "returns": ""
             },
               
             "specularColor":{
        -        
        +        "description":"스페큘러 재질(material)과 조명에 쓰이는 스페큘러 하이라이트 색상을 설정합니다.<br><br>이 메소드를 specularMaterial() 및 shininess() 함수에 결합하여 스페큘러 하이라이트를 설정할 수 있습니다. 기본값은 흰색, 즉 (255,25,255)이며, specularMaterial() 함수 이전에 메소드가 호출되지 않을 경우 사용됩니다.<br>참고: specularColor는 프로세싱 함수 <a href='https://processing.org/reference/lightSpecular_.html'>lightSpecular</a>와 동읠한 효과를 갖습니다.",
        +        "params": ["숫자: 현재 색상 범위에 따른 빨강값 또는 색조값",
        +                  "숫자: 현재 색상 범위에 따른 초록값 또는 채도값",
        +                  "숫자: 현재 색상 범위에 따른 파랑값 또는 밝기값",
        +                  "문자열: 색상 문자열",
        +                  "숫자: 회색값",
        +                  "숫자 배열[]: 색상의 R, G, B & 알파값 성분을 포함한 배열",
        +                  "p5.Color: 앰비언트 조명 색상"
        +                  ]
             },
         
             "directionalLight": {
        -      "description": "使用所定义的颜色及方向创造一个定向光。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值",
        -                 "数字:蓝彩值或亮度值",
        -                 "p5.Vector:光的方向",
        -                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值",
        -                 "数字:x 轴方向",
        -                 "数字:y 轴方向",
        -                 "数字:z 轴方向"],
        +      "description": "색상과 방향을 갖는 디렉셔널 조명을 생성합니다.<br>한 번에 최대 5개의 directionalLight를 활성화할 수 있습니다.",
        +      "params": ["숫자: (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                 "숫자: 초록값 또는 채도값",
        +                 "숫자: 파랑값 또는 밝기값",
        +                 "p5.Vector:조명의 방향",
        +                 "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값",
        +                 "숫자: x축 방향",
        +                 "숫자: y축 방향",
        +                 "숫자: z축 방향"],
               "returns": ""
             },
             "pointLight": {
        -      "description": "使用所定义的颜色及灯光位置创造一个点光源。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值",
        -                 "数字:蓝彩值或亮度值",
        -                 "数字:x 轴方向",
        -                 "数字:y 轴方向",
        -                 "数字:z 轴方向",
        -                 "p5.Vector:光的方向",
        -                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "description": "색상과 조명 위치를 갖는 포인트 조명을 생성합니다.<br>한 번에 최대 5개의 pointlLight를 활성화할 수 있습니다.",
        +      "params": ["숫자: (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                  "숫자: 초록값 또는 채도값",
        +                  "숫자: 파랑값 또는 밝기값",
        +                  "숫자: x축 위치",
        +                  "숫자: y축 위치",
        +                  "숫자: z축 위치",
        +                  "p5.Vector: 조명의 위치",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값"],
               "returns": ""
             },
               
             "lights":{
        +        "description":"기본 앰비언트 조명과 디렉셔널 조명을 설정합니다. 기본값은  ambientLight(128, 128, 128)과 directionalLight(128, 128, 128, 0, 0, -1)입니다. 반복 프로그램에서 조명의 지속성을 확보하려면 조명을 draw() 안에 작성해야 합니다. 반복 프로그램의 setup() 안에 작성할 경우, 반복문의 최초 실행시에만 조명 효과가 발생합니다."
                 
             },
        +      
             "lightFalloff": {
        +        "description":"포인트 조명의 감소율을 설정합니다. 코드 내에서 생성된 요소에만 영향을 줍니다. 기본값은 lightFalloff (1.0, 0.0, 0.0)이며, 사용자가 지정한 매개 변수를 다음의 감소량 계산 방정식에서 사용할 수 있습니다:<br>d = 조명 위치에서 꼭지점 위치까지의 거리<br>감소량 = 1 / (CONSTANT + d * LINEAR + ( d * d ) * QUADRATIC)",
        +        "params": ["숫자: 감소량 결정을 위한 상수값",
        +                  "선형 숫자: 감소량 결정을 위한 선형값",
        +                  "2차 숫자: 감소량 결정을 위한 2차값"]
               
             },
             "spotLight": {
        +        "description":"사용자가 지정한 색상, 위치, 조명 방향, 각도, 농도로 스포트라이트를 생성합니다. 여기서의 '각도'는 스포트라이트 원뿔의 개구부에 대한 각도를 의미합니다. 농도는 빛을 중앙으로 집중시키는 값을 뜻합니다. 각도와 농도는 모두 선택 사항이나, 농도 지정을 위해 각도를 반드시 지정해야합니다.<br><br>한 번에 최대 5개의 spotLight를 활성화할 수 있습니다.",
        +        "params": ["숫자: (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                  "숫자: 초록값 또는 채도값",
        +                  "숫자: 파랑값 또는 밝기값",
        +                  "숫자: x축 위치",
        +                  "숫자: y축 위치",
        +                  "숫자: z축 위치",
        +                  "숫자: 조명의 x축 방향",
        +                  "숫자: 조명의 y축 방향",
        +                  "숫자: 조명의 z축 방향",
        +                  "숫자: 각도 매개 변수. 기본값은 PI/3 (선택 사항)",
        +                  "숫자: 농도 매개 변수. 기본값은 100 (선택 사항)",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값",
        +                  "p5.Vector: 조명의 위치",
        +                  "p5.Vector: 조명의 방향"]
               
             },
        -    "noLights": {
               
        +    "noLights": {
        +        "description": "noLights() 함수 호출 이후에 렌더링된 재질(material)들로부터 모든 조명을 제거합니다. 모든 후속 메소드에 영향을 줍니다. noLights() 이후에 작성된 조명 메소드를 호출할 경우, 스케치상 조명이 다시 활성화됩니다. "
             },
               
               
         // Lights, Camera > Material
               
             "loadShader": {
        -      "description": "从所定义的顶点及片断着色器文件路径加载自定的着色器。着色器是在背景异步加载的,因此此函数应该在 preload() 内使用。<br><br>现在为止有三种主要的着色器种类。只要相对的参数有在着色器内被定义,p5 将会自动提供相对的顶点、法线、颜色及灯光属性。",
        -      "params": ["字符串:存有顶点着色器源代码的文件的路径",
        -                 "字符串:存有片断着色器源代码的文件的路径"],
        -      "returns": "p5.Shader:由所定义的顶点及片断着色器所创造的着色器物件"
        +      "description": "버텍스 및 프래그먼트 셰이더 경로로부터 커스텀 셰이더를 불러옵니다. 셰이더 파일은 배경 화면과 비동기적으로 로드되므로, 이 메소드는 preload()에서 사용해야 합니다.<br><br>현재 3가지 유형의 셰이더를 지원합니다. p5는 셰이더상 정의된 매개 변수 이름과 일치하는 버텍스, 법선(normal), 색상, 조명 속성을 자동으로 제공합니다.",
        +      "params": ["문자열: 버텍스 셰이더 소스 코드 파일의 경로",
        +                 "문자열: 프래그먼트 셰이더의 소스 코드 파일 경로"
        +                 "함수: 문자열: 프래그먼트 셰이더의 소스 코드 파일 경로"
        +                 "함수: loadShader()가 완료된 이후 실행될 함수. 성공시, 셰이더 객체를 1번재 인수로 전달 (선택 사항)",
        +                 "함수: loadShader 내에서 에러 발생시 실행될 함수. 에러 발생시, 에러를 1번째 인수로 전달 (선택 사항)"
        +                ],
        +      "returns": "p5.Shader: 지정된 버텍스 및 프래그먼트 셰이더 파일로부터 생성된 셰이더 객체"
             },
             "createShader": {
               "description": "",
        -      "params": ["字符串:顶点着色器的源代码",
        -                 "字符串:片断着色器的源代码"],
        -      "returns": "p5.Shader:由所定义的顶点及片断着色器所创造的着色器物件"
        +      "params": ["문자열: 버텍스 셰이더의 소스 코드",
        +                 "문자열: 프래그먼트 셰이더의 소스 코드"],
        +      "returns": "p5.Shader: 지정된 버텍스 및 프래그먼트 셰이더 파일로부터 생성된 셰이더 객체"
             },
             "shader": {
        -      "description": "shader() 函数让其使用者提供自定的着色器以用于在 WEBGL 模式下渲染形状。使用这能使用 loadShader() 加载自定义的着色器。",
        -      "params": ["p5.Shader:欲用于渲染形状用的 p5.Shader"]
        +      "description": "shader() 함수를 통해 WebGL 모드상의 도형을 커스텀 셰이더로 채울 수 있습니다. loadShader()로 버텍스 및 프래그먼트 셰이더를 불러와 사용자 자체적으로 셰이더를 생성할 수 있습니다.",
        +      "params": ["p5.Shader: 도형 렌더링에 사용하기 원하는 p5.Shader (선택 사항)"]
             },
               
             "resetShader":{
        +        "description": "이 함수는 WebGL 모드 기본 셰이더를 복원합니다. resetShader() 이후에 실행되는 코드는 그 이전에 정의된 셰이더의 영향을 받지 않습니다. 반드시 shader() 함수 이후에 실행되어야 합니다. "
                 
             },
               
             "normalMaterial": {
        -      "description": "形状的法线材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        +      "description": "도형의 기본 재질(material)은 조명의 영향을 받지 않습니다. 반사성을 갖지 않으며, 종종 디버깅을 위한 자리표시자(placeholder)로 사용됩니다. X축을 향한 표면은 빨강, Y축을 향한 표면은 초록, Z축을 향한 표면은 파랑이 됩니다. 이 <a href='https://p5js.org/ko/examples/3d-materials.html'>예제</a>에서 사용가능한 모든 재질들을 확인할 수 있습니다.",
               "returns": ""
             },
             "texture": {
        -      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "description": "도형의 텍스처. <a href='https://p5js.org/ko/examples/3d-materials.html'>예제</a>에서 사용가능한 다른 재질들을 확인하세요.",
        +      "params": ["p5.Image|p5.MediaElement|p5.Graphics: 텍스처로 렌더링할 2차원 그래픽"],
               "returns": ""
             },
             "textureMode": {
        -      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "description": "텍스처 매핑을 위한 좌표 공간을 설정합니다. 기본 모드는 IMAGE로, 이미지의 실제 좌표를 나타냅니다. NORMAL은 0부터 1 사이의 정규화된 값의 공간을 나타냅니다. 이 함수는 WebGL 모드에서만 작동합니다.<br><br>예를 들어, IMAGE 모드에서 100 x 200 픽셀 이미지를 사용할 경우, 이미지를 사각면(quad)의 전체 크기에 매핑하기 위해 점 (0,0) (100, 0) (100,200) (0,200)이 필요합니다. 동일한 매핑을 NORMAL 모드에서 할 경우 (0,0) (1,0) (1,1) (0,1)입니다.",
        +      "params": ["상수: IMAGE 또는 NORMAL 중 하나"],
               "returns": ""
             },
             "textureWrap": {
        -      "description": "形状的纹理。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["p5.Image|p5.MediaElement|p5.Graphics:该渲染成纹理的二维图像"],
        +      "description": "전역 텍스처 래핑 모드를 설정합니다. UV가 0부터 1까지의 범위를 벗어날 때의 텍스처 동작을 제어합니다. CLAMP, REPEAT, MIRROR의 3가지 옵션이 있습니다.<br><br>CLAMP는 텍스처의 가장자리 픽셀 경계를 확장합니다. REPEAT는 경계에 도달할 때까지 텍스처가 반복적으로 타일링되도록 합니다. MIRROR는 REPEAT와 유사하지만, 매 타일마다 텍스처를 뒤집는다는 점에서 다릅니다.<br><br>REPEAT & MIRROR는 텍스처의 크기가 2의 배수 단위(128, 256, 512, 1024 등)인 경우에 한해서만 사용 가능합니다.<br><br>이 메소드는 그 이후에 작성된 textureWrap이 호출되기 전까지의 스케치 위 모든 텍스처에 영향을 줍니다.<br><br>1개의 인수만 지정할 경우, 해당 인수가 수직 및 수평축 모두에 적용됩니다.",
        +      "params": ["상수: CLAMP, REPEAT, 또는 MIRROR 중 하나",
        +                "상수: CLAMP, REPEAT, 또는 MIRROR 중 하나 (선택 사항)"],
               "returns": ""
             },
               
               
               
             "ambientMaterial": {
        -      "description": "使用所给予颜色定义形状的环境材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值",
        -                 "数字:蓝彩值或亮度值",
        -                 "数字:透明度",
        -                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "description": "지정된 색상의 도형에 입힐 앰비언트 재질입니다. 앰비언트 재질은 앰비언트 조명 아래에서 객체가 반사하는 색상을 정의합니다. 예를 들어, 객체의 앰비언트 재질이 순수 빨강이고 앰비언트 조명이 순수 초록인 경우, 객체는 빛을 반사하지 않습니다. <a href ='https://p5js.org/ko/examples/3d-materials.html'>사용가능한 모든 재질</a>을 확인하세요.",
        +      "params": ["숫자: 회색값, (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                  "숫자: 초록값 또는 채도값 (선택 사항)",
        +                  "숫자: 파랑값 또는 밝기값 (선택 사항)",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값"],
               "returns": ""
             },
             "emissiveMaterial": {
        -      "description": "使用所给予颜色定义形状的环境材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值",
        -                 "数字:蓝彩值或亮度值",
        -                 "数字:透明度",
        -                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "description": "재질의 방사형 색상을 설정합니다. 여기서의 '방사형'은 사실상 잘못된 표현입니다. 주변 도형에도 영향을 미치는 조명을 직접 방사한다기 보다는, 마치 객체가 빛나는 것처럼 보이기 때문입니다. 방사형 재질은 별도의 조명이 없어도 화면상 최대 강도로 빛날 수 있습니다.",
        +      "params": ["숫자: 회색값, (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                  "숫자: 초록값 또는 채도값 (선택 사항)",
        +                  "숫자: 파랑값 또는 밝기값 (선택 사항)",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값"],
               "returns": ""
             },
             "specularMaterial": {
        -      "description": "使用所给予颜色定义形状的镜面材料。您可在此<a href='https://p5js.org/zh-Hans/examples/3d-materials.html'>范例</a>查看所有可用的材料。",
        -      "params": ["数字:红彩值或色调值,需在被定义的范围内",
        -                 "数字:绿彩值或饱和度值",
        -                 "数字:蓝彩值或亮度值",
        -                 "数字:透明度",
        -                 "数字[]|字符串|p5.Color:颜色数组、CSS 颜色字符串或 p5.Color 颜色值"],
        +      "description": "지정된 색상의 도형에 입힐 스페큘러 재질입니다. 스페큘러 재질은 반짝이는 반사 재질입니다. 앰비언트 재질과 마찬가지로, 앰비언트 조명 아래에서 객체가 반사하는 색상을 정의합니다. 예를 들어, 객체의 스페큘러 재질이 순수 빨강이고 앰비언트 조명이 순수 초록인 경우, 객체는 빛을 반사하지 않습니다. 스페큘러 재질은 포인트 조명이나 디렉셔널 조명 등 모든 조명들의 광원 색상을 반영합니다. <a href ='https://p5js.org/ko/examples/3d-materials.html'>사용가능한 모든 재질</a>을 확인하세요.",
        +      "params": ["숫자: 회색값, (현재 색상 모드에 따른) 빨강값 또는 색조값",
        +                  "숫자: 초록값 또는 채도값 (선택 사항)",
        +                  "숫자: 파랑값 또는 밝기값 (선택 사항)",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값"],
               "returns": ""
             },
             "shininess": {
        -      "description": "TODO",
        -      "returns": "p5: 该 p5 物件"
        +      "description": "셰이더 표면의 광택 양을 설정합니다. specularMaterial()과 함께 사용하여 도형의 재질 속성을 설정할 수 있습니다. 기본값이자 최소값은 1입니다.",
        +      "returns": "숫자: 광택 정도. 기본값은 1."
             },
             "p5.Geometry": {
        -      "description": "TODO",
        -      "returns": "p5: 该 p5 物件"
        +      "description": "p5 기하 클래스",
        +      "params": ["정수: 수평 표면 위의 꼭지점 개수 (선택 사항)",
        +                 "정수: 수직 표면 위의 꼭지점 개수 (선택 사항)",
        +                 "함수: 객체를 인스턴스화할 때 호출할 함수"],
        +      "methods": ["",
        +                  "꼭지점 당 부드러운 법선을 각 면의 평균으로서 계산합니다.",
        +                  "꼭지점 법선의 평균을 구합니다. 곡면에 사용됩니다.",
        +                  "극점 법선의 평균을 구합니다. 구형의 기초 조형에 사용됩니다.",
        +                  "모든 꼭지점이 -100부터 100사이의 중심에 오도록 수정합니다."]
             },
             "p5.Shader": {
        -      "description": "Clase Shader para el modo WEBGL",
        -      "params": ["p5.RendererGL: una instancia de p5.RendererGL que servirá de contexto GL para este nuevo p5.Shader",
        -      "String: código fuente para el vertex shader (en forma de string)",
        -      "String: código fuente para el fragment shader (en forma de string)"],
        -      "methods": ["Wrapper de las funciones gl.uniform. Como almacenamos información de uniform en el shader, la podemos usar para revisar los datos provistos y llamar a la función apropiada."]
        +      "description": "WebGL 모드를 위한 셰이더 클래스",
        +      "params": ["p5.RendererGL: 새로운 p5.Shader에 GL 문맥을 제공하는 p5.RendererGL 인스턴스",
        +      "문자열: 버텍스 셰이더의 소스 코드 (문자열 형식)",
        +      "문자열: 프래그먼트 셰이더의 소스 코드 (문자열 형식)"],
        +      "methods": ["gl.uniform 함수를 감싸는 래퍼입니다. 정형의 정보를 셰이더에 저장하여, 데이터의 유형 검사를 수행하고 적절한 함수를 호출할 수 있습니다."]
             },
            
         //Lights, Camera > Camera
               
             "camera": {
        -      "description": "定义在一个三维绘图内相机的位置。此函数的行为与 gluLookAt 相似,不过它会覆盖原有的模型视图矩阵而不会在原有的模型视图上添加任何变形。当没有给予任何参数时,此函数将定义默认相机为 camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);",
        -      "params": ["数字:相机在 x 轴的位置",
        -                 "数字:相机在 y 轴的位置",
        -                 "数字:相机在 z 轴的位置",
        -                 "数字:代表绘图中心点的 x 坐标",
        -                 "数字:代表绘图中心点的 y 坐标",
        -                 "数字:代表绘图中心点的 z 坐标",
        -                 "数字:相机向上方向量的 x 分量",
        -                 "数字:相机向上方向量的 y 分量",
        -                 "数字:相机向上方向量的 z 分量"],
        +      "description": "3D 스케치의 카메라 위치를 설정합니다. 이 함수의 매개 변수들은 카메라의 위치, 스케치의 중심(카메라가 가리키는 위치), 그리고 위쪽 방향(카메라의 오리엔테이션)을 정의합니다. <br><br>이 함수는 카메라 이동을 시뮬레이션하여, 객체를 다양한 각도에서 볼 수 있도록 합니다. 객체 자체가 아닌 카메라를 움직이는 점에 유의하세요. 예를 들어, centerX 값이 양수인 경우, 카메라는 스케치의 우측으로 회전하여 마치 객체가 왼쪽으로 움직이듯 보이게 합니다.<br><br>이 <a href = 'https://www.openprocessing.org/sketch/740258'>예제</a>에서 카메라의 위치 이동 방식을 확인하세요.<br><br>별도의 인수를 지정하지 않는 경우, 함수는 camera (0, 0, (height / 2.0) / tan (PI * 30.0 / 180.0), 0, 0, 0, 0, 1, 0)에 해당하는 기본 카메라를 생성합니다.",
        +      "params": ["숫자: x축에서의 카메라 위치값 (선택 사항)",
        +                 "숫자: y축에서의 카메라 위치값 (선택 사항)",
        +                 "숫자: z축에서의 카메라 위치값 (선택 사항)",
        +                 "숫자: 스케치 중심의 x좌표값 (선택 사항)",
        +                 "숫자: 스케치 중심의 y좌표값 (선택 사항)",
        +                 "숫자: 스케치 중심의 z좌표값 (선택 사항)",
        +                 "숫자: 카메라로부터 위쪽 방향의 x성분 (선택 사항)",
        +                 "숫자: 카메라로부터 위쪽 방향의 y성분 (선택 사항)",
        +                 "숫자: 카메라로부터 위쪽 방향의 z성분 (선택 사항)"],
               "returns": ""
             },
             "perspective": {
        -      "description": "定义透视相机。当没有给予任何参数时,此函数将定义默认相机为 perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*10.0) 其中 cameraZ 为 ((height/2.0) / tan(PI60.0/360.0));",
        -      "params": ["数字:相机视锥的垂直视野,使用角度模式单位定义视野底部到顶部的角度",
        -                 "数字:相机视锥的长宽比",
        -                 "数字:视锥近平面的长度",
        -                 "数字:视锥远平面的长度"],
        +      "description": "3D 스케치의 카메라 투시 투영법을 설정합니다. 이 투영법은 거리 단축 착시효과를 통해 깊이감을 나타냅니다. 카메라로부터 가까운 객체는 실제 크기로 보이고, 멀리 떨어진 객체는 더 작아 보입니다. 이 함수의 매개 변수는 수직 시야, 종횡비(일반적으로, 너비/높이), 그리고 근거리 및 원거리에서 잘리는 평면을 통해 보이는 (즉, 카메라가 보는), 절두체 구도(카메라가 객체를 보는, 잘린 피라미드형 구도)를 정의합니다.<br><br>별도의 인수를 지정하지 않는 경우, 기본값은 perspective(PI/3.0, width/height, eyeZ/10.0, eyeZ10.0)과도 동일한 효과를 가지며, 여기서 eyeZ는((height/2.0) / tan(PI60.0/360.0))과 같습니다.",
        +      "params": ["숫자: 하단에서 상단에 이르는 카메라의 절두체형 수직 시야각, angleMode 단위에 해당 (선택 사항)",
        +                 "숫자: 카메라의 절두체형 종횡비 (선택 사항)",
        +                 "숫자: 절두 근거리 길이 (선택 사항)",
        +                 "숫자: 절두 원거리 길이 (선택 사항)"],
               "returns": ""
             },
             "ortho": {
        -      "description": "定义正射相机。",
        -      "params": ["数字:相机视锥的左平面",
        -                 "数字:相机视锥的右平面",
        -                 "数字:相机视锥的底平面",
        -                 "数字:相机视锥的顶平面",
        -                 "数字:相机视锥的近平面",
        -                 "数字:相机视锥的远平面"],
        +      "description": "3D 스케치의 카메라 직교 투영법을 설정하고, 객체에 대한 상자 모양의 절두체 구도를 정의합니다. 이 투영법은 동일한 차원상의 객체들을 카메라로부터 떨어져있는 거리와 상관없이 모두 동일한 크기로 나타냅니다. 이 함수의 매개 변수는 좌우가 최소 및 최대 x값이고, 상하가 최소 및 최대 y값이며, 원근이 최소 및 최대 z값인 절두체 구도를 지정합니다. 별도의 매개 변수를 지정하지 않는 경우, 기본값은 ortho(-width/2, width/2, -height/2, height/2)입니다.",
        +      "params": ["숫자: 카메라 절두체의 왼쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 먼 평면 (선택 사항)"],
               "returns": ""
             },
               
             "frustrum":{
        -        
        +        "description":"매개 변수에 따른 원근 매트릭스를 설정합니다.<br>절두체는 상단이 잘린 피라미드와 유사한 형태를 갖는 도형입니다. 피라미드의 상단에 가상의 눈이 달려있다고 가정한다면, 나머지 6개의 평면은 3D 뷰를 렌더링할 때 시야를 잘라내는 평면으로서 기능합니다. 따라서, 이 잘라내기 평면들의 안쪽에 위치한 것들만 보이고, 그 바깥에 위치한 것들은 보이지 않습니다.<br>frustrum()을 통해 렌더링 화면의 원근을 변경할 수 있으나, perspective()를 사용하면 동일한 설정을 보다 간편하게 표현할 수 있습니다.",
        +        "params":["숫자: 카메라 절두체의 왼쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        +                 "숫자: 카메라 절두체의 먼 평면 (선택 사항)"]
             },
             "createCamera":{
        +        "description":"새로운 p5.Camera 객체를 생성하고 렌더러에게 해당 카메라를 사용하도록 지시합니다. p5.Camera 객체를 반환합니다.",
        +        "returns":"p5.Camera: 새로 생성된 카메라 객체"
                 
             },
             "p5.Camera":{
        +        "description":"p5의 <a href = 'https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5'>WebGL 모드</a>용 카메라를 위한 클래스입니다. 3D씬 렌더링에 필요한 카메라 위치, 방향, 투영 정보 등을 포함합니다.<br><br>createCamera()로 새로운 p5.Camera 객체를 생성하고, 아래의 메소드들을 통해 이를 제어할 수 있습니다. 이러한 방식으로 생성된 카메라는, 여타 메소드들을 통해 변경하지 않는 한, 화면에 기본값으로 설정된 위치 및 투시 투영법을 사용합니다. 여러 대의 카메라 생성 또한 가능한데, 이 경우 setCamera() 메소드로 현재 카메라를 설정할 수 있습니다.<br><br>참고: 아래의 메소드들은 다음 2개의 좌표계에서 작동합니다: 월드 좌표계는 X,Y,Z축 상의 원점에 대한 위치를 나타내는 반면, 로컬 좌표계는 카메라 시점에서의 위치(좌-우, 위-아래, 앞-뒤)를 나타냅니다. move() 메소드는 카메라의 자체 축을 따라 움직이는 반면, setPosition()은 월드 스페이스에서의 카메라의 위치를 설정합니다.",
        +        "methods":["p5.Camera 객체의 투시 투영법을 설정하고, perspective() 구문에 따라 해당 투영법의 매개 변수를 설정합니다.",
        +                   "p5.Camera 객체의 직교 투영법을 설정하고, ortho() 구문에 따라 해당 투영법의 매개 변수를 설정합니다.",
        +                   "",
        +                   "패닝은 카메라 화면을 좌우로 회전합니다.",
        +                   "틸트는 카메라 화면을 상하로 회전합니다.",
        +                   "월드 스페이스 위치에서 보도록 카메라 방향을 조정합니다.",
        +                   "카메라의 위치와 방향을 설정합니다. p5.Camera 객체에 camera()를 호출하는 것과 동일한 효과를 갖습니다.",
        +                   "현재 카메라 방향을 유지하면서 그 로컬축을 따라 이동합니다.",
        +                   "현재 카메라 방향을 유지하면서 카메라의 위치를 월드 스페이스에서의 위치로 설정합니다."]
                 
             },
        +      
             "setCamera":{
        +        "description":"rendererGL의 현재 카메라를 p5.Camera 객체로 설정합니다. 여러 카메라 간의 화면 전환이 가능합니다.",
        +        "params":"p5.Camera: p5.Camera 객체"
                 
             }
               
        
        From 442b046e2057f704e674482afdeebf3f29fc99a9 Mon Sep 17 00:00:00 2001
        From: Lauren McCarthy <laurenleemccarthy@gmail.com>
        Date: Fri, 26 Jun 2020 17:20:23 -0700
        Subject: [PATCH 34/36] i18n
        
        ---
         src/data/es.yml      | 4 ++--
         src/data/ko.yml      | 3 +--
         src/data/zh-Hans.yml | 3 +--
         3 files changed, 4 insertions(+), 6 deletions(-)
        
        diff --git a/src/data/es.yml b/src/data/es.yml
        index 5ec60af6b4..8b99acee65 100644
        --- a/src/data/es.yml
        +++ b/src/data/es.yml
        @@ -162,7 +162,7 @@ get started:
         
         download:
           Download: "Descargar"
        -  download-intro: '¡Bienvenidos! Aunque esta página se titula "Descargar", en realidad contiene una colección de enlaces para descargar la biblioteca o comenzar a trabajar en línea. Hemos tratado de ordenar cosas desde lo que un principiante podría desear explorar primero, a los recursos que los programadores más experimentados pueden estar buscando.'
        +  download-intro: "¡Bienvenidos! Aunque esta página se titula \"Descargar\", en realidad contiene una colección de enlaces para descargar la biblioteca o comenzar a trabajar en línea. Hemos tratado de ordenar cosas desde lo que un principiante podría desear explorar primero, a los recursos que los programadores más experimentados pueden estar buscando."
           editor-title: "Editor"
           p5.js-editor-intro: "Este enlace te redirige al Editor p5.js en línea para que puedas comenzar a usar p5.js de inmediato."
           p5.js-editor: "Editor de p5.js"
        @@ -869,4 +869,4 @@ showcase:
           project-a-3-4-moon: ". Pude usar y enseñar esta herramienta para visualizar varias ideas sobre el tiempo en movimiento."
           project-a-4-1-moon: "Para mí, un principiante, fue un desafío comprender la estructura general de p5.js y cómo funciona el código en general. Tuve que repetir los conceptos básicos de p5.js un par de veces, y luego dibujé un cuadro para memorizar y enseñar la forma en que entendí la estructura y el código de p5.js con fuertes restricciones que configuré. Fue una excelente experiencia de enseñanza y aprendizaje."
           project-a-5-1-moon: "Echa un vistazo a "
        -  project-a-5-2-moon: " en Milán, Italia."
        +  project-a-5-2-moon: " en Milán, Italia."
        \ No newline at end of file
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index cd8120f276..4ac023223a 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -32,8 +32,7 @@ tagline7: "The p5.js community stands in solidarity with Black Lives Matter."
         
         home:
           blmnamelistending: "and too many more to list here..."
        -  blmstatement1: "This site is currently offline, as a small mark of respect, and expression of solidarity.
        -  The "
        +  blmstatement1: "This site is currently offline, as a small mark of respect, and expression of solidarity."
           blmstatement2: "remains available."
           blmstatement3: "Please consider donating to "
           blacklivesmatter: "Black Lives Matter"
        diff --git a/src/data/zh-Hans.yml b/src/data/zh-Hans.yml
        index 27b685734a..a2f4e92adb 100644
        --- a/src/data/zh-Hans.yml
        +++ b/src/data/zh-Hans.yml
        @@ -32,8 +32,7 @@ tagline7: "The P5.js community stands in solidarity with Black Lives Matter."
         
         home:
           blmnamelistending: "and too many more to list here..."
        -  blmstatement1: "This site is currently offline, as a small mark of respect, and expression of solidarity.
        -  The "
        +  blmstatement1: "This site is currently offline, as a small mark of respect, and expression of solidarity."
           blmstatement2: "remains available."
           blmstatement3: "Please consider donating to "
           blacklivesmatter: "Black Lives Matter"
        
        From fbe064d2a62061f59cb829425882de131ba5e9ce Mon Sep 17 00:00:00 2001
        From: Lauren McCarthy <laurenleemccarthy@gmail.com>
        Date: Fri, 26 Jun 2020 17:52:07 -0700
        Subject: [PATCH 35/36] merge ko translation
        
        ---
         i18n-tracking.yml          |    3 +
         src/data/en.yml            |    2 +-
         src/data/es.yml            |    1 +
         src/data/ko.yml            |    2 +-
         src/data/reference/ko.json | 1393 ++++++++++++++++--------------------
         5 files changed, 622 insertions(+), 779 deletions(-)
        
        diff --git a/i18n-tracking.yml b/i18n-tracking.yml
        index 47371ff5ae..1950e4a190 100644
        --- a/i18n-tracking.yml
        +++ b/i18n-tracking.yml
        @@ -237,6 +237,7 @@ es:
             line 256: '  '
             line 259: '  notes1'
             line 274: '  nominate-project'
        +    line 875: '  project-a-5-2-moon'
         ko:
           src/data/en.yml:
             line 31: tagline7
        @@ -476,6 +477,7 @@ ko:
             line 256: '  '
             line 259: '  notes1'
             line 274: '  nominate-project'
        +    line 875: '  project-a-5-2-moon'
         zh-Hans:
           src/data/en.yml:
             line 31: tagline7
        @@ -715,3 +717,4 @@ zh-Hans:
             line 256: '  '
             line 259: '  notes1'
             line 274: '  nominate-project'
        +    line 875: '  project-a-5-2-moon'
        diff --git a/src/data/en.yml b/src/data/en.yml
        index 48a3f6f5f3..18729ca94e 100644
        --- a/src/data/en.yml
        +++ b/src/data/en.yml
        @@ -871,4 +871,4 @@ showcase:
           project-a-3-4-moon: ". I was able to use and to teach this tool to visualize various ideas about time in motion."
           project-a-4-1-moon: "It was challenging for me, a beginner, to understand the overall structure of p5.js and how code works in general. I had to repeat the p5.js basics a couple of times, and then I drew a chart to memorize and to teach the way I understood the p5.js structure and code with strong constraints I set up. It was an excellent teaching and learning experience."
           project-a-5-1-moon: "Check out the "
        -  project-a-5-2-moon: " in Milan, Italy."
        +  project-a-5-2-moon: " in Milan, Italy."
        \ No newline at end of file
        diff --git a/src/data/es.yml b/src/data/es.yml
        index 8b99acee65..f67b7ce906 100644
        --- a/src/data/es.yml
        +++ b/src/data/es.yml
        @@ -27,6 +27,7 @@ tagline2: "la simplicidad de Processing x la flexibilidad de JavaScript"
         tagline3: "la intuición de Processing x el poder de JavaScript"
         tagline4: "la creatividad de Processing x el dinamismo de JavaScript"
         tagline5: "la comunidad de Processing x la comunidad de JavaScript"
        +tagline6: "la comunidad de Processing x la comunidad de JavaScript"
         tagline7: "La comunidad de p5.jS se solidariza con Black Lives Matter."
         
         home:
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 27c36ae50f..85892299a2 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -871,4 +871,4 @@ showcase:
           project-a-3-4-moon: ". I was able to use and to teach this tool to visualize various ideas about time in motion."
           project-a-4-1-moon: "It was challenging for me, a beginner, to understand the overall structure of p5.js and how code works in general. I had to repeat the p5.js basics a couple of times, and then I drew a chart to memorize and to teach the way I understood the p5.js structure and code with strong constraints I set up. It was an excellent teaching and learning experience."
           project-a-5-1-moon: "Check out the "
        -  project-a-5-2-moon: " in Milan, Italy."
        +  project-a-5-2-moon: " in Milan, Italy."
        \ No newline at end of file
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index c9a45053fe..9699164680 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -89,11 +89,7 @@
           "Lights": "라이트",  
           "Material": "재질(Material)", 
           "p5": {
        -      
        -      
        -//Color > Creating & Reading
        -      
        -   "alpha": {
        +    "alpha": {
               "description": "픽셀 배열로부터 알파값을 추출합니다.",
               "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
               "returns": "알파값"
        @@ -118,7 +114,6 @@
               "숫자[]: RGB 및 알파값을 포함한 숫자열"],
               "returns": "색상 결과"
             },
        -
             "green": {
               "description": "색상 또는 픽셀 배열로부터 초록값 추출합니다.",
               "params": ["p5.Color 객체, 색상 요소, CSS 색상"],
        @@ -149,19 +144,14 @@
               "description": "색상 또는 픽셀 배열로부터 채도값 추출합니다. 채도값은 HSB와 HSL에서 각각 다르게 측정됩니다. 이 함수는 HSL 채도를 기본값으로 제공합니다. 하지만, HSB 색상 객체가 제공 될 때 (또는 색상 모드가 HSB이면서 픽셀 배열이 제공될 때) HSB 채도값을 반환합니다.",
               "params": ["p5.Color|숫자 배열[]|문자열: p5.Color 객체, 색상 요소 또는 CSS 색상"],
               "returns": "숫자: 채도값"
        -    },
        -          
        -      
        -//Color > Setting
        -      
        -      
        +    },   
             "background": {
               "description": "background() 함수는 p5.js 캔버스의 배경색을 설정합니다. 배경색의 기본값은 투명입니다. 이 함수는 주로 draw() 함수 안에 위치하며, 매 프레임마다 윈도우 화면을 초기화하기 위해 사용됩니다. 하지만, 애니메이션의 첫 프레임 배경을 지정하거나 배경색을 최초 한번만 지정할 경우, setup() 함수 안에 쓰이기도 합니다. <br> 색상은 현재 색상 모드(colorMode)에 따라 RGB, HSB, 또는 HSL값으로 지정됩니다. (기본값으로 제공되는 색상 모드는 RGB이고, 그 색상 범위는 0부터 255까지 해당합니다.) 알파값의 기본 제공 범위 역시 0부터 255까지입니다.<br> 단일한 문자열 인수에 대해 RGB, RGBA, Hex CSS 색상 문자열과 더불어 명명된 모든 색상 문자열이 지원됩니다. 단, 투명도인 알파값을 설정하기 위해서는 반드시 RGBA를 사용해야합니다. <br> p5.Color 객체를 통해 배경색을 설정할 수 있습니다. <br> p5.Image를 통해 배경 이미지를 설정할 수 있습니다.",
               "params": ["p5.Color: color() 함수로 생성된 모든 값",
                        "문자열, 지원되는 문자열 형식: 색상 문자열, 정수의 rgb()나 rgba(), 백분율의 rgb()나 rgba(), 3자리 숫자의 hex, 6자리 숫자의 hex",
                        "숫자: 현재 색상 범위에 따른 배경색 투명도 (기본값은 0-255) (선택 사항)",
                        "숫자: 흑과 백 사이의 값 지정",
        -               "숫자: 빨강값 또는 색조값 (현재 색상 모드에 따라 상이),
        +               "숫자: 빨강값 또는 색조값 (현재 색상 모드에 따라 상이)",
                        "숫자: 초록값 또는 채도값 (현재 색상 모드에 따라 상이)",
                        "숫자: 파랑값 또는 밝기값 (현재 색상 모드에 따라 상이)",
                        "숫자 배열[]: 빨강값, 초록값, 파랑값, 알파값을 포함한 배열",
        @@ -214,10 +204,6 @@
               "returns": "p5 객체"
             },
               
        -      
        -// Shape > 2D Primitives
        -      
        -      
             "arc": {
               "description": "화면에 호, 즉 아치형 선을 그립니다. x좌표, y좌표, w(너비), h(높이), 시작점, 끝점을 지정하면 호는 열린 파이 조각의 형태로 그려집니다. 모드 변수를 설정하기에 따라, 호는 각각 반원(OPEN), 닫힌 반원(CHORD), 닫힌 파이 조각(PIE) 형태로 그려집니다. ellipseMode() 함수를 이용하면 시작점을 변경할 수 있습니다. 만약 원 하나를 그리기 위해 arc()의 시작점을 0으로, 끝점을 TWO_PI으로 설정할 경우, 시작점과 끝점이 동일하여 아무것도 그려지지 않습니다. 원을 그릴 때는 ellipse() 함수를, 원의 일부를 그릴 때는 arc() 함수를 이용하세요.",
               "params": ["숫자: 호를 포함하는 원의 x좌표",
        @@ -239,7 +225,6 @@
               "정수: 타원을 몇 개의 부분으로 나누어 그릴 것인지 지정 (WebGL 모드용)"],
               "returns": "p5 객체"
             },
        -
             "line": {
               "description": "화면에 선분, 즉 두 점을 연결하는 곧은 선을 그립니다. line() 함수에 4개의 변수를 입력하여 이차원 평면에 선을 그릴 수 있습니다. stroke() 함수를 사용해 선의 색상을 지정할 수 있습니다. 선은 면을 갖지 않으므로, 면채우기 함수인 fill()은 적용되지 않습니다. 기본값으로 제공되는 선의 두께는 1픽셀이며, 이를 변경하기 위해 strokeWeight() 함수를 사용할 수 있습니다.",
               "params": ["숫자: 1번째 점의 x좌표값",
        @@ -287,8 +272,8 @@
               "정수: y축 방향의 선분 수 (WebGL 모드용)"],
               "returns": "p5 객체"
             },
        -    "sqaure": {
        -      "description": "화면에 정사각형을 그립니다. 정사각형은 동일한 길이의 네 개의 변을 갖고, 모든 변 사이의 각도가 90도인 도형을 뜻합니다. 이 함수는 rect()함수의 특수한 사례와도 같은데, 너비와 높이가 같고 변의 길이를 "s"라는 매개 변수로 처리하게 됩니다. 기본값으로, 처음 두 변수는 처음 두 변수는 좌측 상단 꼭지점의 좌표를, 3번째 변수는 변의 길이를 지정합니다. rectMode() 함수로 사각형 그리기 모드를 변경하면, 모든 매개 변수값들이 달리 해석됩니다. <br> 5번째, 6번째, 7번째매개 변수를 입력하면, 각각 좌측 상단, 우측 상단, 우측 하단, 좌측 하단 모퉁이들의 각도를 지정하게 됩니다. 이 때 특정 각도 변수가 누락되면, 직전에 입력된 변수와 동일한 값이 적용됩니다.",
        +    "square": {
        +      "description": "화면에 정사각형을 그립니다. 정사각형은 동일한 길이의 네 개의 변을 갖고, 모든 변 사이의 각도가 90도인 도형을 뜻합니다. 이 함수는 rect()함수의 특수한 사례와도 같은데, 너비와 높이가 같고 변의 길이를 라는 매개 변수로 처리하게 됩니다. 기본값으로, 처음 두 변수는 처음 두 변수는 좌측 상단 꼭지점의 좌표를, 3번째 변수는 변의 길이를 지정합니다. rectMode() 함수로 사각형 그리기 모드를 변경하면, 모든 매개 변수값들이 달리 해석됩니다. <br> 5번째, 6번째, 7번째매개 변수를 입력하면, 각각 좌측 상단, 우측 상단, 우측 하단, 좌측 하단 모퉁이들의 각도를 지정하게 됩니다. 이 때 특정 각도 변수가 누락되면, 직전에 입력된 변수와 동일한 값이 적용됩니다.",
               "params": ["숫자: 정사각형의 x좌표값",
               "숫자: 정사각형의 y좌표값",
               "숫자: 정사각형의 너비 및 높이값",
        @@ -307,12 +292,7 @@
                          "숫자:3번째 꼭지점의 x좌표값",
                          "숫자:3번째 꼭지점의 y좌표값"],
               "returns": ""
        -    },
        -      
        -      
        -// Shape > Attributes
        -      
        -      
        +    }, 
             "ellipseMode": {
               "description": "ellipse(), circle(), 그리고 arc() 함수의 매개 변수들이 해석되는 방식을 변경하여, 타원이 그려지는 시작점 위치를 변경합니다.<br><br>기본적으로 제공되는 모드는 ellipseMode(CENTER) 함수와도 같습니다. 이는 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로, 3번째와 4번째 변수를 각각 그 너비와 높이값으로서 해석합니다.<br><br>ellipseMode(RADIUS) 역시 ellipse() 함수의 처음 두 매개 변수를 타원의 중심점으로 해석하나, 3번째와 4번째 변수를 각각 너비와 높이의 중간 지점값으로 해석합니다.<br><br>ellipseMode(CORNER)는 ellipse() 함수의 처음 두 매개 변수를 도형의 좌측 상단을 기준으로 해석하고, 3번째와 4번째 변수를 각각 그 너비와 높이로 해석합니다. <br><br>ellipseMode(CORNERS)는 ellipse() 함수의 처음 두 매개 변수를 도형의 바운딩 박스 중 한 모퉁이의 위치값으로서 해석합니다. 그리고, 3번째와 4번째 변수는 그 정반대 모퉁이의 위치값으로 해석합니다.<br><br>이 함수의 모든 매개 변수(CENTER, RADIUS, CORNER, CORNERS)들은 반드시 대문자로 작성되어야 합니다. 자바스크립트에서는 대소문자 구분이 매우 중요하답니다.",
               "params": ["상수:CENTER, RADIUS, CORNER, 또는 CORNERS"],
        @@ -347,10 +327,6 @@
               "returns": ""
             },
               
        -      
        -// Shape > Curves
        -      
        -      
             "bezier": {
               "description": "화면에 3차 베지어 곡선을 그립니다. 베지어 곡선은 일련의 고정점 및 제어점들로 정의됩니다. 처음 두 매개 변수는 1번째 고정점을, 마지막 두 매개 변수는 마지막 고정점을 지정합니다. 중간의 두 매개 변수는 두 개의 제어점을 지정하며, 이는 곧 곡선의 모양을 정의하게 됩니다. 여기서 제어점은 그 자신을 향해 곡선을 당기는 역할을 합니다. <br><br> 베지어 곡선은 프랑스 출신 자동차 엔지니어인 피에르 베지어(Pierre Bezier)가 개발하였으며, 컴퓨터 그래픽상 부드럽게 경사진 곡선을 정의하는 데에 주로 사용됩니다. curve()도 참고하세요.",
               "params": ["숫자: 1번째 고정점의 x좌표값",
        @@ -435,10 +411,6 @@
               "returns": "숫자: 위치 t에 해당하는 탄젠트"
             },
         
        -      
        -// Shape > Vertex
        -      
        -      
             "beginContour": {
               "description": "beginContour()와 endContour() 함수를 사용하여 특정 도형 내부에 그 음수 좌표에 상응하는 동일한 도형 윤곽선을 그릴 수 있습니다. 예를 들어, 동그라미의 안쪽에 또다른 작은 동그라미를 그릴 수 있습니다. beginContour()는 도형의 꼭지점을 기록하기 시작하고, endContour()는 그 기록을 중지합니다. 이 때, 안쪽의 도형을 정의하는 꼭지점은 바깥쪽의 도형과 반대 순서로 그려져야 합니다. 먼저 바깥에 위치한 원래 도형의 꼭지점을 시계 방향으로 그리고, 그 다음 내부의 도형을 시계 반대 방향으로 그립니다.<br><br> beginContour()/endContour() 함수는 반드시 beginShape()/endShape() 함수 사이에 작성되어야 합니다. 또한, beingContour()/endContour() 함수 사이에는 translate(), rotate(), scale()과 같은 변형 함수나 ellipse() 및 rect()와 같은 도형그리기 함수가 사용될 수 없습니다.",
               "returns": ""
        @@ -496,10 +468,6 @@
                          "숫자: 꼭지점의 v좌표값(선택 사항)"],
               "returns": ""
             },
        -   
        -    
        -// Shape > 3D Primitives
        -    
             
             "plane": {
               "description": "사용자가 지정한 너비와 높이로 평면을 그립니다.",
        @@ -514,21 +482,20 @@
               "params": ["숫자: 상자의 너비값 (선택 사항)",
                          "숫자: 상자의 높이값 (선택 사항)",
                          "숫자: 상자의 깊이값 (선택 사항)",
        -                 "정수: x-차원상의 삼각 세분면 개수 (선택 사항)"
        +                 "정수: x-차원상의 삼각 세분면 개수 (선택 사항)",
                          "정수: y-차원상의 삼각 세분면 개수 (선택 사항)"],
               "returns": ""
             },
             "sphere": {
               "description": "사용자가 지정한 반지름으로 구를 그립니다.<br>detailX와 detailY는 각각 구에 대한 x-차원과 y-차원상의 삼각 세분면 개수를 정합니다. 세분면이 많아질수록 구가 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
               "params": ["숫자: 원의 반지름 (선택 사항)",
        -                 "정수: x-차원상의 삼각 세분면 (선택 사항)
        -                 "정수: y-차원상의 삼각 세분면 (선택 사항)
        +                 "정수: x-차원상의 삼각 세분면 (선택 사항)",
        +                 "정수: y-차원상의 삼각 세분면 (선택 사항)"
                         ],
               "returns": ""
             },
             "cylinder": {
               "description": "사용자가 지정한 반지름과 높이로 원기둥을 그립니다.<br>detailX와 detailY는 각각 원기둥에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원기둥이 매끄러워집니다. detailX와 detailY 모두 권장 최대값은 24입니다. 24보다 높은 값을 사용하면 경고창이 뜨거나 브라우저가 느려질 수 있습니다.",
        -      "params": ["숫자: 표면의 반지름 (선택 사항)",
               "params": ["숫자: 원기둥의 높이 (선택 사항)",
                          "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
                          "정수: y-차원상의 세분면 개수, 기본값은 1 (선택 사항)",
        @@ -557,13 +524,11 @@
               "description": "사용자가 지정한 반지름과 튜브 반지름으로 원환을 그립니다. <br>detailX와 detailY는 각각 원환에 대한 x-차원과 y-차원상의 세분면 개수를 정합니다. 세분면이 많아질수록 원환이 매끄러워집니다. detailX과 detailY의 권장 최대값은 각각 24와 16입니다. 4나 6처럼 조금 더 적은 값으로 설정하면, 원환이 아닌 새로운 모양을 만들 수 있습니다.",
               "params": ["숫자: 전체 원환의 반지름 (선택 사항)",
                          "숫자: 튜브의 반지름 (선택 사항)",
        -                 "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항),
        +                 "정수: x-차원상의 세분면 개수, 기본값은 24 (선택 사항)",
                          "정수: y-차원상의 세분면 개수, 기본값은 16 (선택 사항)"],
               "returns": ""
             },
             
        -// Shape > 3D Models
        -    
              "loadModel": {
               "description": "OBJ 또는 STL 파일로부터 3D 모델을 불러옵니다. <br><br> loadModel() 함수는 반드시 preload() 함수 안에 작성되어야 하며, 이로써 3D 모델을 코드 실행에 앞서 온전히 불러올 수 있습니다. <br><br>OBJ와 STL 파일 형식의 한계 중 하나는 빌트인 스케일 기능이 제공되지 않는다는 것입니다. 즉, 파일을 불러오는 소프트웨어 프로그램에 따라 3D 모델의 크기가 상이해집니다. 3D 모델이 보이지 않는다면 loadModel() 함수에 표준화된 매개 변수인 true를 입력해 보세요. 또한 불러온 3D 모델의 크기는 scale() 함수로 변경할 수 있습니다. <br>색상이 지정된 STL 파일은 현재 지원하지 않아, 색상 요소가 제거된 상태로 렌더링될 수 있습니다.",
               "params": ["문자열: 불러올 3D 모델의 파일 경로",
        @@ -578,8 +543,6 @@
               "returns": ""
             },
             
        -//Constants
        -    
             "HALF_PI": {
               "description": "HALF_PI는 1.57079632679489661923 값을 갖는 상수입니다. 지름에 대한 원주율의 절반에 해당하며, 삼각 함수 sin()과 cos()와 함께 쓰면 더욱 유용합니다.",
               "returns": ""
        @@ -608,8 +571,6 @@
               "description": "p5.js가 각도를 해석하고 계산하는 방법을 설정하기 위해, angleMode() 함수와 그 매개 변수(DEGREES 또는 RADIANS)를 사용합니다.",
               "returns": ""
             },
        -
        -//Environment
             
             "print": {
               "description": "print() 함수는 브라우저 콘솔창에 출력할 때 사용됩니다. 프로그램이 생성하는 데이터를 확인할 때 주로 도움됩니다. 함수는 매번 호출될 때마다 콘솔창에 새로운 텍스트 줄을 만듭니다. 개별 요소는 큰따옴표로 분리하고, 더하기 연산자(+)로 두 요소를 결합할 수 있습니다.<br><br>인수없이 print()를 호출하면, window.print()와 동일하게 브라우저상 인쇄 기능을 켭니다. 콘솔창에 빈 줄을 출력하려면 print('\n')을 작성하면 됩니다.",
        @@ -640,7 +601,6 @@
               "description": "화면상 커서를 숨깁니다.",
               "returns": ""
             },
        -
             "displayWidth": {
               "description": "pixelDensity() 함수의 기본값에 따라 화면의 너비값을 저장하는 시스템 변수입니다. 모든 디스플레이에서 프로그램을 전체 화면으로 실행시킬 때 사용합니다. 실제 화면 크기값을 반환하려면 여기에 pixelDensity를 곱하면 됩니다.",
               "returns": ""
        @@ -695,10 +655,7 @@
               "description": "현재 URL 매개 변수들을 객체로 받아옵니다.",
               "returns": "객체: URL 매개 변수들"
             },
        -    
        -    
        -//Structure
        -    
        +
             "preload": {
               "description": "preload() 함수는 setup() 함수 직전에 호출되며, 외부 파일의 비동기 불러오기를 차단하기 위해 사용됩니다. preload() 함수로 외부 파일 사전 불러오기가 설정되면, setup() 함수는 불러오기 호출이 완료될 때까지 대기합니다. 불러오기 호출 이외의 다른 함수(loadImage, loadJOSN, loadFont, loadString)는 preload() 함수 안에 포함되지 않아야 합니다. 만약 비동기 불러오기를 선호한다면, 불러오기 메소드를 setup() 함수 안에 포함시키거나, 그 외의 영역에서 callback 매개 변수를 사용하여 호출하면 됩니다.<br> 기본값으로 'loading..'이라는 텍스트가 화면에 나타납니다. 나만의 로딩 페이지를 만들려면 id가 p5_loading으로 지정된 HTML 요소를 추가하면 됩니다. 자세한 정보는 <a href='http://bit.ly/2kQ6Nio'>여기</a>서 확인하세요.",
               "returns": ""
        @@ -732,7 +689,7 @@
               "returns": ""
             },
             "pop": {
        -      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()""
        +      "description": "push() 함수는 현재의 드로잉 스타일 설정과 변형을 저장하고, pop() 함수는 이 설정들을 복구합니다. 이 함수들은 항상 함께 쓰이는 점에 유의하세요. 이 함수들을 통해 스타일과 변형 설정을 변경한 뒤에도 이전 설정 상태로 돌아갈 수 있습니다. push()와 pop() 함수들은 설정 사항에 대해 좀 더 많은 권한을 제공합니다. (두 번째 예제를 참고하세요.)<br><br> push()는 다음의 함수들을 통해 지정된 현재 변형 상태 및 스타일 설정 사항을 저장합니다: fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed().<br><br>WebGL 모드에서는 다음의 함수들을 통해 지정된, 더욱 다양한 스타일 설정 사항이 저장될 수 있습니다:  setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial(), 그리고 shader()"
             },
             "redraw": {
               "description": "draw() 함수 안에 포함된 코드를 한 번 재실행합니다. 이 함수를 통해 필요시에만 화면을 업데이트할 수 있습니다. mousePressed()나 keyPressed()가 지정한 이벤트를 발생시킬 때가 그 예입니다.<br><br>프로그램의 구조를 고려하면, mousePressed()와 같은 이벤트 함수에 redraw()를 호출하는 것이 좋습니다. 이는 redraw()가 draw()함수를 즉각적으로 실행시키지 않기 때문입니다. redraw()는 화면 업데이트가 필요함을 알리는 표식 설정만합니다.",
        @@ -746,239 +703,234 @@
               "returns": ""
             },
             
        -//DOM
        -    
        -  "p5.Element": {
        -    "description": "캔버스, 그래픽 버퍼, 기타 HTML 요소를 비롯하여, 스케치에 추가된 모든 요소(element)들을 위한 기본 클래스입니다. p5.Element 클래스는 직접 호출되지 않지만, 그 객체는 createCanvas, createGraphics, createDiv, createImg, createInput 호출을 통해 생성됩니다.",
        -    "params": ["문자열: 래핑된 DOM 노드",
        -               "P5: p5 인스턴스에 대한 포인터 (선택 사항)"
        -              ],
        -    "fields": ["기본 HTML 요소로, 모든 일반 HTML 메소드를 호출."
        -               ],
        -    "methods": ["지정된 부모 클래스에 요소를 연결합니다. 요소의 컨테이너를 설정하는 방법입니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 부모 노드가 반환됩니다. 캔버스 배치하는 다른 방법들은 <a href= 'https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>이 위키 페이지</a>를 참고하세요.",
        -                "요소의 ID를 설정합니다. 별도로 지정한 ID 인수가 없으면, 요소의 현재 ID를 반환합니다. 요소당 1개의 특정 id를 가질 수 있습니다. .class() 함수는 동일한 클래스 이름을 가진 여러 요소들을 식별하는 데에 사용됩니다.",
        -                "사용자가 지정한 클래스를 요소에 더합니다. 별도로 지정한 클래스 인수가 없으면, 요소의 현재 클래스(들)를 포함하는 문자열을 반환합니다.",
        -                ".mousePressed() 함수는 요소 위에서 마우스 버튼이 눌릴 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".doubleClicked() 함수는 요소 위에서 마우스 버튼을 빠르게 두 번 클릭할 때마다 한 번씩 호출됩니다. 요소에 행동 특정적 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".mouseWheel() 함수는 요소 위에서 마우스 휠을 스크롤 할 때마다 한 번싹 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.<br> 이 함수에서는 콜백 함수를 인수로서 사용할 수 있습니다. 그 경우, 요소 위에서 휠 이벤트가 발생할 때마다 콜백 함수가 하나의 event 인수로서 전달됩니다. event.deltaY 속성은 마우스 휠이 위쪽으로 회전하거나 사용자로부터 멀어지면 음수값을 반환하고, 그 반대 방향에선 양수값을 반환합니다. event.deltaX 속성은 마우스 가로 휠 스크롤을 읽는다는 점을 제외하고 event.deltaY와 동일하게 작동합니다.",
        -                ".mouseReleased() 함수는 요소 위에서 마우스 버튼을 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".mouseClicked() 함수는 요소 위에서 마우스 버튼을 클릭한 뒤 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".mouseMoved() 함수는 마우스가 요소 위에서 움직일 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".mouseOver() 함수는 마우스가 요소 위에 올라올 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".mouseOut() 함수는 마우스가 요소 위에서 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".touchStarted() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".touchMoved() 함수는 터치 움직임이 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".touchEnded() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".dragOver() 함수는 요소 위에 파일을 드래그할 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                ".dragLeave() 함수는 드래그된 파일이 요소 영역을 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        -                "요소에 특정 클래스를 추가합니다.",
        -                "요소로부터 특정 클래스를 제거합니다.",
        -                "요소에 이미 클래스가 설정되어 있는지 확인합니다.",
        -                "요소 클래스를 토글합니다.",
        -                "지정된 부모 클래스에 요소를 자식으로서 연결합니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 자식 DOM 노드 배열이 반환됩니다. ",
        -                "p5 Element를 수직으로, 수평으로, 또는 수직 및 수평으로 가운데 정렬합니다. 별도로 지정한 부모가 있는 경우 부모를 기준으로, 부모가 없는 경우 그 자신을 기준으로 합니다. 별도로 지정한 인수가 없으면 요소는 수직 및 수평으로 정렬됩니다.",
        -                "사용자가 별도로 지정한 인수로서 요소의 내부 HTML을 설정하며, 기존의 모든 HTML를 대체합니다. 참(true)이 그 2번째 인수로서 포함된 경우, 기존의 모든 HTML을 대체하는 대신 새로운 HTML을 추가(append)합니다. 별도로 지정한 인수가 없으면 요소의 내부 HTML을 반환합니다.",
        -                "요소의 위치를 설정합니다. 별도로 지정한 위치 유형 인수가 없는 경우, 화면창의 (0,0)을 기준으로 합니다. 기본적으로, 이 메소드를 통해 position:absolute와 left 및 top 스타일 속성을 설정합니다. 선택적으로, 3번째 인수를 통해 x 및 y 좌표의 <a href ='https://developer.mozilla.org/en-US/docs/Web/CSS/position'>위치 지정 체계</a>를 설정할 수 있습니다. 별도로 지정한 인수가 없으면 함수는 요소의 x와 y의 위치를 반환합니다.",
        -                "별도 지정한 값(2번째 인수)으로 CSS 스타일 속성(1번째 인수)을 설정합니다. 1개의 인수만 지정할 경우, .style()은 주어진 속성의 값을 반환합니다. 그러나 이 인수를 CSS 구문('text-align:center')으로 작성할 경우, .style()은 CSS를 설정합니다.",
        -                "사용자가 지정한 요소에 새 속성을 추가하거나, 요소의 기존 속성값을 변경합니다. 별도로 지정한 값이 없는 경우 주어진 속성의 값을 반환하고, 속성이 설정되지 않은 경우 null을 반환합니다. ",
        -                "요소로부터 속성을 제거합니다.",
        -                "별도로 지정한 인수가 없는 경우, 요소의 값을 반환하거나 설정합니다.",
        -                "현재 요소를 보여줍니다. display:block로 스타일을 설정합니다.",
        -                "현재 요소를 숨깁니다. display:none으로 스타일을 설정합니다.",
        -                "요소의 너비와 높이를 설정합니다. AUTO는 한 번에 한 개의 수치를 조정하는 데에 쓰입니다. 별도로 지정한 인수가 없는 경우, 객체 속 요소의 너비와 높이를 반환합니다. 이미지 파일과 같이 불러오기가 필요한 요소의 경우, 불러오기가 완료된 후 함수를 호출하는 것을 권장합니다.",
        -                "요소를 제거하고, 모든 미디어 스트림을 중지하며, 모든 리스너를 해제합니다.",
        -                "요소에 드롭된 파일이 로드될 때마다 호출되는 콜백을 등록합니다. p5는 메모리에 드롭된 모든 파일을 로드하고 이를 p5.File 객체로서 콜백에 전달합니다. 동시에 여러 파일을 드롭할 경우, 콜백이 여러 번 호출됩니다. 선택적으로, raw 드롭 이벤트에 등록될 2번째 콜백을 전달할 수 있습니다. 이 경우, 콜백에 본래 DragEvent도 제공됩니다. 동시에 여러 파일을 드롭하면 2번째 콜백이 드롭당 한 번씩 발생하며, 1번째 콜백은 로드된 파일당 한 번씩 발생합니다.",
        -               ]
        -  },
        -
        -  "select": {
        -    "description": "지정한 ID, 클래스, 또는 태그 이름(접두어 '#'로 ID를, '.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element를 반환합니다. 클래스나 태그의 이름이 2개 이상의 요소로 지정된 경우, 1번째 요소만 반환됩니다. DOM 노드는 .elt로 검섹할 수 있습니다. 아무 것도 검색되지 않을 경우 null을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        -    "params": ["문자열: 검색할 요소의 id, 클래스, 또는 태그 이름",
        -               "문자열|p5.Element|HTML 요소: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        -    "returns": "검색된 노드를 포함한 p5.Element"
        -  },
        -  "selectAll": {
        -    "description": "지정한 클래스 또는 태그 이름('.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element 배열로 반환합니다. DOM 노드는 .elt로 검색할 수 있습니다. 아무 것도 검색되지 않을 경우 빈 배열을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        -    "params": ["문자열: 검색할 요소의 클래스 또는 태그 이름",
        -               "문자열: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        -    "returns": "검색된 노드를 포함한 p5.Element 배열"
        -  },
        -  "removeElements": {
        -    "description": "createCanvase() 또는 createGraphics()로 생성된 캔버스와 그래픽을 제외하고, p5로 생성된 모든 요소를 제거합니다. 이벤트 핸들러 역시 제거되며, 요소가 DOM에서 제거됩니다.",
        -    "params": "",
        -    "returns": ""
        -  },
        -  "changed": {
        -    "description": ".changed() 함수는 요소값이 변경될 때 호출됩니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        -    "params": ["함수|불리언: 요소값이 변경될 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        -    "returns": ""
        -  },
        -  "input": {
        -    "description": ".input() 함수는 요소가 사용자 입력을 감지할 때 호출됩니다. 입력 이벤트는 키 또는 슬라이더 요소의 변경을 감지합니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        -    "params": ["함수|불리언: 요소가 사용자 입력을 감지할 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        -    "returns": ""
        -  },
        -  "createDiv": {
        -    "description": "주어진 내부 HTML을 사용하여 DOM에 <div></div> 요소를 생성합니다.",
        -    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createP": {
        -    "description": "주어진 내부 HTML을 사용하여 DOM에 <p></p> 요소를 생성합니다. 문단형 텍스트 작성시 사용됩니다.",
        -    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createSpan": {
        -    "description": "주어진 내부 HTML을 사용하여 DOM에 <span></span> 요소를 생성합니다.",
        -    "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createImg": {
        -    "description": "주어진 src와 대체 텍스트(alt text)를 사용하여 DOM에 <img> 요소를 생성합니다.",
        -    "params": ["문자열: 이미지의 src 또는 url 경로",
        -               "문자열: 이미지가 로드되지 않을 경우 사용할 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Attributes'>대체 텍스트</a>. 빈 문자열(" ")로 이미지 숨기기 가능",
        -               "문자열: img 요소의 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin'>교차 출처 속성(crossOrigin property)</a>. '익명(anonymous)' 또는 '사용 자격 증명(use-credentials)'을 통해 교차 출처 권한이 있는 이미지를 검색하세요. 이는 캔버스에 이미지를 사용하기 위함이며, 빈 문자열(" ")이 전달된 경우 교차 출처 리소스 공유(CORS)는 사용되지 않습니다.",
        -               "gkatn: 인수로 지정된 p5.Element가 이미지 데이터를 불러왔을 때 호출되는 콜백 함수 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createA": {
        -    "description": "DOM에 하이퍼링크를 포함한 <a></a> 요소를 생성합니다.",
        -    "params": ["문자열: 링크될 페이지 url",
        -               "문자열: 화면에 보여질 링크 요소의 내부 HTML",
        -               "문자열: 새로운 링크가 보여질 대상, _blank, _self, _parent, _top 중 지정 가능 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createSlider": {
        -    "description": "DOM에 슬라이더<input></input> 요소를 생성합니다. .size() 함수로 슬라이더의 길이를 설정합니다.",
        -    "params": ["숫자: 슬라이더의 최소값",
        -               "숫자: 슬라이더의 최대값",
        -               "숫자: 슬라이더의 기본값(선택 사항)",
        -               "숫자: 슬라이더의 단위당 이동 크기(이동 크기가 0으로 지정된 경우, 슬라이더는 최소값과 최대값 사이를 부드럽게 이동합니다.)(선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createButton": {
        -    "description": "DOM에 <button></button> 요소를 생성합니다. .size() 함수로 버튼의 크기를 설정합니다. .mousePressed() 함수로 버튼이 클릭됐을 때의 행동을 지정합니다.",
        -    "params": ["문자열: 버튼 위에 나타나는 레이블",
        -               "문자열: 버튼값 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createCheckbox": {
        -    "description": "DOM에 체크박스<input></input> 요소를 생성합니다. .checked() 함수를 통해 체크되었는지의 여부를 반환합니다.",
        -    "params": ["문자열: 체크박스 위에 나타나는 레이블 (선택 사항)",
        -               "불리언: 체크박스의 값: 체크는 참(true), 체크 해제는 거짓(false) (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createSelect": {
        -    "description": "DOM에 드롭다운 메뉴<select></select> 요소를 생성합니다. 이미 생성된 셀렉트 박스(select box)를 선택할 경우, p5.Element에 select-box 메소드를 지정하는 데에도 쓰입니다. 셀렉트 박스 생성 후, .option() 메소드로 선택지(option)를 설정할 수 있습니다. .selected() 메소드는 p5.Element 인스턴스인 현재 드롭다운 요소를 반환합니다. .selected() 메소드는 특정 선택지를 최초 페이지 로드시의 기본값으로서 설정할 수 있습니다. .disable() 메소드는 특정 선택지를 비활성화하고, 별도로 지정된 인수가 없는 경우엔 전체 드롭다운 요소를 비활성화 상태로 표시합니다.",
        -    "params": ["불리언: 드롭다운이 여러 개의 선택지를 제공할 경우 참(true) (선택 사항)",
        -               "객체: DOM 셀렉트 요소"],
        -    "returns": "p5.Element"
        -  },
        -  "createRadio": {
        -    "description": "DOM에 라디오 버튼<input></input> 요소를 생성합니다. 라디오 버튼 생성 후, .option() 메소드로 옵션을 설정할 수 있습니다. .value() 메소드는 현재 선택된 옵션을 반환합니다.",
        -    "params": ["문자열: 생성된 div와 input field 각각의 id 및 이름 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createColorPicker": {
        -    "description": "DOM에 색상 입력을 위한 색상 추출(colorPicker) 요소를 생성합니다. .value() 메소드는 색상의 헥사(Hex) 문자열(#rrggbb)을 반환합니다. .color() 메소드는 현재 선택된 색상의 p5.Color 객체를 반환합니다.",
        -    "params": ["문자열|p5.Color: 요소의 색상 기본값 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createInput": {
        -    "description": "DOM에 텍스트 입력을 위한 <input></input> 요소를 생성합니다. .size() 함수로 상자의 크기를 설정합니다.",
        -    "params": ["문자열: 입력 상자의 기본값 (선택 사항)",
        -               "문자열: 텍스트 유형 (예: text, password 등) 기본값은 text (선택 사항)"],
        -    "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createFileInput": {
        -    "description": "'파일(file)' 유형의 DOM에 <input></input> 요소를 생성합니다. 스케치에 사용할 로컬 파일을 선택할 수 있게 됩니다.",
        -    "params": ["함수: 파일이 로드될 때의 콜백 함수 (선택 사항)",
        -               "문자열: 여러 파일 선택 허용 (선택 사항)"],
        -    "returns": "p5.Element: 생성된 DOM 요소를 담고있는 p5.Element에 대한 포인터"
        -  },
        -  "createVideo": {
        -    "description": "DOM에 간단한 오디오/비디오 재생을 위한 HTML5 <video> 요소를 생성합니다. 화면에 나타나기가 기본값이며, .hide()로 숨길 수 있습니다. video() 함수를 통해 캔버스에 그릴 수 있습니다. 1번째 매개 변수는 비디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 비디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        -    "params": ["문자열|문자열 배열[]: 비디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        -               "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        -    "returns": "p5.MediaElement: 비디오 p5.Element에 대한 포인터"
        -  },
        -  "createAudio": {
        -    "description": "DOM에 간단한 오디오 재생을 위한 HTML5 <audio> 요소를 생성합니다. 1번째 매개 변수는 오디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 오디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        -    "params": ["문자열|문자열 배열[]: 오디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        -               "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        -    "returns": "p5.MediaElement: 오디오 p5.Element에 대한 포인터"
        -  },
        -  "VIDEO": {
        -    "description": "",
        -    "params": [""],
        -    "returns": ""
        -  },
        -  "AUDIO": {
        -    "description": "",
        -    "params": [""],
        -    "returns": ""
        -  },
        -  "createCapture": {
        -    "description": "웹캠의 오디오/비디오 피드를 담는 <video> 요소를 생성합니다. 이 요소는 캔버스와는 별개로 작동합니다. '화면에 나타내기'가 기본값으로 주어지며, .hide()를 사용하여 화면으로부터 숨길 수 있습니다. image() 함수를 사용하여 피드를 캔버스에 그릴 수 있습니다. loadedmetadata 속성을 사용하여 요소가 완전히 로드된 시점을 감지할 수 있습니다. (2번째 예제 참고)<br><br> 피드의 구체적인 속성은 제약 조건(Constraints) 객체를 전달할 수 있습니다. 속성 및 제약 조건 객체와 관련해서는 <a href = 'https://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'>W3C 사양</a>을 참고하세요. 모든 브라우저가 이 기능을 지원하지 않는 점에 유의하세요.<br><br>보안 정보: 최신 브라우저 보안 사양은 createCapture() 이면의 getUserMedia() 메소드가 로컬 또는 HTTPS에서 코드 실행시에만 작동할 것을 요구합니다. 자세한 사항은 <a href = 'https://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>여기</a>와 <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>여기</a>서 확인하세요. ",
        -    "params": ["문자열|상수|객체: 캡처 유형, VIDEO 또는 AUDIO 중 하나로 지정 가능. 별도의 매개 변수가 지정되지 않을 경우 기본값으로 둘 다 또는 제약 조건 객체",
        -               "함수: 스트림 로드 완료 후 1번 호출되는 함수 (선택 사항)"],
        -    "returns": ""
        -  },
        -  "createElement": {
        -    "description": "지정된 콘텐츠를 지닌 DOM에 태그된 요소를 생성합니다.",
        -    "params": ["문자열: 새로운 요소의 태그",
        -               "문자열: 요소 안에 삽입될 HTML 콘텐츠 (선택 사항)"],
        -    "returns": ""
        -  },
        -  "p5.MediaElement": {
        -    "description": "오디오/비디오 처리를 위해 p5.Element를 확장합니다. p5.Element의 메소드 뿐 아니라, 미디어 제어를 위한 메소드도 포함합니다. p5.MediaElements는 직접 호출되지 않지만, createVideo, createAudio, CreateCapture 호출을 통해 생성됩니다.",
        -    "params": ["문자열: 래핑된 DOM 노드"],
        -    "fields": ["미디어 요소 소스 경로"],
        -    "methods": ["HTML5 미디어 요소를 재생합니다.",
        -               "HTML5 미디어 요소를 중지합니다. (현재 시간을 0으로 설정)",
        -               "HTML5 미디어 요소를 일시정지합니다.",
        -               "HTML5 미디어 요소의 반복을 참(true)로 설정하고, 재생 시작합니다.",
        -               "HTML5 미디어 요소의 반복을 거짓(false)으로 설정합니다. 종료 시점에 도달하면 요소가 중지합니다.",
        -               "HTML5 미디어 요소 자동재생 여부 설정",
        -               "HTML5 미디어 요소의 볼륨을 설정합니다. 별도로 지정한 인수가 없으면, 현재 볼륨을 반환합니다.",
        -               "별도로 지정한 인수가 없으면, 요소의 현재 재생 속도를 반환하빈다. 속도 매개 변수는 2.0일 때 2배속으로, 0.5일 때 0.5배속으로, -1일 때 정상 속도로 역재생합니다. (모든 브라우저가 역재생을 지원하지 않으며, 일부 지원 브라우저에서도 부드럽게 재생되지 않을 수 있습니다.)",
        -               "별도로 지정한 인수가 없을 경우, 요소의 현재 시간을 반환합니다. 인수가 지정될 경우, 요소의 현재 시간이 해당 인수로 설정됩니다.",
        -               "HTML5 미디어 요소의 지속 시간을 반환합니다.",
        -               "오디오/비디오 요소가 종료 시점에 도달할 때 호출할 이벤트를 예약합니다. 요소가 반복하는 경우 호출되지 않습니다. 요소는 oneded 콜백에 인수로 전달됩니다.",
        -               "요소가 출력한 오디오를 특정 audioNode나 p5.sound 객체로 보냅니다. 요소가 없는 경우, p5의 마스터 출력에 연결합니다. 모든 연결은 .disconnect() 메소드로 제거할 수 있습니다. p5.sound.js 애드온 라이브러리로 이러한 방법을 사용할 수 있습니다.",
        -               "마스터 출력을 비롯하여 모든 웹 오디오 라우팅을 분리합니다. 사용 예: 오디오 효과를 통해 출력을 다시 라우팅할 때",
        -               "웹 브라우저가 지정한 기본 미디어 요소(MediaElement) 컨트롤을 나타냅니다.",
        -               "기본 미디어 요소(MediaElement) 컨트롤을 숨깁니다.",
        -               "오디오/비디오와 같은 미디어 요소(MediaElement)가 재생 큐 지점에 도달할 때 발생할 이벤트를 예약합니다. 콜백 함수, 콜백이 발생할 시간(초 단위), 콜백에 대한 선택적 매개 변수를 허용합니다. 1번째 매개 변수는 시간(time)을, 2번째 매개 변수는 param을 콜백 함수에 전달합니다.",
        -               "ID를 기반으로 콜백을 제거합니다. ID는 addCue 메소드로 반환됩니다.",
        -               "addCue 메소드로 예약된 모든 콜백을 제거합니다."],
        -    "returns": ""
        -  },
        -  "p5.File": {
        -    "description": "파일을 위한 기본 클래스입니다. Element.drop()과 createFileInput()에 사용됩니다.",
        -    "params": "파일: 래핑된 파일",
        -    "fields": ["기본 파일 객체. 모든 일반 File 메소드를 호출할 수 있습니다.",
        -              "파일 유형 (이미지, 텍스트 등)",
        -              "파일 하위 유형 (주로 jpg, png, xml 등의 파일 확장자)",
        -              "파일명",
        -              "파일 크기",
        -              "이미지 데이터를 담는 URL 문자열"],
        -    "returns": ""
        -  },
        -    
        -//Rendering
        -    
        -  "p5.Graphics": {
        -    "description": "렌더러을 둘러싼 얇은 래퍼(wrapper)로, 그래픽 버퍼 객체를 생성하는 데에 사용합니다. 화면 밖 그래픽 버퍼에 그리려면 이 클래스를 사용하세요. 2개의 매개 변수는 너비와 높이를 픽셀 단위로 지정합니다. 이 클래스의 필드와 메소드는 확장성이 있으나, p5를 위한 일반적인 드로잉 API를 반영합니다.<br>p5.Element를 확장합니다.",
        -    "params": ["숫자: 너비값",
        -               "숫자: 높이값",
        -               "상수: 사용할 렌더러, P2D 또는 WEBGL",
        -               "P5: p5 인스턴스에 대한 포인터 (선택 사항)",
        -    ""],
        -    "methods": ["그래픽 버퍼 객체로 자동 재설정되지 않은 특정값들(예: 레퍼런스 중 변형(Transform) 또는 라이트(Light) 항목에 해당하는 함수들로서 지정된 값들). 이 메소드를 draw() 함수 안에서 호출하면, 기본 캔버스의 행위를 복제합니다.",
        -               "페이지에서 그래픽 객체를 제거하고 이 객체에 연결된 모든 소스들을 연결 해제합니다."]
        -  },
        -  "createCanvas": {
        +    "p5.Element": {
        +      "description": "캔버스, 그래픽 버퍼, 기타 HTML 요소를 비롯하여, 스케치에 추가된 모든 요소(element)들을 위한 기본 클래스입니다. p5.Element 클래스는 직접 호출되지 않지만, 그 객체는 createCanvas, createGraphics, createDiv, createImg, createInput 호출을 통해 생성됩니다.",
        +      "params": ["문자열: 래핑된 DOM 노드",
        +                "P5: p5 인스턴스에 대한 포인터 (선택 사항)"
        +                ],
        +      "fields": ["기본 HTML 요소로, 모든 일반 HTML 메소드를 호출."
        +                ],
        +      "methods": ["지정된 부모 클래스에 요소를 연결합니다. 요소의 컨테이너를 설정하는 방법입니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 부모 노드가 반환됩니다. 캔버스 배치하는 다른 방법들은 <a href= 'https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>이 위키 페이지</a>를 참고하세요.",
        +                  "요소의 ID를 설정합니다. 별도로 지정한 ID 인수가 없으면, 요소의 현재 ID를 반환합니다. 요소당 1개의 특정 id를 가질 수 있습니다. .class() 함수는 동일한 클래스 이름을 가진 여러 요소들을 식별하는 데에 사용됩니다.",
        +                  "사용자가 지정한 클래스를 요소에 더합니다. 별도로 지정한 클래스 인수가 없으면, 요소의 현재 클래스(들)를 포함하는 문자열을 반환합니다.",
        +                  ".mousePressed() 함수는 요소 위에서 마우스 버튼이 눌릴 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".doubleClicked() 함수는 요소 위에서 마우스 버튼을 빠르게 두 번 클릭할 때마다 한 번씩 호출됩니다. 요소에 행동 특정적 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".mouseWheel() 함수는 요소 위에서 마우스 휠을 스크롤 할 때마다 한 번싹 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.<br> 이 함수에서는 콜백 함수를 인수로서 사용할 수 있습니다. 그 경우, 요소 위에서 휠 이벤트가 발생할 때마다 콜백 함수가 하나의 event 인수로서 전달됩니다. event.deltaY 속성은 마우스 휠이 위쪽으로 회전하거나 사용자로부터 멀어지면 음수값을 반환하고, 그 반대 방향에선 양수값을 반환합니다. event.deltaX 속성은 마우스 가로 휠 스크롤을 읽는다는 점을 제외하고 event.deltaY와 동일하게 작동합니다.",
        +                  ".mouseReleased() 함수는 요소 위에서 마우스 버튼을 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".mouseClicked() 함수는 요소 위에서 마우스 버튼을 클릭한 뒤 놓을 때마다 한 번씩 호출됩니다. 터치 스크린 기반의 모바일 브라우저에서는 손가락 탭을 통해 이벤트가 발생합니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".mouseMoved() 함수는 마우스가 요소 위에서 움직일 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".mouseOver() 함수는 마우스가 요소 위에 올라올 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".mouseOut() 함수는 마우스가 요소 위에서 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".touchStarted() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".touchMoved() 함수는 터치 움직임이 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".touchEnded() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".dragOver() 함수는 요소 위에 파일을 드래그할 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  ".dragLeave() 함수는 드래그된 파일이 요소 영역을 벗어날 때마다 한 번씩 호출됩니다. 요소에 이벤트 리스너를 연결하는 데에 사용됩니다.",
        +                  "요소에 특정 클래스를 추가합니다.",
        +                  "요소로부터 특정 클래스를 제거합니다.",
        +                  "요소에 이미 클래스가 설정되어 있는지 확인합니다.",
        +                  "요소 클래스를 토글합니다.",
        +                  "지정된 부모 클래스에 요소를 자식으로서 연결합니다. 문자열 ID, DOM 노드, 또는 p5.Element를 허용합니다. 별도의 인수가 지정되지 않을 경우, 자식 DOM 노드 배열이 반환됩니다. ",
        +                  "p5 Element를 수직으로, 수평으로, 또는 수직 및 수평으로 가운데 정렬합니다. 별도로 지정한 부모가 있는 경우 부모를 기준으로, 부모가 없는 경우 그 자신을 기준으로 합니다. 별도로 지정한 인수가 없으면 요소는 수직 및 수평으로 정렬됩니다.",
        +                  "사용자가 별도로 지정한 인수로서 요소의 내부 HTML을 설정하며, 기존의 모든 HTML를 대체합니다. 참(true)이 그 2번째 인수로서 포함된 경우, 기존의 모든 HTML을 대체하는 대신 새로운 HTML을 추가(append)합니다. 별도로 지정한 인수가 없으면 요소의 내부 HTML을 반환합니다.",
        +                  "요소의 위치를 설정합니다. 별도로 지정한 위치 유형 인수가 없는 경우, 화면창의 (0,0)을 기준으로 합니다. 기본적으로, 이 메소드를 통해 position:absolute와 left 및 top 스타일 속성을 설정합니다. 선택적으로, 3번째 인수를 통해 x 및 y 좌표의 <a href ='https://developer.mozilla.org/en-US/docs/Web/CSS/position'>위치 지정 체계</a>를 설정할 수 있습니다. 별도로 지정한 인수가 없으면 함수는 요소의 x와 y의 위치를 반환합니다.",
        +                  "별도 지정한 값(2번째 인수)으로 CSS 스타일 속성(1번째 인수)을 설정합니다. 1개의 인수만 지정할 경우, .style()은 주어진 속성의 값을 반환합니다. 그러나 이 인수를 CSS 구문('text-align:center')으로 작성할 경우, .style()은 CSS를 설정합니다.",
        +                  "사용자가 지정한 요소에 새 속성을 추가하거나, 요소의 기존 속성값을 변경합니다. 별도로 지정한 값이 없는 경우 주어진 속성의 값을 반환하고, 속성이 설정되지 않은 경우 null을 반환합니다. ",
        +                  "요소로부터 속성을 제거합니다.",
        +                  "별도로 지정한 인수가 없는 경우, 요소의 값을 반환하거나 설정합니다.",
        +                  "현재 요소를 보여줍니다. display:block로 스타일을 설정합니다.",
        +                  "현재 요소를 숨깁니다. display:none으로 스타일을 설정합니다.",
        +                  "요소의 너비와 높이를 설정합니다. AUTO는 한 번에 한 개의 수치를 조정하는 데에 쓰입니다. 별도로 지정한 인수가 없는 경우, 객체 속 요소의 너비와 높이를 반환합니다. 이미지 파일과 같이 불러오기가 필요한 요소의 경우, 불러오기가 완료된 후 함수를 호출하는 것을 권장합니다.",
        +                  "요소를 제거하고, 모든 미디어 스트림을 중지하며, 모든 리스너를 해제합니다.",
        +                  "요소에 드롭된 파일이 로드될 때마다 호출되는 콜백을 등록합니다. p5는 메모리에 드롭된 모든 파일을 로드하고 이를 p5.File 객체로서 콜백에 전달합니다. 동시에 여러 파일을 드롭할 경우, 콜백이 여러 번 호출됩니다. 선택적으로, raw 드롭 이벤트에 등록될 2번째 콜백을 전달할 수 있습니다. 이 경우, 콜백에 본래 DragEvent도 제공됩니다. 동시에 여러 파일을 드롭하면 2번째 콜백이 드롭당 한 번씩 발생하며, 1번째 콜백은 로드된 파일당 한 번씩 발생합니다."
        +                ]
        +    },
        +    "select": {
        +      "description": "지정한 ID, 클래스, 또는 태그 이름(접두어 '#'로 ID를, '.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element를 반환합니다. 클래스나 태그의 이름이 2개 이상의 요소로 지정된 경우, 1번째 요소만 반환됩니다. DOM 노드는 .elt로 검섹할 수 있습니다. 아무 것도 검색되지 않을 경우 null을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        +      "params": ["문자열: 검색할 요소의 id, 클래스, 또는 태그 이름",
        +                "문자열|p5.Element|HTML 요소: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        +      "returns": "검색된 노드를 포함한 p5.Element"
        +    },
        +    "selectAll": {
        +      "description": "지정한 클래스 또는 태그 이름('.'로 클래스 지정 가능, 태그는 별도의 접두어 없음)에 해당하는 요소를 페이지 내에서 검색하고, p5.Element 배열로 반환합니다. DOM 노드는 .elt로 검색할 수 있습니다. 아무 것도 검색되지 않을 경우 빈 배열을 반환합니다. 검색할 컨테이너를 별도로 지정할 수 있습니다.",
        +      "params": ["문자열: 검색할 요소의 클래스 또는 태그 이름",
        +                "문자열: id, p5.Element, 또는 HTML 요소 내에서 검색(선택 사항)"],
        +      "returns": "검색된 노드를 포함한 p5.Element 배열"
        +    },
        +    "removeElements": {
        +      "description": "createCanvase() 또는 createGraphics()로 생성된 캔버스와 그래픽을 제외하고, p5로 생성된 모든 요소를 제거합니다. 이벤트 핸들러 역시 제거되며, 요소가 DOM에서 제거됩니다.",
        +      "params": "",
        +      "returns": ""
        +    },
        +    "changed": {
        +      "description": ".changed() 함수는 요소값이 변경될 때 호출됩니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        +      "params": ["함수|불리언: 요소값이 변경될 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        +      "returns": ""
        +    },
        +    "input": {
        +      "description": ".input() 함수는 요소가 사용자 입력을 감지할 때 호출됩니다. 입력 이벤트는 키 또는 슬라이더 요소의 변경을 감지합니다. 특정 요소의 이벤트 리스너와 연결하는 데에 사용됩니다.",
        +      "params": ["함수|불리언: 요소가 사용자 입력을 감지할 때 발생하는 함수. 거짓(false)이 전달되면 이전 실행 함수는 더이상 실행 불가"],
        +      "returns": ""
        +    },
        +    "createDiv": {
        +      "description": "주어진 내부 HTML을 사용하여 DOM에 <div></div> 요소를 생성합니다.",
        +      "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createP": {
        +      "description": "주어진 내부 HTML을 사용하여 DOM에 <p></p> 요소를 생성합니다. 문단형 텍스트 작성시 사용됩니다.",
        +      "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createSpan": {
        +      "description": "주어진 내부 HTML을 사용하여 DOM에 <span></span> 요소를 생성합니다.",
        +      "params": ["문자열: 요소를 생성한 내부 HTML (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createImg": {
        +      "description": "주어진 src와 대체 텍스트(alt text)를 사용하여 DOM에 <img> 요소를 생성합니다.",
        +      "params": ["문자열: 이미지의 src 또는 url 경로",
        +                "문자열: 이미지가 로드되지 않을 경우 사용할 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Attributes'>대체 텍스트</a>. 빈 문자열(\" \")로 이미지 숨기기 가능",
        +                "문자열: img 요소의 <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin'>교차 출처 속성(crossOrigin property)</a>. '익명(anonymous)' 또는 '사용 자격 증명(use-credentials)'을 통해 교차 출처 권한이 있는 이미지를 검색하세요. 이는 캔버스에 이미지를 사용하기 위함이며, 빈 문자열(\" \")이 전달된 경우 교차 출처 리소스 공유(CORS)는 사용되지 않습니다.",
        +                "gkatn: 인수로 지정된 p5.Element가 이미지 데이터를 불러왔을 때 호출되는 콜백 함수 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createA": {
        +      "description": "DOM에 하이퍼링크를 포함한 <a></a> 요소를 생성합니다.",
        +      "params": ["문자열: 링크될 페이지 url",
        +                "문자열: 화면에 보여질 링크 요소의 내부 HTML",
        +                "문자열: 새로운 링크가 보여질 대상, _blank, _self, _parent, _top 중 지정 가능 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createSlider": {
        +      "description": "DOM에 슬라이더<input></input> 요소를 생성합니다. .size() 함수로 슬라이더의 길이를 설정합니다.",
        +      "params": ["숫자: 슬라이더의 최소값",
        +                "숫자: 슬라이더의 최대값",
        +                "숫자: 슬라이더의 기본값(선택 사항)",
        +                "숫자: 슬라이더의 단위당 이동 크기(이동 크기가 0으로 지정된 경우, 슬라이더는 최소값과 최대값 사이를 부드럽게 이동합니다.)(선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createButton": {
        +      "description": "DOM에 <button></button> 요소를 생성합니다. .size() 함수로 버튼의 크기를 설정합니다. .mousePressed() 함수로 버튼이 클릭됐을 때의 행동을 지정합니다.",
        +      "params": ["문자열: 버튼 위에 나타나는 레이블",
        +                "문자열: 버튼값 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createCheckbox": {
        +      "description": "DOM에 체크박스<input></input> 요소를 생성합니다. .checked() 함수를 통해 체크되었는지의 여부를 반환합니다.",
        +      "params": ["문자열: 체크박스 위에 나타나는 레이블 (선택 사항)",
        +                "불리언: 체크박스의 값: 체크는 참(true), 체크 해제는 거짓(false) (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createSelect": {
        +      "description": "DOM에 드롭다운 메뉴<select></select> 요소를 생성합니다. 이미 생성된 셀렉트 박스(select box)를 선택할 경우, p5.Element에 select-box 메소드를 지정하는 데에도 쓰입니다. 셀렉트 박스 생성 후, .option() 메소드로 선택지(option)를 설정할 수 있습니다. .selected() 메소드는 p5.Element 인스턴스인 현재 드롭다운 요소를 반환합니다. .selected() 메소드는 특정 선택지를 최초 페이지 로드시의 기본값으로서 설정할 수 있습니다. .disable() 메소드는 특정 선택지를 비활성화하고, 별도로 지정된 인수가 없는 경우엔 전체 드롭다운 요소를 비활성화 상태로 표시합니다.",
        +      "params": ["불리언: 드롭다운이 여러 개의 선택지를 제공할 경우 참(true) (선택 사항)",
        +                "객체: DOM 셀렉트 요소"],
        +      "returns": "p5.Element"
        +    },
        +    "createRadio": {
        +      "description": "DOM에 라디오 버튼<input></input> 요소를 생성합니다. 라디오 버튼 생성 후, .option() 메소드로 옵션을 설정할 수 있습니다. .value() 메소드는 현재 선택된 옵션을 반환합니다.",
        +      "params": ["문자열: 생성된 div와 input field 각각의 id 및 이름 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createColorPicker": {
        +      "description": "DOM에 색상 입력을 위한 색상 추출(colorPicker) 요소를 생성합니다. .value() 메소드는 색상의 헥사(Hex) 문자열(#rrggbb)을 반환합니다. .color() 메소드는 현재 선택된 색상의 p5.Color 객체를 반환합니다.",
        +      "params": ["문자열|p5.Color: 요소의 색상 기본값 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createInput": {
        +      "description": "DOM에 텍스트 입력을 위한 <input></input> 요소를 생성합니다. .size() 함수로 상자의 크기를 설정합니다.",
        +      "params": ["문자열: 입력 상자의 기본값 (선택 사항)",
        +                "문자열: 텍스트 유형 (예: text, password 등) 기본값은 text (선택 사항)"],
        +      "returns": "p5.Element: 생성된 노드를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createFileInput": {
        +      "description": "'파일(file)' 유형의 DOM에 <input></input> 요소를 생성합니다. 스케치에 사용할 로컬 파일을 선택할 수 있게 됩니다.",
        +      "params": ["함수: 파일이 로드될 때의 콜백 함수 (선택 사항)",
        +                "문자열: 여러 파일 선택 허용 (선택 사항)"],
        +      "returns": "p5.Element: 생성된 DOM 요소를 담고있는 p5.Element에 대한 포인터"
        +    },
        +    "createVideo": {
        +      "description": "DOM에 간단한 오디오/비디오 재생을 위한 HTML5 <video> 요소를 생성합니다. 화면에 나타나기가 기본값이며, .hide()로 숨길 수 있습니다. video() 함수를 통해 캔버스에 그릴 수 있습니다. 1번째 매개 변수는 비디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 비디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        +      "params": ["문자열|문자열 배열[]: 비디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        +                "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        +      "returns": "p5.MediaElement: 비디오 p5.Element에 대한 포인터"
        +    },
        +    "createAudio": {
        +      "description": "DOM에 간단한 오디오 재생을 위한 HTML5 <audio> 요소를 생성합니다. 1번째 매개 변수는 오디오 파일에 대한 단일 문자열 경로이거나, 또는 동일한 오디오 파일이 여러 개의 형식을 갖는 경우, 문자열 경로들의 배열로 지정됩니다. 특히, 다양한 파일 형식을 지정하여 여러 종류의 브라우저에서 재생될 수 있도록 하는 데에 용이합니다. 지원되는 파일 형식에 대한 자세한 내용은 <a href = 'https://developer.mozilla.org/en-US/docs/Web/Media/Formats'>이 페이지</a>를 참고하세요. ",
        +      "params": ["문자열|문자열 배열[]: 오디오 파일 경로, 또는 경로들의 배열(여러 종류의 브라우저 지원)",
        +                "함수: 브라우저의 미디어 재생가능 상태를 뜻하는, 'canplaythrough' 이벤트 발생시에 호출되는 함수. 추가 버퍼링 없이도, 미디어를 끝까지 재생할 수 있는 충분한 데이터가 로드된 것으로 평가. (선택 사항)"],
        +      "returns": "p5.MediaElement: 오디오 p5.Element에 대한 포인터"
        +    },
        +    "VIDEO": {
        +      "description": "",
        +      "params": [""],
        +      "returns": ""
        +    },
        +    "AUDIO": {
        +      "description": "",
        +      "params": [""],
        +      "returns": ""
        +    },
        +    "createCapture": {
        +      "description": "웹캠의 오디오/비디오 피드를 담는 <video> 요소를 생성합니다. 이 요소는 캔버스와는 별개로 작동합니다. '화면에 나타내기'가 기본값으로 주어지며, .hide()를 사용하여 화면으로부터 숨길 수 있습니다. image() 함수를 사용하여 피드를 캔버스에 그릴 수 있습니다. loadedmetadata 속성을 사용하여 요소가 완전히 로드된 시점을 감지할 수 있습니다. (2번째 예제 참고)<br><br> 피드의 구체적인 속성은 제약 조건(Constraints) 객체를 전달할 수 있습니다. 속성 및 제약 조건 객체와 관련해서는 <a href = 'https://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'>W3C 사양</a>을 참고하세요. 모든 브라우저가 이 기능을 지원하지 않는 점에 유의하세요.<br><br>보안 정보: 최신 브라우저 보안 사양은 createCapture() 이면의 getUserMedia() 메소드가 로컬 또는 HTTPS에서 코드 실행시에만 작동할 것을 요구합니다. 자세한 사항은 <a href = 'https://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>여기</a>와 <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>여기</a>서 확인하세요. ",
        +      "params": ["문자열|상수|객체: 캡처 유형, VIDEO 또는 AUDIO 중 하나로 지정 가능. 별도의 매개 변수가 지정되지 않을 경우 기본값으로 둘 다 또는 제약 조건 객체",
        +                "함수: 스트림 로드 완료 후 1번 호출되는 함수 (선택 사항)"],
        +      "returns": ""
        +    },
        +    "createElement": {
        +      "description": "지정된 콘텐츠를 지닌 DOM에 태그된 요소를 생성합니다.",
        +      "params": ["문자열: 새로운 요소의 태그",
        +                "문자열: 요소 안에 삽입될 HTML 콘텐츠 (선택 사항)"],
        +      "returns": ""
        +    },
        +    "p5.MediaElement": {
        +      "description": "오디오/비디오 처리를 위해 p5.Element를 확장합니다. p5.Element의 메소드 뿐 아니라, 미디어 제어를 위한 메소드도 포함합니다. p5.MediaElements는 직접 호출되지 않지만, createVideo, createAudio, CreateCapture 호출을 통해 생성됩니다.",
        +      "params": ["문자열: 래핑된 DOM 노드"],
        +      "fields": ["미디어 요소 소스 경로"],
        +      "methods": ["HTML5 미디어 요소를 재생합니다.",
        +                "HTML5 미디어 요소를 중지합니다. (현재 시간을 0으로 설정)",
        +                "HTML5 미디어 요소를 일시정지합니다.",
        +                "HTML5 미디어 요소의 반복을 참(true)로 설정하고, 재생 시작합니다.",
        +                "HTML5 미디어 요소의 반복을 거짓(false)으로 설정합니다. 종료 시점에 도달하면 요소가 중지합니다.",
        +                "HTML5 미디어 요소 자동재생 여부 설정",
        +                "HTML5 미디어 요소의 볼륨을 설정합니다. 별도로 지정한 인수가 없으면, 현재 볼륨을 반환합니다.",
        +                "별도로 지정한 인수가 없으면, 요소의 현재 재생 속도를 반환하빈다. 속도 매개 변수는 2.0일 때 2배속으로, 0.5일 때 0.5배속으로, -1일 때 정상 속도로 역재생합니다. (모든 브라우저가 역재생을 지원하지 않으며, 일부 지원 브라우저에서도 부드럽게 재생되지 않을 수 있습니다.)",
        +                "별도로 지정한 인수가 없을 경우, 요소의 현재 시간을 반환합니다. 인수가 지정될 경우, 요소의 현재 시간이 해당 인수로 설정됩니다.",
        +                "HTML5 미디어 요소의 지속 시간을 반환합니다.",
        +                "오디오/비디오 요소가 종료 시점에 도달할 때 호출할 이벤트를 예약합니다. 요소가 반복하는 경우 호출되지 않습니다. 요소는 oneded 콜백에 인수로 전달됩니다.",
        +                "요소가 출력한 오디오를 특정 audioNode나 p5.sound 객체로 보냅니다. 요소가 없는 경우, p5의 마스터 출력에 연결합니다. 모든 연결은 .disconnect() 메소드로 제거할 수 있습니다. p5.sound.js 애드온 라이브러리로 이러한 방법을 사용할 수 있습니다.",
        +                "마스터 출력을 비롯하여 모든 웹 오디오 라우팅을 분리합니다. 사용 예: 오디오 효과를 통해 출력을 다시 라우팅할 때",
        +                "웹 브라우저가 지정한 기본 미디어 요소(MediaElement) 컨트롤을 나타냅니다.",
        +                "기본 미디어 요소(MediaElement) 컨트롤을 숨깁니다.",
        +                "오디오/비디오와 같은 미디어 요소(MediaElement)가 재생 큐 지점에 도달할 때 발생할 이벤트를 예약합니다. 콜백 함수, 콜백이 발생할 시간(초 단위), 콜백에 대한 선택적 매개 변수를 허용합니다. 1번째 매개 변수는 시간(time)을, 2번째 매개 변수는 param을 콜백 함수에 전달합니다.",
        +                "ID를 기반으로 콜백을 제거합니다. ID는 addCue 메소드로 반환됩니다.",
        +                "addCue 메소드로 예약된 모든 콜백을 제거합니다."],
        +      "returns": ""
        +    },
        +    "p5.File": {
        +      "description": "파일을 위한 기본 클래스입니다. Element.drop()과 createFileInput()에 사용됩니다.",
        +      "params": "파일: 래핑된 파일",
        +      "fields": ["기본 파일 객체. 모든 일반 File 메소드를 호출할 수 있습니다.",
        +                "파일 유형 (이미지, 텍스트 등)",
        +                "파일 하위 유형 (주로 jpg, png, xml 등의 파일 확장자)",
        +                "파일명",
        +                "파일 크기",
        +                "이미지 데이터를 담는 URL 문자열"],
        +      "returns": ""
        +    },
        +      
        +    "p5.Graphics": {
        +      "description": "렌더러을 둘러싼 얇은 래퍼(wrapper)로, 그래픽 버퍼 객체를 생성하는 데에 사용합니다. 화면 밖 그래픽 버퍼에 그리려면 이 클래스를 사용하세요. 2개의 매개 변수는 너비와 높이를 픽셀 단위로 지정합니다. 이 클래스의 필드와 메소드는 확장성이 있으나, p5를 위한 일반적인 드로잉 API를 반영합니다.<br>p5.Element를 확장합니다.",
        +      "params": ["숫자: 너비값",
        +                "숫자: 높이값",
        +                "상수: 사용할 렌더러, P2D 또는 WEBGL",
        +                "P5: p5 인스턴스에 대한 포인터 (선택 사항)",
        +      ""],
        +      "methods": ["그래픽 버퍼 객체로 자동 재설정되지 않은 특정값들(예: 레퍼런스 중 변형(Transform) 또는 라이트(Light) 항목에 해당하는 함수들로서 지정된 값들). 이 메소드를 draw() 함수 안에서 호출하면, 기본 캔버스의 행위를 복제합니다.",
        +                "페이지에서 그래픽 객체를 제거하고 이 객체에 연결된 모든 소스들을 연결 해제합니다."]
        +    },
        +    "createCanvas": {
               "description": "캔버스를 생성하고 픽셀 단위로 크기를 설정합니다. createCanvas()는 setup() 함수 시작시 단 한 번만 실행되어야 합니다. createCanvas()를 한 번 이상 호출하면 스케치가 예기치 못한 반응을 보일 수 있습니다. 두 개 이상의 캔버스가 필요하다면 createGraphics()를 이용하세요.<br><br>설정된 캔버스 사이즈는 시스템 변수인 너비(width)와 높이(height)에 각각 저장됩니다. createCanvas() 함수를 생략하면, 스케치의 크기는 기본값인 100x100 픽셀로 지정됩니다.<br><br>캔버스의 위치 지정 방법을 알고싶다면, <a href = 'https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>캔버스 위치 지정하기</a> 위키 페이지를 참고하세요.",
               "params": ["숫자: 캔버스의 너비값",
               "숫자: 캔버스의 높이값",
        @@ -1005,8 +957,8 @@
               "returns": "p5.Graphics: 화면 밖 그래픽 버퍼"
             },
             "blendMode": {
        -      "description": "사용자가 지정한 모드에 따라 디스플레이 화면상의 픽셀들을 혼합합니다. 소스 픽셀 (A)를 디스플레이 화면 (B)상에 있는 픽셀과 혼합하기 위해 다음 모드를 선택할 수 있습니다:<br><ul><li><code>BLEND</code> - 색상 선형 보간:C = (A)\*계수 + (B). 기본 혼합 모드입니다.</li><li><code>ADD</code> - (A)와 (B)의 합</li><li><code>DARKEST</code> - 가장 어두운 색상만 혼합됩니다:C = min(A*계수, B).</li><li><code>LIGHTEST </code> - 가장 밝은 색상만 혼합됩니다.:C = max(A*계수, B).</li><li><code>DIFFERENCE</code> - 기본 이미지에서 색상값을 뺄셈합니다.</li><li><code>EXCLUSION</code> - DIFFERENCE와 유사하지만 덜 극적입니다.</li><li><code>MULTIPLY</code> - 색상을 곱하는 것으로, 결과값은 좀 더 어둡습니다.</li><li><code>SCREEN</code> - MULTIPLY와 반대로 색상의 반전된 값을 사용합니다.</li><li><code>REPLACE</code> - 픽셀이 다른 픽셀을 완전히 대체하며 알파값(투명도)를 사용하지 않습니다.</li><li><code>OVERLAY</code> - MULTIPLY와 SCREEN의 혼합으로, 어두운 값을 곱하고 밝은 값의 반전된 값을 사용합니다. (2D)</li><li><code>HARD_LIGHT</code> - 회색값이 50%보다 높으면 SCREEN로, 낮으면 MULTIPLY로 처리합니다. (2D)</li><li><code>SOFT_LIGHT</code> - DARKEST와 LIGHTEST 혼합으로, OVERLAY처럼 작동하나 덜 강합니다. (2D)</li><li><code>DODGE</code> - 밝은 색조를 더 밝게 처리하고 대비를 높이며, 어두운 영역은 무시합니다. (2D)</li><li><code>BURN</code> - 어두운 영역이 적용되어 대비가 증가하고 밝기는 무시됩니다. (2D)</li><li><code>SUBTRACT</code> - (A)와 (B)의 나머지(3D)</li></ul><br><br>(2D)는 2D 렌더러에서만 작동하는 혼합 모드를 뜻합니다.<br>(3D)는 WEBGL 렌더러에서만 작동하는 혼합 모드를 뜻합니다.",
        -      "params": ["상수:캔버스에 설정되는 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD, REMOVE 또는 SUBTRACT 중 하나"]
        +      "description": "사용자가 지정한 모드에 따라 디스플레이 화면상의 픽셀들을 혼합합니다. 소스 픽셀 (A)를 디스플레이 화면 (B)상에 있는 픽셀과 혼합하기 위해 다음 모드를 선택할 수 있습니다:<br><ul><li><code>BLEND</code> - 색상 선형 보간:C = (A)*계수 + (B). 기본 혼합 모드입니다.</li><li><code>ADD</code> - (A)와 (B)의 합</li><li><code>DARKEST</code> - 가장 어두운 색상만 혼합됩니다:C = min(A*계수, B).</li><li><code>LIGHTEST </code> - 가장 밝은 색상만 혼합됩니다.:C = max(A*계수, B).</li><li><code>DIFFERENCE</code> - 기본 이미지에서 색상값을 뺄셈합니다.</li><li><code>EXCLUSION</code> - DIFFERENCE와 유사하지만 덜 극적입니다.</li><li><code>MULTIPLY</code> - 색상을 곱하는 것으로, 결과값은 좀 더 어둡습니다.</li><li><code>SCREEN</code> - MULTIPLY와 반대로 색상의 반전된 값을 사용합니다.</li><li><code>REPLACE</code> - 픽셀이 다른 픽셀을 완전히 대체하며 알파값(투명도)를 사용하지 않습니다.</li><li><code>OVERLAY</code> - MULTIPLY와 SCREEN의 혼합으로, 어두운 값을 곱하고 밝은 값의 반전된 값을 사용합니다. (2D)</li><li><code>HARD_LIGHT</code> - 회색값이 50%보다 높으면 SCREEN로, 낮으면 MULTIPLY로 처리합니다. (2D)</li><li><code>SOFT_LIGHT</code> - DARKEST와 LIGHTEST 혼합으로, OVERLAY처럼 작동하나 덜 강합니다. (2D)</li><li><code>DODGE</code> - 밝은 색조를 더 밝게 처리하고 대비를 높이며, 어두운 영역은 무시합니다. (2D)</li><li><code>BURN</code> - 어두운 영역이 적용되어 대비가 증가하고 밝기는 무시됩니다. (2D)</li><li><code>SUBTRACT</code> - (A)와 (B)의 나머지(3D)</li></ul><br><br>(2D)는 2D 렌더러에서만 작동하는 혼합 모드를 뜻합니다.<br>(3D)는 WEBGL 렌더러에서만 작동하는 혼합 모드를 뜻합니다.",
        +      "params": ["상수:캔버스에 설정되는 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD, REMOVE 또는 SUBTRACT 중 하나"],
               "returns": ""
             },
             "drawingContext": {
        @@ -1014,7 +966,7 @@
                 "params": ["",
                 ""],
                 "returns": "TODO"
        -      },
        +    },
         
             "setAttributes": {
               "description": "WebGL 드로잉 컨텍스트의 속성을 설정하여 WebGL 렌더러가 화면과 성능을 미세 조정할 수 있도록 합니다.<br><br> WebGL 캔버스를 생성한 후에 이 함수를 호출하면 드로잉 컨텍스트가 다시 초기화되는 점에 유의하세요. <br><br>객체가 매개 변수로 전달될 경우, 객체에 선언되지 않은 모든 속성은 기본값으로 처리됩니다.<br><br>사용한 가능한 속성은 다음과 같습니다:<br>alpha - 캔버스에 알파 버퍼가 있는지의 여부를 나타냅니다. 기본값은 참(true)입니다.<br>stencil - 드로잉 버퍼에 8비트 이상의 스텐실 버퍼가 있는지 여부를 나타냅니다.<br>antialias - 안티앨리어싱 기본값을 수행할지 여부를 나타냅니다. (Safari에서는 참)<br>premultipliedAlpha -   드로잉 버퍼에 포함된 색상이 미리 곱해진 알파 기본값을 포함하는 지의 여부에 대해, 페이지 컴포지터가 거짓(false)으로 가정하고 있음을 나타냅니다.<br>perPixelLighting - 참(true)이라면, 픽셀당 라이팅(per-pixel Lighting)이 라이팅 셰이더에 사용됩니다. 그렇지 않다면, 꼭지점당 라이팅(per-vertex lighting)이 사용됩니다. 기본값은 참입니다.",
        @@ -1023,135 +975,124 @@
                          "객체: 주요값들의 쌍을 갖는 객체"]
             },
         
        +    "let": {
        +      "description": "새로운 변수를 생성하고 그 이름을 지정합니다. 변수는 값을 담는 컨테이너입니다.<br>let으로 선언된 변수는 블록 단위의 적용 범위를 갖습니다. 즉, 변수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let'>MDN Entry</a>에서 발췌: 블록 범위의 지역 변수를 선언하고, 선택적으로 그 값을 초기화합니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
               
        -
        -//Foundation
        -
        +    "const": {
        +      "description": "새로운 상수를 생성하고 그 이름을 지정합니다. 마치 let으로 생성된 변수처럼, const로 생성된 상수는 값을 담는 컨테이너입니다. 하지만, 상수는 한 번 산언된 다음 변경할 수 없습니다.<br>const로 선언된 상수는 블록 단위의 적용 범위를 갖습니다. 즉, 상수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다. 상수는 자신이 존재하고 있는 범위 내에서 재선언될 수 없습니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const'>MDN Entry</a>에서 발췌: 읽기만 가능한 상수를 선언합니다. const는 블록 단위로 적용되며, let으로 선언된 변수들과 유사합니다. 상수값은 재지정을 통해 변경될 수 없으며, 재선언될 수 없습니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "===": {
        +      "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 연산됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN Entry</a>에서 발췌: 이 연산자는 피연산자들이 동일한 값이 아니고/또는 동일한 유형이 아닐 때 참(true)을 반환합니다.<br>웹상의 몇몇 예제에서 피연산자 간의 비교를 위해 이중 등호(==)를 사용하는 것을 볼 수 있습니다. 이는 자바스크립트상의 완전 항등 연산자(===)에 해당하지 않으며, 두 피연산자의 값들을 비교하기에 앞서, 그 유형이 동일한지의 여부를 비교하게 됩니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    ">": {
        +      "description": "비교 연산자 > 는 왼쪽 값이 오른쪽 값보다 큰 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    ">=": {
        +      "description": "비교 연산자 >= 는 왼쪽 값이 오른쪽 값보다 크거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "<": {
        +      "description": "비교 연산자 < 는 왼쪽 값이 오른쪽 값보다 작은 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "<=": {
        +      "description": "비교 연산자 <= 는 왼쪽 값이 오른쪽 값보다 작거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "if-else": {
        +      "description": "if-else문으로 코드의 흐름을 제어할 수 있습니다.<br>'if' 바로 다음 괄호 안에 조건을 지정할 수 있으며, 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/truthy'>참(truthy)</a>으로 연산되면 뒤따른 중괄호 사이의 코드가 실행됩니다. 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Falsy'>거짓(falsy)</a>으로 연산되면 'else' 뒤에 오는 중괄호 사이의 코드가 대신 실행됩니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else'>MDN Entry</a>에서 발췌: 지정된 조건이 참일 경우, if문은 명령문을 실행합니다. 조건이 거짓이면 다른 명령문을 실행할 수 잇습니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "function": {
        +      "description": "새로운 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions'>함수(function)</a>를 생성하고 그 이름을 지정합니다. 함수란, 작업을 수행하는 일련의 명령문을 뜻합니다.<br> 선택적으로, 함수는 매개 변수를 가질 수 있습니다.<a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Parameter'>매개 변수(parameter)</a>란, 특정 함수에만 그 사용 범위가 지정된 변수를 뜻하며 함수 호출시 그 값을 지정할 수 있습니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function'>MDN Entry</a>에서 발췌: 사용자가 지정한 매개 변수를 사용하여 함수를 선언합니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "return": {
        +      "description": "함수가 반환할 값을 지정합니다. <br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return'>MDN Entry 발췌 함수(function) 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "string": {
        +      "description": "문자열(string)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 문자열은 일련의 텍스트 문자들을 뜻하며, 자바스크립트에서 문자열 값은 작은 따옴표나 큰따옴표로 묶여 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/string'>MDN Entry</a>에서 발췌: 문자열은 텍스트를 나타낼 때 사용하는 일련의 문자들입니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "number": {
        +      "description": "숫자(number)는 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 숫자는 정수 또는 10진수로 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry 발췌 숫자(number) 상세 설명</a>",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "object": {
        +      "description": "<a href = 'https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics'>MDN Entry 발췌 객체(object) 기초 설명</a>: 객체(object)는 데이터 그리고/또는 함수의 모음을 뜻합니다. 일반적으로 여러 개의 변수와 함수로 구성됩니다. 변수와 함수가 객체 안에 포함된 경우, 각각을 속성(property)과 메소드(method)라 부릅니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "class": {
        +      "description": "클래스(class)를 생성하고 그 이름을 지정합니다. 클래스는 객체(object) 생성을 위한 하나의 템플릿입니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry</a>에서 발췌: 클래스 선언을 통해 새로운 Class를 생성합니다. 이 때, 새로운 Class의 이름은 프로토타입 기반 상속을 통해 지정됩니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "for": {
        +      "description": "for문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'for 반복문(for loop)'은 괄호 속 3개의 다른 표현식들로 구성되며, 각각의 표현식은 모두 선택 사항입니다. 이 표현식들은 반복 실행(loop)의 횟수를 제어합니다. 1번째 표현식은 반복문의 초기 상태를 설정하는 명령문입니다. 2번째 표현식은 매 반복 실행에 앞서 조건 충족 여부를 확인합니다. 이 표현식이 거짓(false)를 반환하면 반복 실행이 종료됩니다. 3번째 표현식은 반복문의 가장 마지막 단계에 실행됩니다.<br><br>for 반복문의 본문(중괄호 사이의 영역)에 포함된 코드는 2번째와 3번째 표현식의 연산과정 사이에 실행됩니다.<br><br>여타 반복문과 마찬가지로, for 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. 앞서 설명된 2번째 표현식을 통해, for 반복문의 조건이 거짓으로 연산되는 시점을 정할 수 있습니다. for반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않으면, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for'>MDN Entry</a>에서 발췌: for 반복문은 조건이 거짓(false)으로 연산될 때까지 지정된 명령문을 실행합니다. 명령문을 실행한 후에는 조건 충족 여부를 다시 평가하여, 명령문이 최소 1번 실행되도록 합니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "while": {
        +      "description": "while문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'while 반복문(while loop)'을 사용하면, 소괄호 속 조건이 거짓(false)이 될 때까지 중괄호 속 본문의 코드가 반복적으로 실행됩니다. for 반복문과 달리, while 반복문은 그 본문 속 코드를 실행하기 앞서 조건 충족 여부를 먼저 확인합니다. 따라서, 최초 실행시 조건이 거짓일 경우, while문 속 본문과 명령문은 절대 실행되지 않습니다.<br><br>여타 반복문과 마찬가지로, while 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. while 반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않을 경우, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while'>MDN Entry</a>에서 발췌: while 반복문은 조건이 참(true)인 경우에 한해 지정된 명령문을 실행합니다. 명령문 실행에 앞서 조건 충족 여부가 평가됩니다.",
        +      "params": ["",
        +      ""],
        +      "returns": ""
        +    },
        +    "JSON": {
        +      "description": "",
        +      "methods": ["<a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify'>MDN Entry</a>에서 발췌: JSON.stringify() 메소드는 자바스크립트 객체나 값을 JSON 문자열로 변환합니다.",
        +      ""],
        +      "returns": ""
        +    },
        +    "console": {
        +      "description": "",
        +      "methods": ["브라우저의 웹 콘솔창에 메시지를 인쇄합니다. p5의 경우, print()와 console.log()를 모두 사용할 수 있습니다. 콘솔은 사용자의 브라우저에 따라 달라집니다. <a href = 'https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console'>Firefox</a>, <a href = 'https://developers.google.com/web/tools/chrome-devtools/open'>Chrome</a>, <a href = 'https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console'>Edge</a>, <a href = 'https://support.apple.com/en-ca/guide/safari/sfri20948/mac'>Safari</a>에서 콘솔을 여는 방법에 대한 링크는 다음과 같습니다. <a href ='https://editor.p5js.org/'>온라인 p5 에디터</a>의 경우, 콘솔창이 코드 에디터 하단에 임베드 되어있습니다. <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/Console/log'>MDN Entry</a>에서 발췌: 콘솔 메소드 log()는 웹 콘솔에 메시지를 출력합니다. 메시지는 단일 문열(선택적으로, 대체값과 함께)이거나 한 개 이상의 자바스크립트 객체일 수 있습니다.",
        +      ""],
        +      "returns": ""
        +    },
               
        -  "let": {
        -    "description": "새로운 변수를 생성하고 그 이름을 지정합니다. 변수는 값을 담는 컨테이너입니다.<br>let으로 선언된 변수는 블록 단위의 적용 범위를 갖습니다. 즉, 변수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let'>MDN Entry</a>에서 발췌: 블록 범위의 지역 변수를 선언하고, 선택적으로 그 값을 초기화합니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -    
        -  "const": {
        -    "description": "새로운 상수를 생성하고 그 이름을 지정합니다. 마치 let으로 생성된 변수처럼, const로 생성된 상수는 값을 담는 컨테이너입니다. 하지만, 상수는 한 번 산언된 다음 변경할 수 없습니다.<br>const로 선언된 상수는 블록 단위의 적용 범위를 갖습니다. 즉, 상수가 작성된 블록 내에서만 존재하고 사용될 수 있음을 뜻합니다. 상수는 자신이 존재하고 있는 범위 내에서 재선언될 수 없습니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const'>MDN Entry</a>에서 발췌: 읽기만 가능한 상수를 선언합니다. const는 블록 단위로 적용되며, let으로 선언된 변수들과 유사합니다. 상수값은 재지정을 통해 변경될 수 없으며, 재선언될 수 없습니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "===": {
        -    "description": "완전 항등 연산자 '===' 는 두 값이 같으면서 동시에 동일한 유형인지 여부를 확인합니다.<br>비교 표현식은 항상 불리언으로 연산됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN Entry</a>에서 발췌: 이 연산자는 피연산자들이 동일한 값이 아니고/또는 동일한 유형이 아닐 때 참(true)을 반환합니다.<br>웹상의 몇몇 예제에서 피연산자 간의 비교를 위해 이중 등호(==)를 사용하는 것을 볼 수 있습니다. 이는 자바스크립트상의 완전 항등 연산자(===)에 해당하지 않으며, 두 피연산자의 값들을 비교하기에 앞서, 그 유형이 동일한지의 여부를 비교하게 됩니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  ">": {
        -    "description": "비교 연산자 > 는 왼쪽 값이 오른쪽 값보다 큰 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  ">=": {
        -    "description": "비교 연산자 >= 는 왼쪽 값이 오른쪽 값보다 크거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "<": {
        -    "description": "비교 연산자 < 는 왼쪽 값이 오른쪽 값보다 작은 경우 참(true)으로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "<=": {
        -    "description": "비교 연산자 <= 는 왼쪽 값이 오른쪽 값보다 작거나 같은 경우 참(true)로 연산합니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators'>MDN 발췌 비교 연산자 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "if-else": {
        -    "description": "if-else문으로 코드의 흐름을 제어할 수 있습니다.<br>'if' 바로 다음 괄호 안에 조건을 지정할 수 있으며, 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/truthy'>참(truthy)</a>으로 연산되면 뒤따른 중괄호 사이의 코드가 실행됩니다. 조건이 <a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Falsy'>거짓(falsy)</a>으로 연산되면 'else' 뒤에 오는 중괄호 사이의 코드가 대신 실행됩니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else'>MDN Entry</a>에서 발췌: 지정된 조건이 참일 경우, if문은 명령문을 실행합니다. 조건이 거짓이면 다른 명령문을 실행할 수 잇습니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "function": {
        -    "description": "새로운 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions'>함수(function)</a>를 생성하고 그 이름을 지정합니다. 함수란, 작업을 수행하는 일련의 명령문을 뜻합니다.<br> 선택적으로, 함수는 매개 변수를 가질 수 있습니다.<a href = 'https://developer.mozilla.org/en-US/docs/Glossary/Parameter'>매개 변수(parameter)</a>란, 특정 함수에만 그 사용 범위가 지정된 변수를 뜻하며 함수 호출시 그 값을 지정할 수 있습니다.<br><br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function'>MDN Entry</a>에서 발췌: 사용자가 지정한 매개 변수를 사용하여 함수를 선언합니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "return": {
        -    "description": "함수가 반환할 값을 지정합니다. <br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return'>MDN Entry 발췌 함수(function) 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "boolean": {
        -    "description": "불리언(boolean)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 불리언은 참(true) 또는 거짓(false)으로 값을 나타냅니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type'>MDN Entry</a>에서 발췌: 불리언은 논리적 개체를 나타내며 참(true) 또는 거짓(false)이라는 두 개의 값만 갖습니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "string": {
        -    "description": "문자열(string)은 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 문자열은 일련의 텍스트 문자들을 뜻하며, 자바스크립트에서 문자열 값은 작은 따옴표나 큰따옴표로 묶여 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/string'>MDN Entry</a>에서 발췌: 문자열은 텍스트를 나타낼 때 사용하는 일련의 문자들입니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "number": {
        -    "description": "숫자(number)는 자바스크립트에서 지정한 7개의 <a href = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values'>기본 데이터 유형</a> 중 하나입니다. 숫자는 정수 또는 10진수로 표현됩니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry 발췌 숫자(number) 상세 설명</a>",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "object": {
        -    "description": "<a href = 'https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics'>MDN Entry 발췌 객체(object) 기초 설명</a>: 객체(object)는 데이터 그리고/또는 함수의 모음을 뜻합니다. 일반적으로 여러 개의 변수와 함수로 구성됩니다. 변수와 함수가 객체 안에 포함된 경우, 각각을 속성(property)과 메소드(method)라 부릅니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "class": {
        -    "description": "클래스(class)를 생성하고 그 이름을 지정합니다. 클래스는 객체(object) 생성을 위한 하나의 템플릿입니다.<br><a href = 'https://developer.mozilla.org/en-US/docs/Glossary/number'>MDN Entry</a>에서 발췌: 클래스 선언을 통해 새로운 Class를 생성합니다. 이 때, 새로운 Class의 이름은 프로토타입 기반 상속을 통해 지정됩니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "for": {
        -    "description": "for문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'for 반복문(for loop)'은 괄호 속 3개의 다른 표현식들로 구성되며, 각각의 표현식은 모두 선택 사항입니다. 이 표현식들은 반복 실행(loop)의 횟수를 제어합니다. 1번째 표현식은 반복문의 초기 상태를 설정하는 명령문입니다. 2번째 표현식은 매 반복 실행에 앞서 조건 충족 여부를 확인합니다. 이 표현식이 거짓(false)를 반환하면 반복 실행이 종료됩니다. 3번째 표현식은 반복문의 가장 마지막 단계에 실행됩니다.<br><br>for 반복문의 본문(중괄호 사이의 영역)에 포함된 코드는 2번째와 3번째 표현식의 연산과정 사이에 실행됩니다.<br><br>여타 반복문과 마찬가지로, for 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. 앞서 설명된 2번째 표현식을 통해, for 반복문의 조건이 거짓으로 연산되는 시점을 정할 수 있습니다. for반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않으면, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for'>MDN Entry</a>에서 발췌: for 반복문은 조건이 거짓(false)으로 연산될 때까지 지정된 명령문을 실행합니다. 명령문을 실행한 후에는 조건 충족 여부를 다시 평가하여, 명령문이 최소 1번 실행되도록 합니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "while": {
        -    "description": "while문을 사용하여 특정 섹션의 코드에 대한 반복문(loop)을 만듭니다.<br><br>'while 반복문(while loop)'을 사용하면, 소괄호 속 조건이 거짓(false)이 될 때까지 중괄호 속 본문의 코드가 반복적으로 실행됩니다. for 반복문과 달리, while 반복문은 그 본문 속 코드를 실행하기 앞서 조건 충족 여부를 먼저 확인합니다. 따라서, 최초 실행시 조건이 거짓일 경우, while문 속 본문과 명령문은 절대 실행되지 않습니다.<br><br>여타 반복문과 마찬가지로, while 반복문 역시 반복이 '종료'되는 시점이나, 조건을 더이상 충족하지 않아 거짓(false)으로 연산되는 시점을 명시해야 합니다. while 반복문의 조건이 언젠가 거짓으로 처리되는 시점을 지정함으로써, 해당 반복문이 무한으로 실행되지 않도록 처리하기 위함입니다. 그렇지 않을 경우, 브라우저가 중단될 수 있습니다.<br><br><a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while'>MDN Entry</a>에서 발췌: while 반복문은 조건이 참(true)인 경우에 한해 지정된 명령문을 실행합니다. 명령문 실행에 앞서 조건 충족 여부가 평가됩니다.",
        -    "params": ["",
        -    ""],
        -    "returns": ""
        -  },
        -  "JSON": {
        -    "description": "",
        -    "methods": ["<a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify'>MDN Entry</a>에서 발췌: JSON.stringify() 메소드는 자바스크립트 객체나 값을 JSON 문자열로 변환합니다.",
        -    ""],
        -    "returns": ""
        -  },
        -  "console": {
        -    "description": "",
        -    "methods": ["브라우저의 웹 콘솔창에 메시지를 인쇄합니다. p5의 경우, print()와 console.log()를 모두 사용할 수 있습니다. 콘솔은 사용자의 브라우저에 따라 달라집니다. <a href = 'https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console'>Firefox</a>, <a href = 'https://developers.google.com/web/tools/chrome-devtools/open'>Chrome</a>, <a href = 'https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console'>Edge</a>, <a href = 'https://support.apple.com/en-ca/guide/safari/sfri20948/mac'>Safari</a>에서 콘솔을 여는 방법에 대한 링크는 다음과 같습니다. <a href ='https://editor.p5js.org/'>온라인 p5 에디터</a>의 경우, 콘솔창이 코드 에디터 하단에 임베드 되어있습니다. <a href = 'https://developer.mozilla.org/en-US/docs/Web/API/Console/log'>MDN Entry</a>에서 발췌: 콘솔 메소드 log()는 웹 콘솔에 메시지를 출력합니다. 메시지는 단일 문열(선택적으로, 대체값과 함께)이거나 한 개 이상의 자바스크립트 객체일 수 있습니다.",
        -    ""],
        -    "returns": ""
        -  },
        -    
             "applyMatrix": {
               "description": "현재 행렬(matrix)에 매개 변수로 지정된 행렬을 곱합니다. 평행 이동과 같은 연속 이동(translate), 크기 조정(scale), 전단(shear), 회전(rotate)을 한 번에 수행할 수 있습니다. <a href='https://ko.wikipedia.org/wiki/%EB%B3%80%ED%99%98%ED%96%89%EB%A0%AC'>변환행렬 위키피디아</a>에서 더 많은 정보를 확인할 수 있습니다.<br><br>이 때, 인수들은 <a href='https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform'>WHATWG 사양</a>에 따라 그 이름이 지정되며, 다음과 같은 형식의 변환 행렬에 상응합니다:<blockquote><p><img style='max-width: 150px' src='assets/transformation-matrix.png' alt='applyMatrix() 함수 호출시 사용되는 변환 행렬'></p></blockquote>",
               "params": ["숫자: 곱할 2x3 행렬 정의",
        -                 "숫자: 곱할 2x3 행렬 정의",
        -                 "숫자: 곱할 2x3 행렬 정의",
        -                 "숫자: 곱할 2x3 행렬 정의",
        -                 "숫자: 곱할 2x3 행렬 정의",
        -                 "숫자: 곱할 2x3 행렬 정의"],
        +                  "숫자: 곱할 2x3 행렬 정의",
        +                  "숫자: 곱할 2x3 행렬 정의",
        +                  "숫자: 곱할 2x3 행렬 정의",
        +                  "숫자: 곱할 2x3 행렬 정의",
        +                  "숫자: 곱할 2x3 행렬 정의"],
               "returns": ""
             },
             "resetMatrix": {
        @@ -1161,7 +1102,7 @@
             "rotate": {
               "description": "사용자가 지정한 각도 매개 변수에 따라 도형을 회전합니다. 이 함수는 angleMode() 함수의 영향을 받으며, 괄호 안에 RADIANS 또는 DEGREES를 입력하여  각도가 해석되는 방식을 지정할 수 있습니다.<br><br>객체는 항상 원점에 대한 상대적 위치를 중심으로 회전하며, 양수를 입력할 경우 시계 방향으로 객체를 회전합니다. 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용됩니다. 예를 들어, rotate(HALF_PI)를 호출한 뒤 rotate(HALF_PI)를 호출하면, 결과적으로 rotate(PI)와 동일한 효과를 갖습니다. 모든 변형은 draw() 함수가 다시 시작하는 시점에 리셋됩니다.<br><br>좀 더 기술적으로 설명하자면, rotate() 함수는 현재 변환 행렬에 회전 행렬을 곱하는 셈입니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
               "params": ["숫자: 현재 angleMode의 매개 변수인 RADIANS(부채각) 또는 DEGREES(도)의 설정 사항에 따른 회전각",
        -                 "p5.Vector|숫자 배열[]: (3D의 경우,) 회전축 (선택 사항)"],
        +                  "p5.Vector|숫자 배열[]: (3D의 경우,) 회전축 (선택 사항)"],
               "returns": ""
             },
             "rotateX": {
        @@ -1182,9 +1123,9 @@
             "scale": {
               "description": "꼭지점을 확장하거나 축소하여 도형의 크기를 키우거나 줄입니다. 객체의 크기는 언제나 좌표계에 대한 상대적 원점을 기준으로 조정됩니다. 크기값들은 10진수 백분율로 지정됩니다. 예를 들어, scale(2.0) 함수를 호출하면 도형의 크기를 200% 증가시킵니다.<br><br> 이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용됩니다. 예를 들어, scale(2.0)을 호출한 뒤 scale(1.5)를 호출하면, 결과적으로 scale(3.0)과 동일한 효과를 갖습니다. 모든 변형은 draw() 함수가 다시 시작하는 시점에 리셋됩니다.<br><br>매개 변수 z는 오직 WebGL 모드에서만 사용 가능합니다. 이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
               "params": ["숫자|p5.Vector|숫자 배열[]:객체 크기를 조정하는 백분율, 또는 여러 인수를 지정할 경우 x축에서의 객체 크기 배율을 조정하는 백분율",
        -                 "숫자: y축에서의 객체 크기를 조정하는 백분율 (선택 사항)",
        -                 "숫자: z축에서의 객체 크기를 조정하는 백분율(WebGL 모드용)(선택 사항)",
        -                 "p5.Vector|숫자 배열[]: 축을 기준으로 객체의 크기 조정"],
        +                  "숫자: y축에서의 객체 크기를 조정하는 백분율 (선택 사항)",
        +                  "숫자: z축에서의 객체 크기를 조정하는 백분율(WebGL 모드용)(선택 사항)",
        +                  "p5.Vector|숫자 배열[]: 축을 기준으로 객체의 크기 조정"],
               "returns": ""
             },
             "shearX": {
        @@ -1200,14 +1141,12 @@
             "translate": {
               "description": "디스플레이 화면 내에서 객체를 이동시킬 양을 지정합니다. 매개 변수 x는 좌/우 이동을, 매개 변수 y는 상/하 이동을 지정합니다.<br><br>이러한 변형(transformation) 함수는 그것이 호출된 뒤 후속적으로 호출된 모든 변형 함수들에 적용되어, 그 효과들이 축적됩니다. 예를 들어, translate(50, 0)를 호출한 뒤 translate(20, 0)를 또 호출하면, 결과적으로 translate(70, 0)와 동일한 효과를 갖습니다. draw() 함수 내에서 translate()을 호출하면, 반복 실행이 다시 시작되는 시점에 모든 변형 내용이 리셋됩니다.<br><br>이 함수는 push()와 pop() 함수를 통해 추가적으로 제어 가능합니다.",
               "params": ["숫자: 좌/우 이동",
        -                 "숫자: 상/하 이동",
        -                 "숫자: 앞/뒤 이동(WebGL 모드용)",
        -                 "p5.Vector: 이동시킬 벡터"],
        +                  "숫자: 상/하 이동",
        +                  "숫자: 앞/뒤 이동(WebGL 모드용)",
        +                  "p5.Vector: 이동시킬 벡터"],
               "returns": ""
             },
         
        -// Data > Array Functions
        -    
             "storeItem":{
                 "description":"로컬 저장소에 값을 키 이름(key name)으로 저장합니다. 로컬 저장소는 브라우저에 저장되며, 브라우징 세션과 페이지를 다시 불러오는 사이에 유지됩니다. 키(key)는 변수명과 동일하게 지정될 수 있으나, 반드시 그럴 필요는 없습니다. 저장된 항목(item)을 가져오려면 <a href = 'https://p5js.org/reference/#/p5/getItem'>getItem</a>을 참조하세요.<br><br>비밀번호나 개인 정보와같이 민감한 데이터는 로컬 저장소에 저장되면 안됩니다.",
                 "params":["문자열:",
        @@ -1230,13 +1169,10 @@
                 "returns":""
             },
               
        -      
        -// Data > Dictionary
        -      
             "createStringDict":{
                 "description":"키-값(key-value) 쌍 또는 사용자가 지정한 객체를 사용하여 p5.StringDict의 새로운 인스턴스를 생성합니다.",
                 "params":["문자열:",
        -                  "문자열:"
        +                  "문자열:",
                           "객체: 객체"],
                 "returns":"p5.StringDict:"
             },
        @@ -1244,8 +1180,8 @@
                 "description":"키-값(key-value) 쌍 또는 사용자가 지정한 객체를 사용하여 p5.NumberDict의 새로운 인스턴스를 생성합니다.",
                 "params":["숫자:",
                           "숫자",
        -                  "객체: 객체",
        -                 ],
        +                  "객체: 객체"
        +                  ],
                 "returns":"p5.NumberDict:"
             },
             "p5.TypedDict":{
        @@ -1275,27 +1211,25 @@
                 "returns":""
             },
         
        -// Data > Array Functions
        -      
             "append": {
               "description": "사용 불가: append()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push'>array.push(value)</a>를 대신 사용하세요.<br><br>배열의 끝에 값을 추가하여, 그 길이를 1씩 확장합니다. Array.push()에 매핑합니다.",
               "params": ["배열: 추가할 배열",
        -                 "전부: 배열에 추가될 모든 것"],
        +                  "전부: 배열에 추가될 모든 것"],
               "returns": "추가된 배열"
             },
             "arrayCopy": {
               "description": "사용 불가: copyArray()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.<br>배열(또는 그 일부)을 다른 배열에 복사합니다. src 배열이 dst 배열에 복사되며, srcPosition으로 지정된 위치에서 시작하여 dstPosition으로 지정된 위치를 향합니다. 복사할 요소의 개수는 배열의 길이로 결정됩니다. 값을 복사하면 대상 배열의 기존값을 덮어씁니다. 덮어쓰기없이 값을 추가하려면 concat()을 사용하세요.<br>",
               "params": ["",
        -                 "",
        -                 "",
        -                 "",
        -                 ""],
        +                  "",
        +                  "",
        +                  "",
        +                  ""],
               "returns": ""
             },
             "concat": {
               "description": "사용 불가: concat()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat'>arr1.concat(arr2)</a>를 대신 사용하세요.<br><br>",
               "params": ["",
        -                 ""],
        +                  ""],
               "returns": ""
             },
             "reverse": {
        @@ -1311,34 +1245,30 @@
             "shuffle": {
               "description": "사용 불가: shuffle()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. <a hreh='https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array'>使用 Javascript 混洗数组</a>를 대신 사용하세요.<br><br><a href = 'https://bost.ocks.org/mike/shuffle/'>피셔-예이츠(Fisher-Yates) 셔플 알고리즘</a>을 구현합니다.",
               "params": ["",
        -                 ""],
        +                  ""],
               "returns": ""
             },
             "sort": {
               "description": "사용 불가: sort()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort'>array.sort()</a>를 대신 사용하세요. <br><br>",
               "params": ["",
        -                 ""],
        +                  ""],
               "returns": ""
             },
             "splice": {
               "description": "사용 불가: splice()는 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다.请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice'>array.splice()</a>를 대신 사용하세요.<br><br>",
               "params": ["",
        -                 "",
        -                 ""],
        +                  "",
        +                  ""],
               "returns": ""
             },
             "subset": {
               "description": "弃用:subset()은 더이상 사용 불가하며, p5의 추후 버전에서 제거됩니다. 请改用 <a href='https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice'>array.slice()</a>를 대신 사용하세요.<br><br>",
               "params": ["",
        -                 "",
        -                 ""],
        +                  "",
        +                  ""],
               "returns": ""
             },
        -      
        -      
        -// Data > Conversion
        -      
        -      
        +        
             "float": {
               "description": "문자열을 실수(float), 즉 부동 소수점 숫자형 표현으로 변환합니다. 이 때, 문자열의 구문은 숫자 형식과 유사해야 합니다. 그렇지 않으면 NaN(숫자 아님)이 반환됩니다. 예컨대, float (\"1234.56\")은 1234.56으로 연산되지만, float (\"giraffe\")는 NaN을 반환합니다.<br>전달된 배열과 길이가 동일한 실수 배열이 반환됩니다.",
               "params": ["문자열: 구문 분석할 실수 문자열"],
        @@ -1347,8 +1277,8 @@
             "int": {
               "description": "불리언(boolean), 문자열(string), 실수(float)를 정수(int)형 표현으로 변환합니다. 전달된 배열과 길이가 동일한 정수 배열이 반환됩니다.",
               "params": ["문자열|불리언|숫자: 구문 분석할 값",
        -                 "정수: 기수로 변환 (기본값: 10) (선택 사항)",
        -                 "배열: 구문 분석할 값"],
        +                  "정수: 기수로 변환 (기본값: 10) (선택 사항)",
        +                  "배열: 구문 분석할 값"],
               "returns": "숫자: 값의 정수형 표현"
             },
             "str": {
        @@ -1364,112 +1294,103 @@
             "byte": {
               "description": "숫자, 숫자의 문자열 표현, 또는 불리언을 바이트 표현으로 변환합니다. 바이트는 -128과 127 사이의 정수이므로, 이 범위를 벗어난 값은 상응하는 바이트 표현에 래핑됩니다. 숫자, 문자열, 또는 불리언 값의 배열을 전달하면, 동일한 길이의 바이트 배열이 반환됩니다.",
               "params": ["문자열|불리언|숫자: 구문 분석할 값",
        -                 "배열: 구문 분석할 값"],
        +                  "배열: 구문 분석할 값"],
               "returns": "값의 바이트형 표현"
             },
             "char": {
               "description": "숫자나 문자열을 단일 문자형(character) 문자열 표현으로 변환합니다. 사용자가 별도 지정한 문자열 매개 변수의 경우, 먼저 정수로서 구문 분석된 후 단일 문자형 문자열로 변환됩니다. 숫자 또는 문자열 값의 배열을 전달하면, 동일한 길이의 단일 문자형 문자열이 반환됩니다.",
               "params": ["문자열|숫자: 구문 분석할 값",
        -                 "배열: 구문 분석할 값"],
        +                  "배열: 구문 분석할 값"],
               "returns": "값의 문자열 표현"
             },             
             "unchar": {
               "description": "단일 문자형 문자열 표현을 정수로 변환합니다. 단일 문자열 문자열 값의 배열을 전달하면, 동일한 길이의 정수 배열이 반환됩니다.",
               "params": ["문자열: 구문 분석할 값",
        -                 "배열: 구문 분석할 값"],
        +                  "배열: 구문 분석할 값"],
               "returns": "값의 정수형 표현"
             },
             "hex": {
               "description": "숫자를 16진수 문자열로 변환합니다. 전달된 2번째 매개 변수는 16진수 표기법으로 생성할 문자 개수를 설정합니다. 배열이 전달되면, 동일한 길이를 갖는 16진수 문자열을 반환합니다.",
               "params": ["숫자: 구문 분석할 값",
        -                 "숫자: (선택 사항)",
        -                 "숫자 배열[]: 구문 분석할 숫자 값들 배열"],
        +                  "숫자: (선택 사항)",
        +                  "숫자 배열[]: 구문 분석할 숫자 값들 배열"],
               "returns": "값의 16진수 문자열 표현"
             },
             "unhex": {
               "description": "16진수 문자열 표현을 정수로 변환합니다. 16진수 문자열 값의 배열을 전달하면, 동일한 길이의 정수 배열이 반환됩니다.",
               "params": ["문자열: 구문 분석할 값",
        -                 "배열: 구문 분석할 값"],
        +                  "배열: 구문 분석할 값"],
               "returns": "16진수 값의 정수형 표현"
             },
        -      
        -      
        -      
        -// Data > String Functions
        -      
        -      
        +
             "join": {
               "description": "문자열 배열을 결합하여 하나의 문자열을 만듭니다. 각 문자열은 사용자가 구분자 매개 변수로 지정한 문자를 통해 구분됩니다. 정수(int) 또는 실수(float) 배열을 결합하려면, 먼저 nf() 또는 nfs()를 통해 문자열로 변환되어야 합니다.",
               "params": ["배열: 결합할 문자열 배열",
        -                 "문자열: 각 항목 사이에 놓일 문자열"],
        +                  "문자열: 각 항목 사이에 놓일 문자열"],
               "returns": "문자열: 결합된 문자열"
             },
             "match": {
               "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들) 리스트를 문자열 배열로 반환합니다. 매치하는 내용이 없는 경우, null을 반환합니다. 정규 표현식에 그룹이 지정되지 않지만 시퀀스가 일치하는 경우, 길이가 1인 배열(일치하는 텍스트가 배열의 첫번째 요소인 배열)을 반환합니다.<br><br>match() 함수 사용시, 결과값이 null인지를 잘 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우, 배열이 반환됩니다.<br><br>그룹(괄호들로 지정)이 정규식 표현인 경우, 각각의 내용들이 배열로 반환됩니다. 매치하는 정규식 표현의 요소[0]는 모든 매칭 문자열을 반환하는데, 이 경우 매칭 그룹은 요소[1](첫 번째 그룹은 [1], 두번째 그룹은 [2])에서 시작합니다.",
               "params": ["문자열: 검색할 문자열",
        -                 "문자열: 매칭에 사용될 정규식 표현"],
        +                  "문자열: 매칭에 사용될 정규식 표현"],
               "returns": "검색된 문자열들의 배열"
             },
             "matchAll": {
               "description": "이 함수는 정규 표현식을 텍스트로 적용하고, 매치하는 그룹(괄호 안 요소들)의 리스트를 2차원 문자열 배열로 반환합니다. 매치하는 내용이 없는 경우, null을 반환합니다. 정규 표현식에 그룹이 지정되지 않지만 시퀀스가 일치하는 경우, 2차원 배열이 반환되지만 2번째 차원의 길이는 1이 됩니다.<br><br>matchAll() 함수 사용시, 결과값이 null인지를 잘 확인하세요. 결과가 null이면 시퀀스도 일치하지 않는다는 뜻입니다. 시퀀스가 일치하는 경우, 2D 배열이 반환됩니다.<br><br>그룹(괄호들로 지정)이 정규식 표현인 경우, 각각의 내용들이 배열로 반환됩니다. 카운터 변수 i가 있는 반복문을 가정할 때, 매칭되는 정규식의 [i][0] 요소는 모든 매칭 문자열을 반환하고, 매칭 그룹은 [i][1](첫 번째 그룹은 [i][1], 두번째 그룹은 [i][2], ...)에서 시작합니다.",
               "params": ["문자열: 검색할 문자열",
        -                 "문자열: 매칭에 사용될 정규식 표현"],
        +                  "문자열: 매칭에 사용될 정규식 표현"],
               "returns": "검색된 문자열들의 2D 배열"
             },
             "nf": {
               "description": "숫자를 문자열로 형식화하는 기능으로, 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수로는 각각 자릿수(digit), 소수점 기준 왼쪽 자릿수(left), 소수점 기준 오른쪽 자릿수(right)를 지정할 수 있으며, 이 매개 변수 값들은 항상 양의 정수여야 합니다. <br> 참고: left와 right 매개 변수 사용시, 그 값이 현재 숫자의 자릿수 길이보다 클 경우 자릿수를 맞추기 위해 매개 변수에 0이 붙는 점에 유의하세요. 예를 들어, 현재 숫자가 123.2이고 전달된 left 매개 변수가 4인 경우, 그 길이가 num의 정수 부분인 123의 길이(즉, 3)보다 큽니다. 이 경우, 0123.2가 반환됩니다. right 매개 변수의 경우에도 마찬가지로 값이 3인 정수 123.200이 반환됩니다.",
               "params": ["숫자|문자열: 형식화할 숫자",
        -                 "정수|문자열: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        -                 "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        -                 "배열: 형식화할 숫자들"],
        +                  "정수|문자열: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                  "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                  "배열: 형식화할 숫자들"],
               "returns": "문자열: 형식화된 문자열"
             },
             "nfc": {
               "description": "숫자를 문자열로 형식화하고 1000을 단위로 표시하기 위해 쉼표를 배치하는 기능입니다. 크게 두 가지 버전이 제공되는데, 하나는 정수(int)를 형식화하는 것이고, 다른 하나는 정수 배열을 형식화합니다. 매개 변수의 값들은 항상 양의 정수여야 합니다.",
               "params": ["숫자|문자열: 형식화할 숫자",
        -                 "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        -                 "배열: 형식화할 숫자들"],
        +                  "정수|문자열: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                  "배열: 형식화할 숫자들"],
               "returns": "문자열: 형식화된 문자열"
             },
             "nfp": {
               "description": "숫자를 문자열로 형식화하는 기능입니다. nf()와 유사하나, 양수 앞에 '+'를, 음수 앞에 '-' 기호를 추가합니다. 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수 중, 소수점 기준 왼쪽 자릿수(left)와 소수점 기준 오른쪽 자릿수(right)의 값은 항상 양의 정수여야 합니다.",
               "params": ["숫자: 형식화할 숫자",
        -                 "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        -                 "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        -                 "숫자 배열[]: 형식화할 숫자들"],
        +                  "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                  "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                  "숫자 배열[]: 형식화할 숫자들"],
               "returns": "문자열: 형식화된 문자열"
             },
             "nfs": {
               "description": "숫자를 문자열로 형식화하는 기능입니다. nf()와 유사하나, '-' 기호가 붙은 음수와 정렬할 경우를 위해 '_(공백)' 기호를 양수 앞에 추가합니다. nfs()는 주로 음수가 아닌 숫자의 자릿수에 음수를 맞출 때 사용됩니다. (명확한 이해를 위해 예제를 참고하세요.) 실수(float) 형식과 정수(int) 형식의 두 가지 버전이 있습니다. 매개 변수 중, 자릿수(digit), 소수점 기준 왼쪽 자릿수(left)와 소수점 기준 오른쪽 자릿수(right)의 값은 항상 양의 정수여야 합니다. (IMP): 정렬 결과는 사용자의 타입페이스에 따라 달라집니다. 참고: left와 right 매개 변수 사용시, 그 값이 현재 숫자의 자릿수 길이보다 클 경우 자릿수를 맞추기 위해 매개 변수에 0이 붙는 점에 유의하세요. 예를 들어, 현재 숫자가 123.2이고 전달된 left 매개 변수가 4인 경우, 그 길이가 num의 정수 부분인 123의 길이(즉, 3)보다 큽니다. 이 경우, 0123.2가 반환됩니다. right 매개 변수의 경우에도 마찬가지로 값이 3인 정수 123.200이 반환됩니다.",
               "params": ["숫자: 형식화할 숫자",
        -                 "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        -                 "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        -                 "배열: 형식화할 숫자들"],
        +                  "정수: 소수점 기준 왼쪽의 자릿수(선택 사항)",
        +                  "정수: 소수점 기준 오른쪽의 자릿수(선택 사항)",
        +                  "배열: 형식화할 숫자들"],
               "returns": "문자열: 형식화된 문자열"
             },
             "split": {
               "description": "split() 함수는 String.split()에 매핑되며, 구분 기호를 사용하여 문자 또는 문자열을 분할합니다. 분리 문자(delim) 매개 변수는 분할 경계를 나타낼 기호를 지정합니다. 각 조각들을 포함한 문자열 배열이 반환됩니다.<br>splitTokens() 역시 비슷하게 작동하나, 특정 문자나 시퀀스 대신 여러 개의 분리 문자를 분할한다는 점에서 다릅니다.",
               "params": ["문자열: 분할될 문자열",
        -                 "문자열: 데이터 분할에 쓰이는 문자열"],
        +                  "문자열: 데이터 분할에 쓰이는 문자열"],
               "returns": "문자열 배열[]: 문자열들의 배열"
             },
             "splitTokens": {
               "description": "splitTokens() 함수는 일명 '토큰(token)'이라 불리는, 하나 이상의 분리 문자를 사용하여 문자열을 분할합니다. <br><br> 분리 문자(delim) 매개 변수를 지정하지 않는 경우, 공백 문자를 사용하여 분할합니다. 공백 문자는 탭(\\t), 줄바꾸기(\\n), 캐리지 반환(CR: Carriage Return)(\\r), 폼 피드(FF: Form Feed)(\\f), 그리고 공백을 포함합니다.",
               "params": ["문자열: 분할될 문자열",
        -                 "문자열: 데이터 분할에 쓰이는 문자열"],
        +                  "문자열: 데이터 분할에 쓰이는 문자열"],
               "returns": "문자열 배열[]:문자열들의 배열"
             },
             "trim": {
               "description": "문자열 앞뒤의 공백 문자를 제거합니다. 공백, 캐리지 반환(CR: Carriage Return), 탭과 같은 표준 공백 문자 외에, 유니코드 'nbsp' 문자도 제거합니다.",
               "params": ["문자열: 트리밍될 문자열",
        -                 "배열: 트리밍될 문자열 배열"],
        +                  "배열: 트리밍될 문자열 배열"],
               "returns": "문자열: 트리밍된 문자열"
             },
        -
        -
        -      
        -// Events > Accleration
        -      
        +        
             "deviceOrientation": {
               "description": "시스템 변수 deviceOrientation는 기기의 방향을 담습니다. 변수값은 LANDSCAPE(가로) 또는 PORTRAIT(세로)로 설정가능합니다. 사용 가능한 데이터가 없는 경우, '정의되지 않음(undefined)로 설정됩니다.",
               "returns": ""
        @@ -1549,12 +1470,8 @@
             "deviceShaken": {
               "description": "deviceShaken() 함수는 accelerationX와 accelerationY의 전체 가속도 변화량이 임계값보다 클 때 호출됩니다. 기본 임계값은 30입니다. 임계값은 setShakeThreshold()로 변경할 수 있습니다.",
               "returns": ""
        -    },
        -      
        -      
        -// Events > Keyboard
        -      
        -      
        +    },  
        +        
             "keyIsPressed": {
               "description": "불리언 시스템 변수 keyIsPressed입니다. 자판키를 누르면 참(true)을, 누르지 않을 때 거짓(false)을 반환합니다.",
               "returns": ""
        @@ -1584,14 +1501,7 @@
               "params": "숫자: 확인할 자판키",
               "returns": "자판을 눌렀는지 아닌지의 여부"
             },
        -      
        -      
        -// Events > Mouse
        -      
        -    "movedX": {
        -      "description": "movedX 변수는 직전 프레임 이후의 마우스 수평 이동을 담습니다.",
        -      "returns": ""
        -    },
        +        
             "movedX": {
               "description": "movedY 변수는 직전 프레임 이후의 마우스 수직 이동을 담습니다.",
               "returns": ""
        @@ -1673,11 +1583,6 @@
               "returns": ""
             },
               
        -      
        -      
        -// Events > Touch
        -      
        -      
             "touches": {
               "description": "시스템 변수 touches[]는 캔버스 (0,0)에 대한 현재의 모든 터치 포인트 위치, 그리고 터치를 식별하는 고유 ID를 담습니다.배열 속 요소들은 각각 x, y, 그리고 id 속성을 갖는 객체들입니다.<br><br>touch[] 배열은 터치 기반 데스크톱 및 노트북상의 Safari나 Internet Explorer에서 지원되지 않습니다.",
               "returns": ""
        @@ -1694,45 +1599,36 @@
               "description": "touchEnded() 함수는 터치가 등록될 때마다 한 번씩 호출됩니다. touchEnded() 함수가 정의되지 않고, mouseReleased() 함수가 정의된 경우, 후자가 대신 호출됩니다.<br>마우스 입력을 통한 이벤트 발생이 브라우저 기본값으로 설정되어있는 경우, 메소드 말미에 \"return false\"를 넣어 브라우저 기본값 이벤트 발생을 방지할 수 있습니다.",
               "params": "객체: TouchEvent 콜백 인수 (선택 사항)"
             },
        -      
         
        -//Image
        -      
        -      
        -      
             "createImage": {
               "description": "새로운 p5.Image(이미지 저장을 위한 데이터 유형)를 생성합니다. 이 함수는 새 픽셀 버퍼를 제공합니다. 너비 및 높이 매개 변수로 버퍼 크기를 설정하세요. <br><br>.pixels를 통해 디스플레이 화면의 모든 픽셀값이 담긴 배열에 접근합니다. 픽셀값은 숫자로 표현됩니다. 배열은 디스플레이 화면의 4배 크기(픽셀 밀도에 대한 인수 포함)로, 각 픽셀에 대한 R, G, B, A값을 나타냅니다. 배열은 행의 좌에서 우로, 그 다음 열로 내려가는 순으로 채워집니다. 자세한 내용은 .pixels 레퍼런스를 참고하세요. 몇몇 경우에서는 set() 및 get() 함수를 사용하는 편이 더 편리할 수 있습니다.<br><br>이미지의 픽셀에 접근하기에 앞서, loadPixels() 함수를 통해 픽셀을 불러와야 합니다. 또한, 배열 데이터를 수정한 후에는 updatePixels()로 수정된 내용을 반영해야 합니다.",
               "params": ["정수: 픽셀 단위 너비값",
        -                 "정수: 픽셀 단위 높이값"],
        +                  "정수: 픽셀 단위 높이값"],
               "returns": "p5.Image: p5.Image 객체"
             },
             "saveCanvas": {
               "description": "현재 캔버스를 이미지로 저장합니다. 브라우저에 따라 파일을 즉시 저장하거나 사용자에게 대화 상자를 표시합니다. ",
               "params": ["p5.Element|HTMLCanvasElement: 특정 HTML5 캔버스를 나타내는 변수 (선택 사항)",
        -                 "문자열: (선택 사항)",
        -                 "문자열: 'jpg' 또는 'png' (선택 사항)"],
        +                  "문자열: (선택 사항)",
        +                  "문자열: 'jpg' 또는 'png' (선택 사항)"],
               "returns": ""
             },
             "saveFrames": {
               "description": "동영상 제작에 사용되는 일련의 프레임을 캡처합니다. 콜백을 허용하는 함수로, 프레임을 서버로 보내 저장하거나 동영상으로 변환할 수 있습니다. 콜백을 지정하지 않으면, 생성된 모든 이미지 다운로드를 위한 대화 상자가 브라우저에 팝업창으로 나타납니다. 콜백을 지정할 경우 이미지 데이터를 자동 저장하는 대신, 총 프레임 수와 동일한 갯수의 크기를 갖는 객체 배열을 콜백 함수에 인수로서 전달합니다.<br><br>saveFrames() 함수는 애니메이션의 처음 15개의 프레임만 저장합니다. 재생 시간이 더 긴 애니메이션을 내보내려면 <a href='https://github.com/spite/ccapture.js/'>ccapture.js</a>와 같은 라이브러리를 확인하세요.",
               "params": ["문자열:",
        -                 "문자열: 'jpg' 또는 'png'",
        -                 "숫자: 프레임을 저장할 시간(초)",
        -                 "숫자: 저장할 프레임 속도",
        -                 "함수(배열): 이미지 데이터를 처리하는 콜백 함수. 이 함수는 배열을 인수로만 받습니다. 지정된 개수의 객체 프레임이 배열에 포함됩니다. 각 객체는 다음의 3가지 속성을 가집니다: imageData - 이미지/옥텟 스트림, 파일명, 파일 확장자 (선택 사항)"],
        +                  "문자열: 'jpg' 또는 'png'",
        +                  "숫자: 프레임을 저장할 시간(초)",
        +                  "숫자: 저장할 프레임 속도",
        +                  "함수(배열): 이미지 데이터를 처리하는 콜백 함수. 이 함수는 배열을 인수로만 받습니다. 지정된 개수의 객체 프레임이 배열에 포함됩니다. 각 객체는 다음의 3가지 속성을 가집니다: imageData - 이미지/옥텟 스트림, 파일명, 파일 확장자 (선택 사항)"],
               "returns": ""
             },
        -      
        -
        -// Image > Loading & Displaying
        -      
         
             "loadImage": {
               "description": "사용자가 지정한 경로로부터 이미지를 불러오고 p5.Image를 생성합니다. <br><br>이미지를 불러와도 곧바로 렌더링되지 않는 경우가 있습니다. 여타 작업을 수행하기에 앞서 이미지 로드를 완료하려면, loadImage()를 preload() 함수 안에서 호출하면 됩니다. 또는, 로드가 완료된 이미지 처리를 위한 콜백 함수를 지정할 수 있습니다. <br><br>이미지 경로는 스케치에 링크된 HTML 파일에 대한 상대 경로를 사용합니다. URL이나 원격 경로를 이용하면 브라우저의 보안 설정에 따라 이미지를 불러오는 데에 문제가 생길 수 있습니다.",
               "params": ["문자열: 불러올 이미지 경로",
               "함수(p5.Image): 이미지 불러오기 후 호출되는 함수로, p5.Image가 전달됩니다. (선택 사항)",
               "함수(Event): 이미지 불러오기 실패시 이벤트 에러와 함께 호출되는 함수 (선택 사항)"],
        -       "returns": "p5.Image: p5.Image 객체"  
        +        "returns": "p5.Image: p5.Image 객체"  
             },
               
             "image": {
        @@ -1754,13 +1650,13 @@
             "tint": {
               "description": "화면에 나타날 이미지의 면채우기 값을 설정합니다. 이미지에 색조를 입히거나 알파값을 통해 투명도를 조정할 수 있습니다.<br><br>이미지 본래의 색상을 유지하면서 투명도를 적용하려면, 흰색 색조에 알파값을 지정하면 됩니다. 예를 들어 tint(255, 128)는 이미지를 50% 투명하게 만듭니다. (기본 알파 범위 0-255를 가정, 범위는 colorMode()로 조정 가능)<br><br>회색값 매개 변수는 현재 colorMode()에 따른 최대값보다 작거나 같아야합니다. 기본 최대값은 255입니다.",
               "params": ["숫자: 현재 색상 범위에 대한 빨강값 또는 색조값",
        -                 "숫자: 현재 색상 범위에 대한 초록값 또는 채도값",
        -                 "숫자: 현재 색상 범위에 대한 파랑값 또는 밝기값"",
        -                 "숫자: (선택 사항)",
        -                 "문자열: 색상 문자열",
        -                 "숫자: 회색값",
        -                 "숫자 배열[]: 색상의 R, G, B & 알파값을 담는 배열",
        -                 "p5.Color: 입힐 색조의 색상],
        +                  "숫자: 현재 색상 범위에 대한 초록값 또는 채도값",
        +                  "숫자: 현재 색상 범위에 대한 파랑값 또는 밝기값",
        +                  "숫자: (선택 사항)",
        +                  "문자열: 색상 문자열",
        +                  "숫자: 회색값",
        +                  "숫자 배열[]: 색상의 R, G, B & 알파값을 담는 배열",
        +                  "p5.Color: 입힐 색조의 색상]"],
               "returns": ""
             },
             "noTint": {
        @@ -1769,14 +1665,9 @@
             },
             "imageMode": {
               "description": "이미지의 모드를 설정합니다. image()의 매개 변수가 해석되는 방식을 변경하여 이미지가 그려지는 위치를 수정합니다. 기본 모드는 imageMode(CORNER)이며, image()의 2번째 및 3번째 매개 변수를 이미지의 좌측 상단 모퉁이의 좌표값으로 해석합니다. 추가 매개 변수 2개를 통해 이미지의 너비와 높이도 설정할 수 있습니다.<br><br>imageMode(CORNERS)는 image()의 2번째 및 3번째 매개 변수를 모퉁이 한 개의 좌표값으로 해석합니다. 그리고, 4번째 및 5번째 매개 변수를 그 반대편 모퉁이의 좌표값으로 해석합니다.<br><br>imageMode(CENTER)는 2번째 및 3번째 매개 변수를 이미지의 중심점 좌표값으로 해석합니다. 추가 매개 변수 2개를 통해 이미지의 너비와 높이도 설정할 수 있습니다.",
        -      "params": ["常量:CORNER、CORNERS 或 CENTER"],
        -      "params": "상수: CORNER, CORNERS, CENTER 중 하나"
        +      "params": ["常量:CORNER、CORNERS 或 CENTER"]
             },
               
        -      
        -// Image > Pixels
        -      
        -      
             "pixels": {
               "description": "디스플레이 화면의 모든 픽셀값을 담는 <a href ='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray'>Uint8ClampedArray</a>입니다. 픽셀값은 숫자로 표현됩니다. 배열은 디스플레이 화면의 4배 크기(픽셀 밀도에 대한 인수 포함)로, 각 픽셀에 대한 R, G, B, A값을 나타냅니다. 배열은 행의 좌에서 우로, 그 다음 열로 내려가는 순으로 채워집니다. Retina를 비롯한 기타 고밀도 디스플레이는 (pixelDensity^2 계수로 인해) 크기가 더 큰 픽셀 배열[]을 갖기도 합니다. 일반 디스플레이 화면상 이미지가 100x100 픽셀이고 그 배열이 40,000이라면, Retina에서 배열은 160,000이 됩니다. <br><br>배열상 처음 4개의 값들(즉, 인덱스 0-3)은 (0,0) 픽셀에서의 R, G, B, A값을, 그 다음 4개의 값들(즉, 인덱스 4-7)은 (1,0) 픽셀에서의 R, G, B, A값을 담습니다. 특정 좌표 (x,y)에서의 픽셀값을 설정하는 방법은 아래의 예제와 같습니다.<br><br>다소 복잡해보이는 예제지만, 모든 픽셀 밀도(pixelDensity)를 사용할 수 있을정도로 유연합니다. set()은 임의의 pixelDensity에서 주어진 (x,y)에 대한 픽셀 배열[]의 모든 값들을 자동으로 설정합니다. 배열을 여러 차례 수정할 경우, 성능이 느려질 수 있습니다.<br><br>이 레퍼런스는 표준 자바스크립트 배열이 아니고, 따라서 slice()나 arrayCopy()와 같은 표준 자바스크립트 함수가 작동하지 않는 점에 유의하세요.  ",
               "returns": ""
        @@ -1784,42 +1675,42 @@
             "blend": {
               "description": "사용자가 지정한 혼합 모드를 사용하여, 한 이미지의 픽셀 영역을 다른 이미지로 복사합니다.",
               "params": ["p5.Image: 원본 이미지",
        -                 "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        -                 "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        -                 "정수: 원본 이미지 너비값",
        -                 "정수: 원본 이미지 높이값",
        -                 "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        -                 "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        -                 "정수: 대상 이미지 너비값",
        -                 "정수: 대상 이미지 높이값",
        -                 "상수: 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD or NORMAL 중 하나"],
        +                  "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        +                  "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        +                  "정수: 원본 이미지 너비값",
        +                  "정수: 원본 이미지 높이값",
        +                  "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        +                  "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        +                  "정수: 대상 이미지 너비값",
        +                  "정수: 대상 이미지 높이값",
        +                  "상수: 혼합 모드. BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD or NORMAL 중 하나"],
               "returns": ""
             },
             "copy": {
               "description": "캔버스의 한 영역을 다른 영역에 복사하고, srcImg 매개 변수로 사용되는 한 이미지의 픽셀 영역을 캔버스에 복사합니다. srcImage는 원본 이미지로, 사용자가 지정합니다. 원본과 복사 대상 영역의 크기가 같지 않을 경우, 원본 픽셀 영역의 크기를 대상 영역의 크기에 맞게 자동으로 재조정합니다.",
               "params": ["p5.Image|p5 요소: 원본 이미지",
        -                 "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        -                 "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        -                 "정수: 원본 이미지 너비값",
        -                 "정수: 원본 이미지 높이값",
        -                 "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        -                 "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        -                 "정수: 대상 이미지 너비값",
        -                 "정수: 대상 이미지 높이값"],
        +                  "정수: 원본 영역의 좌측 상단 모퉁이 x좌표값",
        +                  "정수: 원본 영역의 좌측 상단 모퉁이 y좌표값",
        +                  "정수: 원본 이미지 너비값",
        +                  "정수: 원본 이미지 높이값",
        +                  "정수: 대상 영역의 좌측 상단 모퉁이 x좌표값",
        +                  "정수: 대상 영역의 좌측 상단 모퉁이 y좌표값",
        +                  "정수: 대상 이미지 너비값",
        +                  "정수: 대상 이미지 높이값"],
               "returns": ""
             },
             "filter": {
               "description": "캔버스에 필터를 적용합니다.<br><br>GRAY: 이미지의 모든 색상을 그레이 스케일로 변환합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>OPAQUE: 알파 채널을 완전히 불투명하게 설정합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>INVERT: 각 픽셀을 그 역의 값으로 설정합니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>POSTERIZE: 이미지의 각 채널을 매개 변수로 지정한 색상 수로 제한합니다. 매개 변수는 2부터 255사이의 값으로 설정 가능하나, 낮은 범위에서 가장 두드러진 결과를 볼 수 있습니다.<br><br>BLUR: 블러 범위를 설정하는 level 매개 변수를 사용하여 가우시안 블러를 실행합니다. 별도의 매개 변수를 지정하지 않으면, 반경 1의 가우시안 블러와 동일한 효과가 됩니다. 값이 클수록 흐림 정도가 증가합니다.<br><br>ERODE: 밝은 영역을 줄입니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>DILATE: 밝은 영역을 증가시킵니다. 별도의 매개 변수를 사용하지 않습니다.<br><br>WebGL 모드에서는 filter()가 작동하지 않으나, 커스텀 셰이더를 사용하여 유사한 효과를 얻을 수 있습니다. 아담 페리스(Adam Ferriss)가 작성한 <a href='https://github.com/aferriss/p5jsShaderExamples'>셰이더 예제</a> 중, filter()와 유사한 효과를 나타내는 예제들이 있으니 참고하세요.",
               "params": ["상수: THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE, DILATE, BLUR 중 하나. 각 필터에 대한 문서는 Filters.js를 참조.",
        -                 "숫자: 각 필터 고유의 선택적 매개 변수 (선택 사항)"],
        +                  "숫자: 각 필터 고유의 선택적 매개 변수 (선택 사항)"],
               "returns": ""
             },
             "get": {
               "description": "지정된 픽셀 영역 또는 단일 픽셀을 캔버스로부터 받아옵니다.<br><br>특정 픽셀에 대한 [R,G,B,A] 값의 배열이나, 이미지의 한 영역을 반환합니다. 별도의 매개 변수를 지정하지 않는 경우, 전체 이미지를 반환합니다. 매개 변수 x, y를 통해 특정 픽셀의 좌표값을 받아올 수 있습니다. 추가 매개 변수 w, h를 통해 디스플레이 창의 한 영역을 지정할 수도 있습니다. 이미지를 받아올 때, 매개 변수 x와 y는 현재 imageMode()와 관계없이 좌측 상단 모퉁이의 좌표값을 정의합니다. <br><br>get(x,y) 함수로 픽셀 1개의 색상을 받아오는 것은 쉬운 방법이지만, pixels[] 배열로부터 직접 데이터를 받아오는 것만큼 빠르진 않습니다. pixels[] 배열과 픽셀 밀도 매개 변수 d를 사용하여 get(x,y)과 동일한 효과를 나타낼 수 있고, 구체적인 명령문은 다음의 예제와 같습니다.<br><br>더 많은 정보는 pixels[] 레퍼런스를 확인하세요.<br>p5.Image 객체의 하위 이미지로부터 색상 배열을 추출하는 방법은 p5.Image.get()에서 참고하세요.",
               "params": ["숫자: 픽셀의 x좌표값",
        -                 "숫자: 픽셀의 y좌표값",
        -                 "숫자: 너비",
        -                 "숫자: 높이"],
        +                  "숫자: 픽셀의 y좌표값",
        +                  "숫자: 너비",
        +                  "숫자: 높이"],
               "returns": "p5.Image: 직사각형 p5.Image"
             },
             "loadPixels": {
        @@ -1829,91 +1720,86 @@
             "set": {
               "description": "특정 픽셀의 색상을 변경하거나, 디스플레이 창에 이미지를 직접 작성합니다.<br><br>매개 변수 x와 y는 변경할 픽셀을 지정하고, 매개 변수 c는 색상값을 지정합니다. 색상값으로는 p5.Color 객체, [R,G,B,A] 베열, 또는 단일 그레이 스케일값을 사용할 수 있습니다. 이미지 설정시, 매개 변수 x와 y는 현재 imageMode()와 관계없이 좌측 상단 모퉁이의 좌표값을 정의합니다.<br><br>set() 함수 사용 후에는 반드시 updatePixels()를 호출하여 변경 사항을 반영해야 합니다. 호출 시점은 픽셀 설정을 완료한 이후이면서 동시에, .get() 또는 그리기 함수 호출 이전이어야 합니다.<br><br>set(x,y) 함수로 픽셀 1개의 색상을 받아오는 것은 쉬운 방법이지만, pixels[] 배열로부터 직접 데이터를 받아오는 것만큼 빠르진 않습니다. 레티나 디스플레이에선 pixels[] 배열값을 직접 설정하는 것이 복잡할 수 있으나, 많은 양의 픽셀들이 반복 실행되도록 설정된 경우 그 작업 성능이 향상됩니다.<br><br>자세한 내용은 pixels[]를 참고하세요. ",
               "params": ["숫자: 픽셀의 x좌표값",
        -                 "숫자: 픽셀의 y좌표값",
        -                 "숫자|숫자 배열[]|객체: 그레이스케일 값 기입|픽셀 배열|p5.Color객체|복사할p5.Image"],
        +                  "숫자: 픽셀의 y좌표값",
        +                  "숫자|숫자 배열[]|객체: 그레이스케일 값 기입|픽셀 배열|p5.Color객체|복사할p5.Image"],
               "returns": ""
             },
             "updatePixels": {
        -      "description": "pixels[] 배열의 데이터로 디스플레이 창을 업데이트합니다. loadPixels()와 함께 사용하세요. 배열로부터 픽셀값을 읽어오기만 할 경우, updatePixels()를 사용할 필요가 없습니다. 업데이트는 배열값 변경 사항을 적용하는 데에만 필요합니다. updatePixels()는 픽셀 배열을 수정하거나 set() 함수를 호출할 때마다 매번 호출되어야하며, set() 함수 또는 pixels[] 배열 직접 조작을 통한 변경 사항만 반영합니다.,
        +      "description": "pixels[] 배열의 데이터로 디스플레이 창을 업데이트합니다. loadPixels()와 함께 사용하세요. 배열로부터 픽셀값을 읽어오기만 할 경우, updatePixels()를 사용할 필요가 없습니다. 업데이트는 배열값 변경 사항을 적용하는 데에만 필요합니다. updatePixels()는 픽셀 배열을 수정하거나 set() 함수를 호출할 때마다 매번 호출되어야하며, set() 함수 또는 pixels[] 배열 직접 조작을 통한 변경 사항만 반영합니다.",
               "params": ["숫자: 업데이트할 영역의 좌측 상단 모퉁이 x좌표값 (선택 사항)",
        -                 "숫자: 업데이트할 영역의 좌측 상단 모퉁이 y좌표값 (선택 사항)",
        -                 "숫자: 업데이트할 영역의 너비값 (선택 사항)",
        -                 "숫자: 업데이트할 영역의 높이값 (선택 사항)"],
        +                  "숫자: 업데이트할 영역의 좌측 상단 모퉁이 y좌표값 (선택 사항)",
        +                  "숫자: 업데이트할 영역의 너비값 (선택 사항)",
        +                  "숫자: 업데이트할 영역의 높이값 (선택 사항)"],
               "returns": ""
             },
               
        -      
        -      
        -// IO > Input
        -      
        -      
             "loadJSON": {
               "description": "파일 또는 URL로부터 JSON 파일을 불러오고, 객체를 반환합니다. JSON 파일에 배열이 포함된 경우, 인덱스 번호를 키(key)로 사용하여 객체를 반환할 수 있습니다.<br><br>이는 비동기적 메소드으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. JSONP는 polyfill을 통해 지원되며, <a href ='https://github.com/camsong/fetch-jsonp'>여기</a>의 구문에 따라 JSON 콜백 함수가 정의한 객체를 2번째 인수로 전달할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "객체: jsonp 관련 설정을 위한 객체 (선택 사항)",
        -                 "문자열: \"json\" 또는 \"jsonp\"",
        -                 "함수: loadJSON()이 완료된 이후 실행될 함수, 데이터를 1번재 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +                  "객체: jsonp 관련 설정을 위한 객체 (선택 사항)",
        +                  "문자열: \"json\" 또는 \"jsonp\"",
        +                  "함수: loadJSON()이 완료된 이후 실행될 함수, 데이터를 1번재 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "객체|배열: JSON 데이터"
             },
               
             "loadStrings": {
               "description": "파일의 내용을 읽어와 개별 행에 대한 문자열 배열을 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다.<br><br>이는 비동기적 메소드으로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.<br><br>[1번째 예제] preload() 함수 안에 loadStrings() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "함수: loadStrings()이 완료된 이후 실행될 함수, 배열을 1번째 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +                  "함수: loadStrings()이 완료된 이후 실행될 함수, 배열을 1번째 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "문자열 배열[]: 문자열들의 배열"
             },
               
             "loadTable": {
               "description": "파일 또는 URL의 내용을 읽어와 그 값으로 p5.Table 객체를 만듭니다. 특정 파일을 지정하려면, 해당 파일이 'data' 폴더 안에 있어야 합니다. 매개 변수 filename는 온라인 파일 URL로도 지정 가능합니다. 기본값으로, 파일 내용이 쉼표 단위로 구분된 것(CSV 형식)으로 간주합니다. 'header' 옵션이 포함된 경우, 헤더 행만 찾습니다.<br><br>가능한 옵션은 다음과 같습니다:<ul><li>csv - 테이블을 쉼표로 구분된 값으로서 구문 분석</li><li>tsv - 테이블을 탭으로 구분된 값으로서 구문 분석</li><li>header - 테이블에 헤더 행이 있음을 표기</li></ul><br><br>여러 옵션을 사용할 경우, 매개 변수들을 쉼표로 구분하여 전달할 수 있습니다. 예를 들면 다음과 같습니다:<br><br><code>loadTable('my_csv_file.csv', 'csv', 'header'); </code><br><br>불러오기 및 저장된 모든 파일은 UTF-8 인코딩을 사용합니다.<br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadTable() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "문자열: \"header\" \"csv\" \"tsv\"",
        -                 "함수: loadTable()이 완료된 이후 실행될 함수, 성공시 Table 객체를 1번째 인수로 전달 (선택 사항)",
        +                  "문자열: \"header\" \"csv\" \"tsv\"",
        +                  "함수: loadTable()이 완료된 이후 실행될 함수, 성공시 Table 객체를 1번째 인수로 전달 (선택 사항)",
                         "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "객체: 데이터를 포함한 Table 객체"
             },
             "loadXML": {
               "description": "파일의 내용을 읽어와 그 값으로 XML 객체를 생성합니다. 위의 예제처럼 파일명(filename)을 매개 변수로 사용할 경우, 해당 파일이 스케치 디렉토리/폴더(directory/folder) 안에 있어야 합니다.<br><br>절대 경로(Unix 및 Linux의 경우 with/on 으로, 윈도우의 경우 드라이브 문자로 시작)로도 로컬 컴퓨터로부터 파일을 불러올 수 있습니다. 또는, 매개 변수 filename을 URL 또는 네트워크상의 파일로 지정할 수 있습니다. <br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다. 그 경우, preload() 함수 안에 loadXML() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>preload() 함수 밖의 영역에서 콜백 함수를  작성하여 객체를 처리할 수 있습니다.<br><br>이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "함수: loadXML()이 완료된 이후 실행될 함수, XML 객체를 1번째 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +                  "함수: loadXML()이 완료된 이후 실행될 함수, XML 객체를 1번째 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "객체: 데이터를 포함한 XML 객체"
             },
             "loadBytes": {
               "description": "이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "함수: loadBytes()가 완료된 이후 실행될 함수 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수 (선택 사항)"],
        +                  "함수: loadBytes()가 완료된 이후 실행될 함수 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수 (선택 사항)"],
               "returns": "객체: 'bytes' 속성을 로드 완료된 버퍼로서 갖는 객체"
             },
             "httpGet": {
               "description": "HTTP GET 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다. 이는 httpDo(path, 'GET')을 호출하는 것과 동일한 효과를 갖습니다. ‘binary’ 데이터 형식은 Blob 객체를, ‘arrayBuffer’ 데이터 형식은 지정된 형식의 배열(예: Uint8Array)을 초기화할 ArrayBuffer를 반환합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\"",
        -                 "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        -                 "함수: httpGet()이 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +                  "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\"",
        +                  "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                  "함수: httpGet()이 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부."
             },
             "httpPost": {
               "description": "HTTP POST 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다. 이는 httpDo(path, 'POST')를 호출하는 것과 동일한 효과를 갖습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\". 생략할 경우, httpPost()가 임의로 가정합니다.",
        -                 "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        -                 "함수: httpPost()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
        +                  "문자열: \"json\",\"jsonp\",\"binary\",\"arrayBuffer\",\"xml\" 또는 \"text\". 생략할 경우, httpPost()가 임의로 가정합니다.",
        +                  "객체:불리언: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                  "함수: httpPost()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)"],
               "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부"
             },
             "httpDo": {
               "description": "HTTP 요청을 실행하는 메소드입니다. 별도의 데이터 유형(datatype)을 지정하지 않을 경우, p5는 URL을 기본값 텍스트로서 가정합니다.<br><br>고급 응용 단계에서는 경로를 1번째 인수로, 객체를 2번째 인수로 전달할 수 있습니다. 서명은 Fetch API 사양을 따릅니다. 이 방법은 최대 64MB 크기의 파일을 불러오는 데에 적합합니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "문자열: \"GET\", \"POST\", \"PUT\" 중 하나, 기본값은 \"GET\"",
        -                 "문자열: \"json\", \"jsonp\", \"xml\" 또는 \"text\" (선택 사항)",
        -                 "객체: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        -                 "함수: httpDo()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)",
        -                 "객체: <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>Fetch API 레퍼런스</a>에 따른 요청(request) 객체 옵션"],
        +                  "문자열: \"GET\", \"POST\", \"PUT\" 중 하나, 기본값은 \"GET\"",
        +                  "문자열: \"json\", \"jsonp\", \"xml\" 또는 \"text\" (선택 사항)",
        +                  "객체: 요청과 함께 전달되는 매개 변수 데이터 (선택 사항)",
        +                  "함수: httpDo()가 완료된 이후 실행될 함수, 데이터를 1번째 인수로 전달 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수, 반응(response)이 1번째 인수로 전달 (선택 사항)",
        +                  "객체: <a href='https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API'>Fetch API 레퍼런스</a>에 따른 요청(request) 객체 옵션"],
               "returns": "약속: 작업 성공시 데이터로 해결되는 약속, 또는 오류 발생시 거부"
             },
               
        @@ -1938,88 +1824,81 @@
                           "요소의 내용을 설정합니다.",
                           "요소를 문자열로 직렬화합니다. 요소의 내용을 http 요청으로 전송하거나 파일 저장을 준비할 때 사용됩니다."]
             },  
        -      
        -      
        -// IO > Input
        -      
        +
             "createWriter": {
               "description": "",
               "params": ["문자열: 생성될 파일의 이름",
        -                 "문자열: (선택 사항)"],
        +                  "문자열: (선택 사항)"],
               "returns": "p5.PrintWriter"
             },
               
             "p5.PrintWriter":{
                 "description":"",
                 "methods":["PrintWriter 스트림에 데이터를 작성합니다.",
        -                   "PrintWriter 스트림에 데이터를 작성하고, 마지막에 새로운 한 줄을 추가합니다.",
        -                   "PrintWriter 객체에 이미 작성된 데이터를 제거합니다.",
        +                    "PrintWriter 스트림에 데이터를 작성하고, 마지막에 새로운 한 줄을 추가합니다.",
        +                    "PrintWriter 객체에 이미 작성된 데이터를 제거합니다.",
                           "PrintWriter를 종료합니다."]
             }, 
                     
             "save": {
               "description": "이미지, 텍스트, json, csv, wav, 또는 html을 저장합니다. 클라이언트 컴퓨터에 다운로드 대화 상자가 뜹니다. <b>save() 함수는 매 프레임마다 새로운 저장 대화 상자를 엽니다. 따라서, 반복 실행되는 함수인 draw() 안에서 save()를 호출하지 않는 것을 권장합니다.</b><br><br>기본 동작은 캔버스를 이미지로 저장하는 것입니다. 선택적으로 파일명을 지정할 수 있습니다. 예를 들면 다음과 같습니다:<pre>CODE BLOCK PENDING</pre> 또는, 1번째 매개 변수를 캔버스 p5.Element애 대한 포인터, JSON 배열, JSON 객체, p5.Table, p5.Image, p5.SoundFile(p5.sound 필요)로 지정할 수 있습니다. 2번째 매개 변수로 파일명(확장자 포함)을 지정합니다. 3번째는 객체 유형에 따른 옵션을 설정합니다. 이 메소드는 사용자가 지정한 매개 변수에 따라 파일을 저장합니다. 예를 들면, 다음과 같습니다:<pre>CODE BLOCK PENDING</pre>",
               "params": ["객체|문자열: 지정된 파일명에 따라 캔버스를 png 또는 jpg 확장자 이미지로 저장합니다. 객체 지정시, 객체와 파일명에 따라 저장합니다. (위의 예제 참고) (선택 사항)",
        -                 "문자열: 객체를 1번째 매개 변수로 지정할 경우, 2번째 매개 변수는 파일명을 지시하게 되며, 이 경우 적절한 파일 확장자를 포함해야 합니다. (위의 예제 참고) (선택 사항) ",
        -                 "불리언|문자열: 파일 유형에 따른 추가 옵션. 예를 들어 JSON을 저장할 경우, 참(true)은 결과물의 가독성이 아닌, 결과물 파일 크기의 최적화를 뜻합니다. (선택 사항)"],
        +                  "문자열: 객체를 1번째 매개 변수로 지정할 경우, 2번째 매개 변수는 파일명을 지시하게 되며, 이 경우 적절한 파일 확장자를 포함해야 합니다. (위의 예제 참고) (선택 사항) ",
        +                  "불리언|문자열: 파일 유형에 따른 추가 옵션. 예를 들어 JSON을 저장할 경우, 참(true)은 결과물의 가독성이 아닌, 결과물 파일 크기의 최적화를 뜻합니다. (선택 사항)"],
               "returns": ""
             },
             "saveJSON": {
               "description": "배열 또는 JSON 객체의 내용을 .json 파일에 작성합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
               "params": ["배열|객체:",
        -                 "문자열:",
        -                 "불리언: 참(true)일 경우, 출력 파일상 줄바꿈과 공백을 제거하여 파일 크기를 최적화합니다. (가독성은 최적화 제외) (선택 사항)"],
        +                  "문자열:",
        +                  "불리언: 참(true)일 경우, 출력 파일상 줄바꿈과 공백을 제거하여 파일 크기를 최적화합니다. (가독성은 최적화 제외) (선택 사항)"],
               "returns": ""
             },
             "saveStrings": {
               "description": "문자열 배열을 문자열당 1줄 단위로 텍스트 파일에 작성합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
               "params": ["문자열 배열[]: 작성할 문자열 배열",
        -                 "문자열: 결과값을 위한 파일명",
        -                 "문자열: filename의 확장자 (선택 사항)",
        -                 "불리언: 참(true)일 경우, 줄바꿈을 CRLF로 변환 (선택 사항)"],
        +                  "문자열: 결과값을 위한 파일명",
        +                  "문자열: filename의 확장자 (선택 사항)",
        +                  "불리언: 참(true)일 경우, 줄바꿈을 CRLF로 변환 (선택 사항)"],
               "returns": ""
             },
             "saveTable": {
               "description": "테이블(Table) 객체의 내용을 파일에 작성합니다. 쉼표 단위로 값을 구분하는 텍스트 파일('csv')이 기본값으로 설정되지만, 탭 구분('tsv') 또는 HTML 테이블('html')도 생성가능합니다. 파일 저장 처리 방식 및 저장 파일 위치는 웹 브라우저마다 다릅니다.",
               "params": ["p5.Table: 파일에 저장할 Table 객체",
        -                 "문자열: Table을 저장할 파일명",
        -                 "문자열: 可以是 \"tsv\", \"csv\", \"html\" 중 하나 (선택 사항)"],
        +                  "문자열: Table을 저장할 파일명",
        +                  "문자열: 可以是 \"tsv\", \"csv\", \"html\" 중 하나 (선택 사항)"],
               "returns": ""
             },
        -      
        -      
        -// IO > Table
        -      
        -      
        +
             "p5.Table": {
               "description": "테이블 객체는 기존의 스프레트 시트처럼 복수의 행과 열에 데이터를 저장합니다. 동적으로 새로운 테이블을 생성하거나, 기존 파일 데이터를 사용하여 생성할 수 있습니다.",
               "params": "p5.TableRow 배열[]: p5.TableRow 객체의 배열 (선택 사항)",
               "fields": ["테이블의 행명을 담는 배열. 테이블의 헤더(header)를 함께 불러올 경우, header 매개 변수.",
        -                 "테이블의 행을 채우는 p5.TableRow 객체의 배열. getRows() 호출과 동일한 결과를 갖습니다."],
        +                  "테이블의 행을 채우는 p5.TableRow 객체의 배열. getRows() 호출과 동일한 결과를 갖습니다."],
               "methods":["addRow()를 사용하여 p5.Table 객체에 새로운 행 데이터를 추가할 수 있습니다. 기본값으로 빈 행이 생성됩니다. 일반적으로, TableRow 객체에 있는 새로운 행에 레퍼런스를 저장하고 (위의 예제 중 newRow 참고), set()을 사용하여 각각의 개별값을 설정합니다. p5.TableRow 객체를 매개 변수로 지정할 경우, 행을 복제하여 테이블에 추가합니다.",
        -                 "테이블 객체에서 행을 제거합니다.",
        -                 "지정된 p5.TableRow에 레퍼런스를 반환합니다. 반환된 레퍼런스는 지정된 행의 값을 받아오거나 설정할 때 사용할 수 있습니다.",
        -                 "테이블의 모든 행을 받아옵니다. p5.TableRow 배열들을 반환합니다.",
        -                 "지정된 값을 포함하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 여러 개의 행들이 지정된 값을 포함하더라도, 오직 1번째 행만 반환됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        -                 "지정된 값을 포함하는 테이블 행들을 검색하고, 해당 행들의 레퍼런스를 반환합니다. 반환된 배열은 위의 예제처럼 모든 행을 반복 처리하는 데에 사용됩니다.ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        -                 "지정된 정규 표현식과 매칭하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 반환된 배열은 모든 행을 반복 처리하는 데에 사용됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        -                 "특정 열의 모든 값들을 가져와 배열로 반환합니다. 열은 그 ID 또는 제목(title)으로 지정가능합니다.",
        -                 "테이블로부터 모든 행을 제거합니다. 모든 행들이 제거되어도 열과 열 제목은 유지됩니다.",
        -                 "addColumn()을 사용하여 p5.Table 객체에 새로운 열 데이터를 추가할 수 있습니다. 일반적으로 열 제목을 설정하여 이후 쉽게 참조되도록 합니다. (별도의 제목을 지정하지 않는 경우, 새로운 열의 제목은 null이 됩니다.)",
        -                 "테이블의 전체 열 개수를 반환합니다.",
        -                 "테이블의 전체 행 개수를 반환합니다.",
        -                 "지정된 문자(또는 '토큰')을 제거합니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        -                 "문자열 테이블 값에서 스페이스나 탭과 같은 선행 및 후행 공백을 자릅니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        -                 "removeColumn()을 사용하여 테이블 객체로부터 특정 열을 제거합니다. 제거될 열은 그 제목(문자열) 또는 인덱스 값(정수)로 식별할 수 있습니다. removeColumn(0)은 1번째 열을, removeColumn(1)은 2번째 열을 제거합니다.",
        -                 "테이블 중 지정된 행과 열에 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "테이블 중 지정된 행과 열에 실수(float)값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "테이블 중 지정된 행과 열에 문자열 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "테이블 중 지정된 행과 열에 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "이블 중 지정된 행과 열에 실수(float)값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "테이블 중 지정된 행과 열에 문자열 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",",
        -                 "모든 테이블 데이터를 받아와 객체로 반환합니다. 열 이름이 전달될 경우, 각 행 객체는 해당 속성을 제목으로 저장합니다.",
        -                 "모든 테이블 데이터를 받아와 다차원 배열로 반환합니다."
        -                 ] 
        +                  "테이블 객체에서 행을 제거합니다.",
        +                  "지정된 p5.TableRow에 레퍼런스를 반환합니다. 반환된 레퍼런스는 지정된 행의 값을 받아오거나 설정할 때 사용할 수 있습니다.",
        +                  "테이블의 모든 행을 받아옵니다. p5.TableRow 배열들을 반환합니다.",
        +                  "지정된 값을 포함하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 여러 개의 행들이 지정된 값을 포함하더라도, 오직 1번째 행만 반환됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                  "지정된 값을 포함하는 테이블 행들을 검색하고, 해당 행들의 레퍼런스를 반환합니다. 반환된 배열은 위의 예제처럼 모든 행을 반복 처리하는 데에 사용됩니다.ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                  "지정된 정규 표현식과 매칭하는 테이블 행 중 1번째 행을 검색하고, 해당 행의 레퍼런스를 반환합니다. 반환된 배열은 모든 행을 반복 처리하는 데에 사용됩니다. ID 또는 제목(title) 설정을 통해 검색할 열도 지정가능합니다.",
        +                  "특정 열의 모든 값들을 가져와 배열로 반환합니다. 열은 그 ID 또는 제목(title)으로 지정가능합니다.",
        +                  "테이블로부터 모든 행을 제거합니다. 모든 행들이 제거되어도 열과 열 제목은 유지됩니다.",
        +                  "addColumn()을 사용하여 p5.Table 객체에 새로운 열 데이터를 추가할 수 있습니다. 일반적으로 열 제목을 설정하여 이후 쉽게 참조되도록 합니다. (별도의 제목을 지정하지 않는 경우, 새로운 열의 제목은 null이 됩니다.)",
        +                  "테이블의 전체 열 개수를 반환합니다.",
        +                  "테이블의 전체 행 개수를 반환합니다.",
        +                  "지정된 문자(또는 '토큰')을 제거합니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        +                  "문자열 테이블 값에서 스페이스나 탭과 같은 선행 및 후행 공백을 자릅니다. 별도의 열을 지정하지 않는 경우, 모든 행과 열 속 값들이 처리됩니다. 열은 ID 또는 제목으로 참조가능합니다.",
        +                  "removeColumn()을 사용하여 테이블 객체로부터 특정 열을 제거합니다. 제거될 열은 그 제목(문자열) 또는 인덱스 값(정수)로 식별할 수 있습니다. removeColumn(0)은 1번째 열을, removeColumn(1)은 2번째 열을 제거합니다.",
        +                  "테이블 중 지정된 행과 열에 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "테이블 중 지정된 행과 열에 실수(float)값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "테이블 중 지정된 행과 열에 문자열 값을 저장합니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "테이블 중 지정된 행과 열에 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "이블 중 지정된 행과 열에 실수(float)값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "테이블 중 지정된 행과 열에 문자열 값을 받아옵니다. 행은 ID로, 열은 ID 또는 제목으로 지정가능합니다.",
        +                  "모든 테이블 데이터를 받아와 객체로 반환합니다. 열 이름이 전달될 경우, 각 행 객체는 해당 속성을 제목으로 저장합니다.",
        +                  "모든 테이블 데이터를 받아와 다차원 배열로 반환합니다."
        +                  ] 
             },
               
             "p5.TableRow": {
        @@ -2031,13 +1910,9 @@
                           "TableRow의 지정된 열에 문자열 값을 저장합니다. 열은 ID 또는 제목으로 지정가능합니다.",
                           "TableRow의 지정된 열로부터 값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다. ",
                           "TableRow의 지정된 열로부터 실수(float)값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다.",
        -                 "TableRow의 지정된 열로부터 문자열 값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다."]
        +                  "TableRow의 지정된 열로부터 문자열 값을 받습니다. 열은 ID 또는 제목으로 지정가능합니다."]
             },
               
        -
        -// IO > Time & Date
        -      
        -      
             "day": {
               "description": "p5.js는 컴퓨터의 시계와도 통신합니다. day() 함수는 현재 날짜를 1부터 31에 해당하는 값으로 반환합니다.",
               "returns": "정수: 현재 날짜"
        @@ -2067,8 +1942,6 @@
               "returns": "정수: 현재 년도"
             },
         
        -// Math > Calculation      
        -      
             "abs": {
               "description": "숫자의 절대값(크기)을 계산합니다. Math.abs()에 매핑합니다. 숫자의 절대값은 항상 양수입니다.",
               "params": ["숫자: 계산할 숫자"],
        @@ -2082,18 +1955,18 @@
             "constrain": {
               "description": "값을 최소값과 최대값 사이에 제한합니다.",
               "params": ["수자: 제한할 숫자",
        -                 "숫자: 최소 한계",
        -                 "숫자: 최대 한계"],
        +                  "숫자: 최소 한계",
        +                  "숫자: 최대 한계"],
               "returns": "숫자: 제한된 숫자"
             },
             "dist": {
               "description": "2차원 또는 3차원 상 두 점 사이의 거리를 계산합니다.",
               "params": ["숫자: 1번째 점의 x좌표값",
        -                 "숫자: 1번째 점의 y좌표값",
        -                 "숫자: 2번째 점의 x좌표값",
        -                 "숫자: 2번째 점의 y좌표값",
        -                 "숫자: 1번째 점의 z좌표값",
        -                 "숫자: 2번째 점의 z좌표값"],
        +                  "숫자: 1번째 점의 y좌표값",
        +                  "숫자: 2번째 점의 x좌표값",
        +                  "숫자: 2번째 점의 y좌표값",
        +                  "숫자: 1번째 점의 z좌표값",
        +                  "숫자: 2번째 점의 z좌표값"],
               "returns": "숫자: 두 점 사이의 거리"
             },
             "exp": {
        @@ -2109,8 +1982,8 @@
             "lerp": {
               "description": "지정된 증분(increment)을 통해 두 숫자 사이의 특정 숫자를 계산합니다. 여기서 매개 변수 amt는 두 개의 값 사이를 선형적으로 보간합니다. 예를 들어, 0.0은 첫 번째 값과 동일한 색상값을, 0.1은 첫 번째 값에 매우 가까운 색상값을, 0.5는 두 값 사이의 중간 색상값을 나타내는 식입니다. 이 때, 0 미만의 값과 1이상의 값은 지정된 2개의 숫자의 비율에 따라 자동 처리됩니다. lerp() 함수는 직선 경로를 따라 모션을 생성하고 점선을 그리는 데에 사용됩니다.",
               "params": ["숫자: 1번째 값",
        -                 "숫자: 2번째 값",
        -                 "숫자: 숫자"],
        +                  "숫자: 2번째 값",
        +                  "숫자: 숫자"],
               "returns": "숫자: 선형보간된 값"
             },
             "log": {
        @@ -2121,44 +1994,44 @@
             "mag": {
               "description": "벡터의 크기(또는 길이)를 계산합니다. 벡터는 컴퓨터 그래픽과 선형 대수에서 일반적으로 사용되며, 공간 속 방향을 뜻합니다. 벡터에는 시작점 개념이 없으므로, 그 크기는 좌표 0,0에서 x,y값까지의 거리에 비유할 수 있습니다. 이 점에서 mag()는 dist(0, 0, x, y)와 동일한 효과를 갖고 보다 간단하게 표현한 셈입니다.",
               "params": ["숫자: 1번째 값",
        -                 "숫자: 2번째 값"],
        +                  "숫자: 2번째 값"],
               "returns": "숫자: (0,0)에서 (a,b)까지의 벡터 크기"
             },
             "map": {
               "description": "숫자의 범위를 다른 범위로 다시 매핑합니다.<br><br>첫 번째 예제의 숫자 25는 화면상 좌측 상단 모퉁이(0)부터 우측 변(너비)에 이르는 범위에 해당하는데, 이는 0부터 100 사이에 해당하는 본래 범위에서 변환된 것입니다.",
               "params": ["숫자: 변환할 값",
        -                 "숫자: 값의 현재 범위의 하한",
        -                 "숫자: 값의 현재 범위의 상한",
        -                 "숫자: 값의 대상 범위의 하한",
        -                 "숫자: 값의 대상 범위의 상한",
        -                 "불리언: 값을 새로 매핑된 범위에 제한 (선택 사항)"],
        +                  "숫자: 값의 현재 범위의 하한",
        +                  "숫자: 값의 현재 범위의 상한",
        +                  "숫자: 값의 대상 범위의 하한",
        +                  "숫자: 값의 대상 범위의 상한",
        +                  "불리언: 값을 새로 매핑된 범위에 제한 (선택 사항)"],
               "returns": "숫자: 다시 매핑된 숫자"
             },
             "max": {
               "description": "일련의 숫자들 중, 가장 큰 값을 확인하고 이를 반환합니다. max() 함수는 매개 변수 Number로 지정된 모든 숫자 또는 모든 길의의 배열을 허용합니다.",
               "params": ["숫자: 비교할 숫자",
        -                 "숫자: 비교할 숫자",
        -                 "숫자 배열[]: 비교할 숫자"],
        +                  "숫자: 비교할 숫자",
        +                  "숫자 배열[]: 비교할 숫자"],
               "returns": "숫자: 최대 숫자"
             },
             "min": {
               "description": "일련의 숫자들 중, 가장 작은 값을 확인하고 이를 반환합니다. min() 함수는 매개 변수 Number로 지정된 모든 숫자 또는 모든 길의의 배열을 허용합니다.",
               "params": ["숫자: 비교할 숫자",
        -                 "숫자: 비교할 숫자",
        -                 "숫자 배열[]: 비교할 숫자"],
        +                  "숫자: 비교할 숫자",
        +                  "숫자 배열[]: 비교할 숫자"],
               "returns": "숫자: 최소 숫자"
             },
             "norm": {
               "description": "특정 범위 내의 숫자를 0과 1 범위의 값으로 정규화합니다. 이는 map(value, low, high, 0, 1)과도 동일한 효과를 갖습니다. 숫자가 0과 1 범위를 벗어나더라도, 사용자의 의도와 활용 가능성을 감안하여 0과 1 사이의 값으로 재고정하지 않습니다. (위의 예제를 참고하세요.)   ",
               "params": ["숫자: 정규화될 값",
        -                 "숫자: 값의 현재 범위 하한",
        -                 "숫자: 값의 현재 범위 상한"],
        +                  "숫자: 값의 현재 범위 하한",
        +                  "숫자: 값의 현재 범위 상한"],
               "returns": "숫자: 정규화된 숫자"
             },
             "pow": {
               "description": "pow() 함수는 지수 식을 효율적으로 사용하는 한 방법으로, 특정 숫자(또는 그 역수)를 반복하여 곱할 수 있습니다. 예를 들어, pow(3,5)는 3 x 3 x 3 x 3 x 3과 같고, pow(3,-5)는 1 / 3 x 3 x 3 x 3 x 3과 같습니다. Math.pow()에 매핑합니다. ",
               "params": ["숫자: 지수 식의 밑",
        -                 "숫자: 거듭 제곱의 지수"],
        +                  "숫자: 거듭 제곱의 지수"],
               "returns": "숫자:n^e"
             },
             "round": {
        @@ -2182,26 +2055,23 @@
                 "params": "숫자: 소수 부분 파악이 필요한 숫자",
                 "returns": "x의 소수 부분, 예: {x}"
             },
        -      
        -      
        -// Math > Vector
         
             "createVector()": {
                 "description": "새로운 p5.Vector (벡터 저장을 위한 데이터 유형)를 생성합니다. 2차원 및 3차원 벡터, 그리고 유클리드(기하학) 벡터를 제공합니다. 벡터는 크기와 방향을 모두 지닌 개체입니다.",
                 "params": ["숫자: 벡터의 x성분 (선택 사항)",
        -                   "숫자: 벡터의 y성분 (선택 사항)",
        -                   "숫자: 벡터의 z성분 (선택 사항)"],
        +                    "숫자: 벡터의 y성분 (선택 사항)",
        +                    "숫자: 벡터의 z성분 (선택 사항)"],
                 "returns": "p5.Vector"
             },
         
             "p5.Vector()": {
                 "description": "2차원 및 3차원 벡터, 특히 유클리드 (기하학) 벡터를 설명하는 클래스입니다. 벡터는 크기와 방향을 모두 지닌 개체입니다. 하지만, 그 데이터 유형은 벡터의 성분(2D의 경우 x와 y, 3D의 경우 x, y, z)을 저장합니다. 크기와 방향은 각각 mag() 및 heading() 메소드를 통해 접근할 수 있습니다.<br><br>p5.Vector는 위치, 속도, 가속을 다루는 수많은 p5.js 예제에서 사용됩니다. 예를 들어, 화면을 가로질러 움직이는 직사각형을 만들려면, 이 물체의 위치(원점에서 그 위치를 가리키는 벡터), 속도(단위 시간당 객체의 위치가 변하는 속도, 벡터로 표시), 그리고 가속도(단위 시간당 객체의 속도가 변하는 속도, 벡터로 표시)를 반드시 고려해야합니다.<br><br>벡터는 그룹화된 값들을 나타냅니다. 따라서, 전통적인 덧셈/곱셈 대신, p5.Vector 클래스 내부의 벡터 수학 메소드를 사용해서 계산해야 합니다.",
                 "params":["숫자: 벡터의 x성분 (선택 사항)",
        -                   "숫자: 벡터의 y성분 (선택 사항)",
        -                   "숫자: 벡터의 z성분 (선택 사항)"],
        +                    "숫자: 벡터의 y성분 (선택 사항)",
        +                    "숫자: 벡터의 z성분 (선택 사항)"],
                 "fields":["벡터의 x성분",
        -                 "벡터의 y성분",
        -                 "벡터의 z성분"],
        +                  "벡터의 y성분",
        +                  "벡터의 z성분"],
                 "methods":["String(v) 또는 v.toString()을 호출하여 벡터 v의 문자열 표현을 반환합니다. 주로 콘솔창에서 벡터 로그를 확인할 때 사용됩니다.",
                           "두 세개의 개별 변수, p5.Vector 데이터, 또는 실수(float) 배열의 값들을 사용하여 벡터의 x, y, z성분을 설정합니다.",
                           "벡터의 복사본을 가져와 p5.Vector 객체를 반환합니다.",
        @@ -2227,23 +2097,20 @@
                           "p5.Vector에 대한 평등 검사",
                           "특정 각도에서 새로운 2D 벡터를 생성합니다.",
                           "임의의 각도에서 새로운 2D 단위 벡터를 생성합니다.",
        -                  "새로운 임의의 3D 단위 벡터를 생성합니다."],
        +                  "새로운 임의의 3D 단위 벡터를 생성합니다."]
             },
         
        -
        -// Math > Noise
        -      
             "noise": {
               "description": "지정된 좌표에서의 펄린 노이즈(Perlin noise)값을 반환합니다. 일반 random() 함수에 비해, 펄린 노이즈는 고조파 연속 숫자를 보다 자연스러운 시퀀스로 생성합니다. 켄 펄린(Ken Perlin)이 1980년대에 발명하였으며, 그래픽 응용 프로그램상 절차적 텍스처, 자연스러운 모션, 형상, 지형 등을 생성하는 데에 사용됩니다.<br><br><b>random()</b> 함수와의 주요 차이점은, 펄린 노이즈가 반-무작위 값을 갖는 고정 좌표쌍을 n차원의 무한 공간에서 정의한다는 점에 있습니다. (이는 프로그램의 수명 동안에만 고정되며, 관련해서는 noiseSeed()함수를 참고하세요.) p5.js는 사용자가 지정한 좌표 개수에 따라 1D, 2D, 3D 노이즈를 계산할 수 있습니다. 결과값은 항상 0.0과 1.0 사이입니다. 위의 예제처럼, 노이즈값은 공간 이동을 통해 애니메이션화 될 수 있습니다. 2차원 및 3차원 역시 시간으로 해석될 수 있습니다.<br><br>노이즈 함수의 주파수 사용은 실제 오디오 신호와 유사하게 구성됩니다. 물리학에서의 고조파 개념과 마찬가지로, 펄린 노이즈는 여러 옥타브에 걸쳐 계산되며, 최종 결과 생성을 위해 모든 옥타브를 합칩니다. <br><br>입력 좌표값의 크기를 통해서도 결과 시퀀스의 문자를 조정할 수 있습니다. 함수는 무한 공간 속에서 작동하기 때문에 좌표값이 크게 중요하지 않지만, 연속된 좌표들 사이의 거리만큼은 중요합니다 (예: 반복문 내에서 noise()를 실행하는 경우). 일반적으로, 좌표들 간의 거리차가 적을수록 노이즈 시퀀스가 더 매끄러워집니다. 0.0005부터 0.03 사이의 단계가 대부분의 응용 프로그램에서 사용하기에 가장 적합하나, 사용에 따라 달라질 수 있습니다.",
               "params": ["숫자: 노이즈 공간 속 x좌표값",
        -                 "숫자: 노이즈 공간 속 y좌표값",
        -                 "숫자: 노이즈 공간 속 z좌표값"],
        +                  "숫자: 노이즈 공간 속 y좌표값",
        +                  "숫자: 노이즈 공간 속 z좌표값"],
               "returns": "숫자: 지정된 좌표에서의 펄린 노이즈 값 (0과 1 사이)"
             },
             "noiseDetail": {
               "description": "펄린 노이즈 함수로 생성되는 문자와 세부 레벨을 조정합니다. 물리학의 고조파처럼, 노이즈 역시 여러 옥타브에 걸쳐 계산됩니다. 낮은 옥타브는 출력 신호에 더 많이 기여함으로써 노이즈의 전체 강도를 정의하는 반면, 높은 옥타브는 노이즈 시퀀스에서 세밀한 디테일을 만듭니다.<br><br>기본값으로, 노이즈는 4 옥타브 이상으로 계산되고 각 옥타브는 이전 옥타브의 정확히 절반을 기여하도록 설정됩니다. 즉, 2번째 옥타브는 1번째 옥타브의 강도 50%에서 시작하는 식입니다. 이러한 감소량은 추가 매개 변수를 통해 변경할 수 있습니다. 예: 감소 계수 0.75는 각 옥타브가 이전 하위 옥타브의 75%만큼 영향(25% 감소)을 받는다는 것을 뜻합니다. 0.0과 1.0 사이의 모든 값이 유효하나, 0.5보다 큰 값은 noise()에 의해 반환된 1.0보다 더 큰 결과값을 가질 수 있는 점에 유의하세요.<br><br>이처럼 매개 변수를 변경하여, noise() 함수가 생성한 신호를 매우 구체적인 요구와 특성에 맞게 조정할 수 있습니다.",
               "params": ["숫자: 노이즈가 사용한 옥타브 개수",
        -                 "숫자: 각 옥타브에 대한 감소 계수"],
        +                  "숫자: 각 옥타브에 대한 감소 계수"],
               "returns": ""
             },
             "noiseSeed": {
        @@ -2252,9 +2119,6 @@
               "returns": ""
             },
         
        -// Math > Random
        -      
        -
             "randomSeed": {
               "description": "random() 함수의 시드(seed) 값을 설정합니다.<br>기본적으로, random()은 소프트웨어 프로그램이 실행될 때마다 매번 다른 결과를 생성합니다. 매 실행마다 동일한 유사-난수(random)를 반환하려면 매개 변수 value를 상수로 설정하세요. ",
               "params": ["숫자: 시드값"],
        @@ -2263,20 +2127,17 @@
             "random": {
               "description": "임의의 부동 소수점 숫자, 즉 실수(float)를 반환합니다.<br>0, 1, 또는 2개의 인수를 사용합니다.<br>별도의 인수를 지정하지 않을 경우, 0부터 1미만 사이의 난수(random)를 반환합니다.<br>1개의 인수를 숫자로 지정한 경우, 0부터 해당 숫자 미만 사이의 난수를 반환합니다.<br>1개의 인수를 배열로 지정한 경우, 해당 배열로부터 임의의 요소를 반환합니다.<br>2개의 인수를 지정한 경우, 1번째 인수에서 2번째 인수 미만 사이의 난수를 반환합니다.",
               "params": ["숫자: (해당 숫자를 포함한) 하한 (선택 사항)",
        -                 "숫자: (해당 숫자를 제외한) 상한 (선택 사항)",
        -                 "배열: 요소를 골라올 배열"],
        +                  "숫자: (해당 숫자를 제외한) 상한 (선택 사항)",
        +                  "배열: 요소를 골라올 배열"],
               "returns": "숫자: 난수"
             },
             "randomGaussian": {
               "description": "가우스 및 정규 분포에 맞는 난수를 반환합니다. randomGaussian()이 반환할 수 있는 최소값이나 최대값 개념은 이론상 없습니다. 평균으로부터 멀리 떨어진 값이 반환될 확률은 매우 낮고, 평균 근처의 숫자가 반환될 확률이 높습니다. <br><br> 0, 1, 또는 2개의 인수를 사용합니다.<br>별도의 인수를 지정하지 않을 경우, 평균으로 0을, 표준 편차로 1을 반환합니다.<br>1개의 인수를 지정한 경우, 해당 인수가 평균입니다. (표준 편차는 1)<br>2개의 인수를 지정한 경우, 1번째 인수는 평균, 2번째 인수는 표준 편차입니다.",
               "params": ["숫자: 평균",
        -                 "숫자: 표준 편차"],
        +                  "숫자: 표준 편차"],
               "returns": "숫자: 난수"
             },
               
        -      
        -// Math > Trigonometry
        -      
             "acos": {
               "description": "cos()함수의 역으로, 값의 아크 코사인을 반환합니다. 이 함수는 -1부터 1까지 범위 내의 값을 예상하고, 0부터 PI(3.1415927)까지 범위 내의 값을 반환합니다.",
               "params": "숫자: 아크 코사인으로 반환될 값",
        @@ -2295,7 +2156,7 @@
             "atan2": {
               "description": "양의 x축상의 특정 좌표로부터 좌표 원점을 향한 각도(부채각, radian)를 계산합니다. 값은 PI부터 -PI까지 범위 내의 실수(float)로 반환됩니다. atan2() 함수는 도형을 커서 위치에 맞추는 데에 자주 사용됩니다.<br><br>참고: 접선 계산 방식에 따라 1번째 매개 변수를 점의 y좌표로, 2번째 매개 변수를 x좌표로 지정합니다.",
               "params": ["숫자: 점의 y좌표값",
        -                 "숫자: 점의 x좌표값"],
        +                  "숫자: 점의 x좌표값"],
               "returns": "지정된 점의 아크 탄젠트"
             },
             "cos": {
        @@ -2321,7 +2182,7 @@
             "radians": {
               "description": "도(degree) 측정값을 부채각(radian) 단위에 해당하는 값으로 변환합니다. 부채각과 도는 같은 것을 측정하는 2개의 다른 단위입니다. 원은 360도이면서 동시에 2*PI 부채각이기도 합니다. 또, 90° = PI/2 = 1.5707964 가 성립합니다. 이 함수는 현재 설정된 angleMode를 반영하지 않습니다",
               "params": "숫자: 부채각 단위로 변환할 도 값",
        -      "returns": "숫자: 변환된 각도",
        +      "returns": "숫자: 변환된 각도"
             },
             "angleMode": {
               "description": "p5의 현재 모드를 설정합니다. 기본 모드는 RADIANS(부채각) 입니다.",
        @@ -2329,13 +2190,10 @@
               "returns": ""
             },
               
        -      
        -// Typography > Attributes
        -      
             "textAlign": {
               "description": "텍스트 그리기에 대한 현재 정렬을 설정합니다. horizAlign(LEFT, CENTER, 또는 RIGHT)와 vertAlign(TOP, BOTTOM, CENTER, 또는 BASELINE)이라는 2개의 인수를 받습니다.<br><br>매개 변수 horizAlign은 text() 함수의 x값을, 매개 변수 vertAlign은 y값을 참조합니다.<br><br>따라서, textAlign(LEFT)는 텍스트의 왼쪽 가장자리를 text()에서 지정된 x값에 정렬합니다. textAlign(RIGHT, TOP)은 텍스트의 오른쪽 가장자리를 x값에, 텍스트의 가장자리 위쪽을 y값에 정렬합니다.",
               "params": ["상수: 가로 정렬, LEFT, CENTER, 또는 RIGHT 중 하나",
        -                 "상수: 세로 정렬, TOP, BOTTOM, CENTER, 또는 BASELINE 중 하나"],
        +                  "상수: 세로 정렬, TOP, BOTTOM, CENTER, 또는 BASELINE 중 하나"],
               "returns": ""
             },
             "textLeading": {
        @@ -2367,14 +2225,11 @@
               "returns": "숫자:"
             },
               
        -      
        -// Typography > Loading & Displaying
        -      
             "loadFont": {
               "description": "파일 또는 URL로부터 폰트 파일(.otf, .ttf)을 불러오고, PFont 객체를 반환합니다. <br><br>이는 비동기적 메소드로, 스케치상의 다음 코드 줄이 실행되기 전에 함수 실행이 완료되지 않을 수 있습니다.<br><br>폰트의 경로는 스케치상 링크된 HTML 파일을 기준으로 합니다. 브라우저의 내장 보안으로 인해 URL 또는 다른 원격 경로에서 폰트를 불러오는 것이 차단될 수 있습니다.<br><br>[1번째 예제] preload() 함수 안에 loadJSON() 함수를 호출하여, 모든 불러오기 작업이 setup()과 draw() 함수가 호출되기에 앞서 완료되도록 처리합니다.<br><br>[2번째 예제] preload() 함수 밖의 영역에서 콜백 함수를 2번째 예제와 같이 작성하여 객체를 처리할 수 있습니다.",
               "params": ["문자열: 불러올 파일명 또는 URL",
        -                 "함수: loadFont()가 완료된 이후 실행될 함수 (선택 사항)",
        -                 "함수: 에러 발생시 실행될 함수"],
        +                  "함수: loadFont()가 완료된 이후 실행될 함수 (선택 사항)",
        +                  "함수: 에러 발생시 실행될 함수"],
               "returns": "p5.Font: p5.Font 객체"
             },
               
        @@ -2382,16 +2237,16 @@
             "text": {
               "description": "화면에 텍스트를 그립니다. 1번째 매개 변수로 지정된 정보를 추가 매개 변수로 지정한 화면 위치에 나타냅니다. textFont() 함수로 별도 폰트를 지정하지 않을 경우, 기본 폰트가 사용됩니다. textSize()로 별도의 글자 크기를 지정하지 않을 경우, 기본 글자 크기가 사용됩니다. fill() 함수로 텍스트의 색상을 변경할 수 있습니다. stroke() 및 strokeWeight() 함수로 텍스트의 윤곽선을 변경할 수 있습니다.<br><br>텍스트는 textAlign() 함수의 매개 변수에 따라 좌표를 기준으로 왼쪽, 오른쪽, 그리고 중심에서 텍스트를 그릴 수 있습니다.<br><br>매개 변수 x2와 y2는 화면에 나타날 텍스트 상자의 영역을 정의하며, 문자열 데이터에만 사용됩니다. 이 매개 변수들은 현재 rectMode() 설정에 따라 해석됩니다. 사용자가 지정한 텍스트 상자 크기에 맞지 않는 텍스트는 그려지지 않습니다. 별도의 x2와 y2를 지정하지 않을 경우, 기준선 정렬이 기본값으로 제공됩니다. 즉, 텍스트가 x와 y로부터 위쪽으로 그려집니다.<br><br>WebGL: 개방형(opentype)/트루 타입(truetype) 폰트만 지원됩니다. 반드시 loadFont() 메소드를 사용하여 폰트를 불러와야 합니다. (위의 예제 참고) stroke()는 현재 WebGL 모드에서 아무런 효과를 갖지 않습니다.",
               "params": ["문자열|객체|배열|숫자|불리언: 표시할 영숫자 기호",
        -                 "숫자: 텍스트의 x좌표값",
        -                 "숫자: 텍스트의 y좌표값",
        -                 "숫자: 기본값은 텍스트 상자의 너비, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)",
        -                 "숫자: 기본값은 텍스트 상자의 높이, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)"],
        +                  "숫자: 텍스트의 x좌표값",
        +                  "숫자: 텍스트의 y좌표값",
        +                  "숫자: 기본값은 텍스트 상자의 너비, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)",
        +                  "숫자: 기본값은 텍스트 상자의 높이, 자세한 사항은 rectMode()를 확인하세요. (선택 사항)"],
               "returns": ""
             },
             "textFont": {
               "description": "text() 함수로 그릴 현재 폰트를 설정합니다.<br><br>WebGL: loadFont()를 통해 불러온 폰트만 지원합니다.",
               "params": ["객체|문자열: loadFont()로 불러온 폰트 또는 <a href = 'https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Fundamentals#Web_safe_fonts'>웹 안전 폰트</a>(일반적으로 모든 시스템에서 사용가능한 폰트)를 나타내는 문자열",
        -                 "숫자: 사용할 폰트 크기 (선택 사항)"],
        +                  "숫자: 사용할 폰트 크기 (선택 사항)"],
               "returns": "현재 폰트"
             },
             "p5.Font": {
        @@ -2399,11 +2254,9 @@
               "params": "P5: p5 인스턴스 포인터 (선택 사항)",
               "fields": "기본 개방형 글꼴 구현",
               "methods": ["이 폰트로 지정된 텍스트 문자열에 대한 바운딩 박스를 반환합니다. (현재 텍스트 한 줄씩만 지원합니다.)",
        -                 "지정된 텍스트 경로를 따르는 점들의 배열을 계산합니다."]
        +                  "지정된 텍스트 경로를 따르는 점들의 배열을 계산합니다."]
             },
        -      
        -      
        -// Lights, Camera > Interaction
        +
             "orbitControl":{
                 "description": "마우스 또는 트랙 패드로 3D 스케치 주위를 움직일 수 있습니다. 마우스 왼쪽 버튼을 클릭 후 드래그하면 스케치 중심을 기준으로 카메라 위치가 회전합니다. 마우스 오른쪽 버튼을 클릭 후 드래그하면 회전없이 카메라 위치가 이동합니다. 마우스 휠(스크롤)을 사용하면 카메라 위치가 스케치와 더 가까워지거나 멀어집니다. 함수 호출시, x축과 y축상의 마우스 이동에 대한 민감도를 매개 변수를 사용할 수 있습니다. 별도로 지정한 매개 변수없이 함수를 호출하면 orbitControl(1,1)과 동일한 효과를 갖습니다. 민감도 매개 변수를 음수로 입력하면 각 축의 이동 방향을 지정할 수 있습니다.",
                 "params":["숫자: X축상의 마우스 이동에 대한 민감도 (선택 사항)",
        @@ -2432,18 +2285,17 @@
             "noDebugMode":{
                 "description": "3D 스케치의 debugMode() 실행을 종료합니다."
             },
        -// Lights, Camera > Lights
               
             "ambientLight": {
               "description": "색상을 갖는 앰비언트 조명을 생성합니다. 앰비언트 조명은 별도의 광원없이 캔버스의 모든 영역에서 나오는 조명을 뜻합니다.",
               "params": ["숫자: 현재 색상 범위에 따른 빨강값 또는 색조값",
        -                 "현재 색상 범위에 따른 초록값 또는 채도값",
        -                 "현재 색상 범위에 따른 파랑값 또는 밝기값",
        -                 "숫자: 알파값 (선택 사항)",
        -                 "문자열: 색상 문자열",
        -                 "숫자: 회색값",
        -                 "숫자 배열[]: 색상의 R, G, B & 알파값 성분을 포함한 배열",
        -                 "p5.Color: 앰비언트 조명 색상"],
        +                  "현재 색상 범위에 따른 초록값 또는 채도값",
        +                  "현재 색상 범위에 따른 파랑값 또는 밝기값",
        +                  "숫자: 알파값 (선택 사항)",
        +                  "문자열: 색상 문자열",
        +                  "숫자: 회색값",
        +                  "숫자 배열[]: 색상의 R, G, B & 알파값 성분을 포함한 배열",
        +                  "p5.Color: 앰비언트 조명 색상"],
               "returns": ""
             },
               
        @@ -2462,13 +2314,13 @@
             "directionalLight": {
               "description": "색상과 방향을 갖는 디렉셔널 조명을 생성합니다.<br>한 번에 최대 5개의 directionalLight를 활성화할 수 있습니다.",
               "params": ["숫자: (현재 색상 모드에 따른) 빨강값 또는 색조값",
        -                 "숫자: 초록값 또는 채도값",
        -                 "숫자: 파랑값 또는 밝기값",
        -                 "p5.Vector:조명의 방향",
        -                 "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값",
        -                 "숫자: x축 방향",
        -                 "숫자: y축 방향",
        -                 "숫자: z축 방향"],
        +                  "숫자: 초록값 또는 채도값",
        +                  "숫자: 파랑값 또는 밝기값",
        +                  "p5.Vector:조명의 방향",
        +                  "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값",
        +                  "숫자: x축 방향",
        +                  "숫자: y축 방향",
        +                  "숫자: z축 방향"],
               "returns": ""
             },
             "pointLight": {
        @@ -2483,7 +2335,7 @@
                           "숫자 배열[]|문자열|p5.Color: 색상 배열, CSS 색상 문자열, 또는 p5.Color 값"],
               "returns": ""
             },
        -      
        +    
             "lights":{
                 "description":"기본 앰비언트 조명과 디렉셔널 조명을 설정합니다. 기본값은  ambientLight(128, 128, 128)과 directionalLight(128, 128, 128, 0, 0, -1)입니다. 반복 프로그램에서 조명의 지속성을 확보하려면 조명을 draw() 안에 작성해야 합니다. 반복 프로그램의 setup() 안에 작성할 경우, 반복문의 최초 실행시에만 조명 효과가 발생합니다."
                 
        @@ -2519,23 +2371,20 @@
                 "description": "noLights() 함수 호출 이후에 렌더링된 재질(material)들로부터 모든 조명을 제거합니다. 모든 후속 메소드에 영향을 줍니다. noLights() 이후에 작성된 조명 메소드를 호출할 경우, 스케치상 조명이 다시 활성화됩니다. "
             },
               
        -      
        -// Lights, Camera > Material
        -      
             "loadShader": {
               "description": "버텍스 및 프래그먼트 셰이더 경로로부터 커스텀 셰이더를 불러옵니다. 셰이더 파일은 배경 화면과 비동기적으로 로드되므로, 이 메소드는 preload()에서 사용해야 합니다.<br><br>현재 3가지 유형의 셰이더를 지원합니다. p5는 셰이더상 정의된 매개 변수 이름과 일치하는 버텍스, 법선(normal), 색상, 조명 속성을 자동으로 제공합니다.",
               "params": ["문자열: 버텍스 셰이더 소스 코드 파일의 경로",
        -                 "문자열: 프래그먼트 셰이더의 소스 코드 파일 경로"
        -                 "함수: 문자열: 프래그먼트 셰이더의 소스 코드 파일 경로"
        -                 "함수: loadShader()가 완료된 이후 실행될 함수. 성공시, 셰이더 객체를 1번재 인수로 전달 (선택 사항)",
        -                 "함수: loadShader 내에서 에러 발생시 실행될 함수. 에러 발생시, 에러를 1번째 인수로 전달 (선택 사항)"
        +                  "문자열: 프래그먼트 셰이더의 소스 코드 파일 경로",
        +                  "함수: 문자열: 프래그먼트 셰이더의 소스 코드 파일 경로",
        +                  "함수: loadShader()가 완료된 이후 실행될 함수. 성공시, 셰이더 객체를 1번재 인수로 전달 (선택 사항)",
        +                  "함수: loadShader 내에서 에러 발생시 실행될 함수. 에러 발생시, 에러를 1번째 인수로 전달 (선택 사항)"
                         ],
               "returns": "p5.Shader: 지정된 버텍스 및 프래그먼트 셰이더 파일로부터 생성된 셰이더 객체"
             },
             "createShader": {
               "description": "",
               "params": ["문자열: 버텍스 셰이더의 소스 코드",
        -                 "문자열: 프래그먼트 셰이더의 소스 코드"],
        +                  "문자열: 프래그먼트 셰이더의 소스 코드"],
               "returns": "p5.Shader: 지정된 버텍스 및 프래그먼트 셰이더 파일로부터 생성된 셰이더 객체"
             },
             "shader": {
        @@ -2568,9 +2417,6 @@
                         "상수: CLAMP, REPEAT, 또는 MIRROR 중 하나 (선택 사항)"],
               "returns": ""
             },
        -      
        -      
        -      
             "ambientMaterial": {
               "description": "지정된 색상의 도형에 입힐 앰비언트 재질입니다. 앰비언트 재질은 앰비언트 조명 아래에서 객체가 반사하는 색상을 정의합니다. 예를 들어, 객체의 앰비언트 재질이 순수 빨강이고 앰비언트 조명이 순수 초록인 경우, 객체는 빛을 반사하지 않습니다. <a href ='https://p5js.org/ko/examples/3d-materials.html'>사용가능한 모든 재질</a>을 확인하세요.",
               "params": ["숫자: 회색값, (현재 색상 모드에 따른) 빨강값 또는 색조값",
        @@ -2602,8 +2448,8 @@
             "p5.Geometry": {
               "description": "p5 기하 클래스",
               "params": ["정수: 수평 표면 위의 꼭지점 개수 (선택 사항)",
        -                 "정수: 수직 표면 위의 꼭지점 개수 (선택 사항)",
        -                 "함수: 객체를 인스턴스화할 때 호출할 함수"],
        +                  "정수: 수직 표면 위의 꼭지점 개수 (선택 사항)",
        +                  "함수: 객체를 인스턴스화할 때 호출할 함수"],
               "methods": ["",
                           "꼭지점 당 부드러운 법선을 각 면의 평균으로서 계산합니다.",
                           "꼭지점 법선의 평균을 구합니다. 곡면에 사용됩니다.",
        @@ -2617,49 +2463,47 @@
               "문자열: 프래그먼트 셰이더의 소스 코드 (문자열 형식)"],
               "methods": ["gl.uniform 함수를 감싸는 래퍼입니다. 정형의 정보를 셰이더에 저장하여, 데이터의 유형 검사를 수행하고 적절한 함수를 호출할 수 있습니다."]
             },
        -   
        -//Lights, Camera > Camera
               
             "camera": {
               "description": "3D 스케치의 카메라 위치를 설정합니다. 이 함수의 매개 변수들은 카메라의 위치, 스케치의 중심(카메라가 가리키는 위치), 그리고 위쪽 방향(카메라의 오리엔테이션)을 정의합니다. <br><br>이 함수는 카메라 이동을 시뮬레이션하여, 객체를 다양한 각도에서 볼 수 있도록 합니다. 객체 자체가 아닌 카메라를 움직이는 점에 유의하세요. 예를 들어, centerX 값이 양수인 경우, 카메라는 스케치의 우측으로 회전하여 마치 객체가 왼쪽으로 움직이듯 보이게 합니다.<br><br>이 <a href = 'https://www.openprocessing.org/sketch/740258'>예제</a>에서 카메라의 위치 이동 방식을 확인하세요.<br><br>별도의 인수를 지정하지 않는 경우, 함수는 camera (0, 0, (height / 2.0) / tan (PI * 30.0 / 180.0), 0, 0, 0, 0, 1, 0)에 해당하는 기본 카메라를 생성합니다.",
               "params": ["숫자: x축에서의 카메라 위치값 (선택 사항)",
        -                 "숫자: y축에서의 카메라 위치값 (선택 사항)",
        -                 "숫자: z축에서의 카메라 위치값 (선택 사항)",
        -                 "숫자: 스케치 중심의 x좌표값 (선택 사항)",
        -                 "숫자: 스케치 중심의 y좌표값 (선택 사항)",
        -                 "숫자: 스케치 중심의 z좌표값 (선택 사항)",
        -                 "숫자: 카메라로부터 위쪽 방향의 x성분 (선택 사항)",
        -                 "숫자: 카메라로부터 위쪽 방향의 y성분 (선택 사항)",
        -                 "숫자: 카메라로부터 위쪽 방향의 z성분 (선택 사항)"],
        +                  "숫자: y축에서의 카메라 위치값 (선택 사항)",
        +                  "숫자: z축에서의 카메라 위치값 (선택 사항)",
        +                  "숫자: 스케치 중심의 x좌표값 (선택 사항)",
        +                  "숫자: 스케치 중심의 y좌표값 (선택 사항)",
        +                  "숫자: 스케치 중심의 z좌표값 (선택 사항)",
        +                  "숫자: 카메라로부터 위쪽 방향의 x성분 (선택 사항)",
        +                  "숫자: 카메라로부터 위쪽 방향의 y성분 (선택 사항)",
        +                  "숫자: 카메라로부터 위쪽 방향의 z성분 (선택 사항)"],
               "returns": ""
             },
             "perspective": {
               "description": "3D 스케치의 카메라 투시 투영법을 설정합니다. 이 투영법은 거리 단축 착시효과를 통해 깊이감을 나타냅니다. 카메라로부터 가까운 객체는 실제 크기로 보이고, 멀리 떨어진 객체는 더 작아 보입니다. 이 함수의 매개 변수는 수직 시야, 종횡비(일반적으로, 너비/높이), 그리고 근거리 및 원거리에서 잘리는 평면을 통해 보이는 (즉, 카메라가 보는), 절두체 구도(카메라가 객체를 보는, 잘린 피라미드형 구도)를 정의합니다.<br><br>별도의 인수를 지정하지 않는 경우, 기본값은 perspective(PI/3.0, width/height, eyeZ/10.0, eyeZ10.0)과도 동일한 효과를 가지며, 여기서 eyeZ는((height/2.0) / tan(PI60.0/360.0))과 같습니다.",
               "params": ["숫자: 하단에서 상단에 이르는 카메라의 절두체형 수직 시야각, angleMode 단위에 해당 (선택 사항)",
        -                 "숫자: 카메라의 절두체형 종횡비 (선택 사항)",
        -                 "숫자: 절두 근거리 길이 (선택 사항)",
        -                 "숫자: 절두 원거리 길이 (선택 사항)"],
        +                  "숫자: 카메라의 절두체형 종횡비 (선택 사항)",
        +                  "숫자: 절두 근거리 길이 (선택 사항)",
        +                  "숫자: 절두 원거리 길이 (선택 사항)"],
               "returns": ""
             },
             "ortho": {
               "description": "3D 스케치의 카메라 직교 투영법을 설정하고, 객체에 대한 상자 모양의 절두체 구도를 정의합니다. 이 투영법은 동일한 차원상의 객체들을 카메라로부터 떨어져있는 거리와 상관없이 모두 동일한 크기로 나타냅니다. 이 함수의 매개 변수는 좌우가 최소 및 최대 x값이고, 상하가 최소 및 최대 y값이며, 원근이 최소 및 최대 z값인 절두체 구도를 지정합니다. 별도의 매개 변수를 지정하지 않는 경우, 기본값은 ortho(-width/2, width/2, -height/2, height/2)입니다.",
               "params": ["숫자: 카메라 절두체의 왼쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 먼 평면 (선택 사항)"],
        +                  "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 먼 평면 (선택 사항)"],
               "returns": ""
             },
               
             "frustrum":{
                 "description":"매개 변수에 따른 원근 매트릭스를 설정합니다.<br>절두체는 상단이 잘린 피라미드와 유사한 형태를 갖는 도형입니다. 피라미드의 상단에 가상의 눈이 달려있다고 가정한다면, 나머지 6개의 평면은 3D 뷰를 렌더링할 때 시야를 잘라내는 평면으로서 기능합니다. 따라서, 이 잘라내기 평면들의 안쪽에 위치한 것들만 보이고, 그 바깥에 위치한 것들은 보이지 않습니다.<br>frustrum()을 통해 렌더링 화면의 원근을 변경할 수 있으나, perspective()를 사용하면 동일한 설정을 보다 간편하게 표현할 수 있습니다.",
                 "params":["숫자: 카메라 절두체의 왼쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        -                 "숫자: 카메라 절두체의 먼 평면 (선택 사항)"]
        +                  "숫자: 카메라 절두체의 오른쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 아래쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 위쪽 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 가까운 평면 (선택 사항)",
        +                  "숫자: 카메라 절두체의 먼 평면 (선택 사항)"]
             },
             "createCamera":{
                 "description":"새로운 p5.Camera 객체를 생성하고 렌더러에게 해당 카메라를 사용하도록 지시합니다. p5.Camera 객체를 반환합니다.",
        @@ -2669,24 +2513,19 @@
             "p5.Camera":{
                 "description":"p5의 <a href = 'https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5'>WebGL 모드</a>용 카메라를 위한 클래스입니다. 3D씬 렌더링에 필요한 카메라 위치, 방향, 투영 정보 등을 포함합니다.<br><br>createCamera()로 새로운 p5.Camera 객체를 생성하고, 아래의 메소드들을 통해 이를 제어할 수 있습니다. 이러한 방식으로 생성된 카메라는, 여타 메소드들을 통해 변경하지 않는 한, 화면에 기본값으로 설정된 위치 및 투시 투영법을 사용합니다. 여러 대의 카메라 생성 또한 가능한데, 이 경우 setCamera() 메소드로 현재 카메라를 설정할 수 있습니다.<br><br>참고: 아래의 메소드들은 다음 2개의 좌표계에서 작동합니다: 월드 좌표계는 X,Y,Z축 상의 원점에 대한 위치를 나타내는 반면, 로컬 좌표계는 카메라 시점에서의 위치(좌-우, 위-아래, 앞-뒤)를 나타냅니다. move() 메소드는 카메라의 자체 축을 따라 움직이는 반면, setPosition()은 월드 스페이스에서의 카메라의 위치를 설정합니다.",
                 "methods":["p5.Camera 객체의 투시 투영법을 설정하고, perspective() 구문에 따라 해당 투영법의 매개 변수를 설정합니다.",
        -                   "p5.Camera 객체의 직교 투영법을 설정하고, ortho() 구문에 따라 해당 투영법의 매개 변수를 설정합니다.",
        -                   "",
        -                   "패닝은 카메라 화면을 좌우로 회전합니다.",
        -                   "틸트는 카메라 화면을 상하로 회전합니다.",
        -                   "월드 스페이스 위치에서 보도록 카메라 방향을 조정합니다.",
        -                   "카메라의 위치와 방향을 설정합니다. p5.Camera 객체에 camera()를 호출하는 것과 동일한 효과를 갖습니다.",
        -                   "현재 카메라 방향을 유지하면서 그 로컬축을 따라 이동합니다.",
        -                   "현재 카메라 방향을 유지하면서 카메라의 위치를 월드 스페이스에서의 위치로 설정합니다."]
        -        
        +                    "p5.Camera 객체의 직교 투영법을 설정하고, ortho() 구문에 따라 해당 투영법의 매개 변수를 설정합니다.",
        +                    "",
        +                    "패닝은 카메라 화면을 좌우로 회전합니다.",
        +                    "틸트는 카메라 화면을 상하로 회전합니다.",
        +                    "월드 스페이스 위치에서 보도록 카메라 방향을 조정합니다.",
        +                    "카메라의 위치와 방향을 설정합니다. p5.Camera 객체에 camera()를 호출하는 것과 동일한 효과를 갖습니다.",
        +                    "현재 카메라 방향을 유지하면서 그 로컬축을 따라 이동합니다.",
        +                    "현재 카메라 방향을 유지하면서 카메라의 위치를 월드 스페이스에서의 위치로 설정합니다."]
             },
        -      
             "setCamera":{
                 "description":"rendererGL의 현재 카메라를 p5.Camera 객체로 설정합니다. 여러 카메라 간의 화면 전환이 가능합니다.",
                 "params":"p5.Camera: p5.Camera 객체"
                 
        -    }
        -      
        +    }  
           }
        -
        -  
         }
        \ No newline at end of file
        
        From 563d8cf1872b84b1f2bbb1ebde3a6161f965b11b Mon Sep 17 00:00:00 2001
        From: yinhwa <yinhwa.erica@gmail.com>
        Date: Wed, 1 Jul 2020 22:45:55 +0900
        Subject: [PATCH 36/36] final revision in ko.yml and ko.json
        
        ---
         src/data/ko.yml            | 170 ++++++++++++++++++-------------------
         src/data/reference/ko.json |  13 +--
         2 files changed, 93 insertions(+), 90 deletions(-)
        
        diff --git a/src/data/ko.yml b/src/data/ko.yml
        index 85892299a2..c796525df9 100644
        --- a/src/data/ko.yml
        +++ b/src/data/ko.yml
        @@ -28,13 +28,13 @@ tagline3: "프로세싱의 직관성에 자바스크립트의 강력함을 곱
         tagline4: "프로세싱의 창조성에 자바스크립트의 역동성을 곱하다*"
         tagline5: "프로세싱 커뮤니티에 자바스크립트 커뮤니티를 곱하다*"
         tagline6: "프로세싱의 강력함에 자바스크립트의 범용성을 곱하다*"
        -tagline7: "The p5.js community stands in solidarity with Black Lives Matter."
        +tagline7: "p5.js 커뮤니티는 Black Lives Matter와 연대합니다."
         
         home:
        -  blmnamelistending: "and too many more to list here..."
        -  blmstatement1: "This site is currently offline, as a small mark of respect, and expression of solidarity."
        -  blmstatement2: "remains available."
        -  blmstatement3: "Please consider donating to "
        +  blmnamelistending: "그 외 수많은 사람들이 있습니다..."
        +  blmstatement1: "조지 플로이드 사건에 대한 작은 존중과 연대의 표시로 사이트를 임시로 닫습니다."
        +  blmstatement2: "은 여전히 이용가능합니다."
        +  blmstatement3: "다음의 단체들에 대한 많은 관심과 기부가 필요합니다: "
           blacklivesmatter: "Black Lives Matter"
           naacp: "The NAACP Legal Defense and Educational Fund"
           equaljustice: "The Equal Justice Initiative"
        @@ -43,13 +43,13 @@ home:
         
           start-creating: "p5 에디터로 프로젝트 시작하기"
           p1xh1: "안녕하세요!"
        -  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 특히, 예술가, 디자이너, 교육자, 초심자, 그리고 모두에게 접근성이 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공되며, 이는 소프트웨어와 학습 도구가 모두에게 열려있어야 한다는 생각에 기반합니다."
        -  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 포함한 각종 HTML 요소를 사용할 수 있습니다."
        +  p1x1: "p5.js는 크리에이티브 코딩을 위한 자바스크립트 라이브러리입니다. 예술가, 디자이너, 교육자, 입문자, 그리고 모두에게 접근성 높고 포용적인 언어를 지향합니다. p5.js는 무료 오픈 소스로 제공되며, 이는 소프트웨어와 학습 도구가 모두에게 열려있어야 한다는 생각에 기반합니다."
        +  p1x2: "p5.js는 마치 스케치북과도 같으며 다양한 드로잉 기능을 제공합니다. p5.js를 이용하면 인터넷 브라우저 전체를 스케치북 삼아 그릴 수 있을 뿐 아니라, 텍스트, 입력, 비디오, 웹캠, 그리고 사운드 등을 비롯한 각종 HTML 요소를 사용할 수 있습니다."
           p2xh2: "커뮤니티"
        -  p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        +  p2x1: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업 등의 배경을 가진 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
           p2x2: "p5.js는 프로세싱 "
        -  p2x3: "을 오늘날의 웹에 맞게 해석한 버전이라 볼 수 있습니다. p5의 행사와 모임은 프로세싱 재단 "
        -  p2x4: "의 지원을 받아 개최됩니다."
        +  p2x3: " 을 오늘날의 웹에 맞게 해석한 버전입니다. p5의 행사와 모임은 프로세싱 재단 "
        +  p2x4: " 의 지원을 받아 개최됩니다."
           p2x5: ""
           p2x6: "커뮤니티"
           p2x7: "에 대해 더 알아보세요."
        @@ -83,87 +83,87 @@ copyright:
         
         get started:
           get-started-title: "시작하기"
        -  get-started1: "p5.js 프로젝트를 설정하고 나의 첫 스케치를 만드는 방법을 소개합니다."
        -  get-started2: ""
        +  get-started1: "p5.js 프로젝트를 에디터에 설정하고 나의 첫 스케치를 만드는 방법을 소개합니다."
        +  get-started2: "가장 쉬운 방법은 인터넷에서"
           get-started3: "p5.js 웹에디터"
        -  get-started4: "로 스케치를 만들고 싶다면 이 곳을 클릭하세요:"
        +  get-started4: "를 바로 사용하는 것입니다. 웹에디터를 켜고 "
           get-started5: "나의 첫 스케치"
        -  get-started6: ". If you would like to work on the the desktop version of p5.js you can scroll down to"
        -  get-started7: "downloading instructions"
        -  settingUp-title: "Setting up p5.js with an editor on your own computer"
        +  get-started6: "로 내려가 코드 작성법을 확인하세요. p5.js를 데스크탑 에디터에서 사용하는 방법은 여기서 확인하세요:"
        +  get-started7: "데스크탑에 다운받기"
        +  settingUp-title: "데스크탑 에디터에 p5.js 설정하기"
           download-title: "다운로드 & 파일 설정"
        -  hosted-title: "Using a hosted version of the p5.js library"
        -  download1: "The easiest way to start is by using the empty example that comes with the "
        +  hosted-title: "호스팅된 p5.js 라이브러리 사용하기"
        +  download1: ""
           download2: "p5.js complete"
        -  download3: "와 함께 제공되는 빈 예제 프로젝트를 이용해 쉽게 테스트 해보세요."
        -  download4: "그 중 index.html 파일에는 p5.js 링크가 적혀있습니다. 로딩 시간을 단축하려면 이 p5.js 링크를 간략 버전인 p5.min.js로 아래와 같이 변경하면 됩니다. "
        -  download5: "또는, p5.js 파일의 온라인 링크를 입력하는 방법도 있습니다. p5.js의 모든 버전은 CDN (Content Delivery Network)에 저장되어 있으며, 버전 히스토리는 여기서 확인할 수 있습니다: "
        +  download3: "을 다운받아 시작하는 것이 가장 쉽고 간편한 방법입니다."
        +  download4: "그 중 index.html 파일에는 p5.js 링크가 적혀있습니다. 불러오기 시간을 단축하려면 이 p5.js 링크를 그 간략 버전인 p5.min.js로 아래와 같이 변경하면 됩니다. "
        +  download5: "p5.js 파일의 온라인 링크를 직접 입력하는 방법도 있습니다. p5.js의 모든 버전은 CDN(Content Delivery Network)에 저장되어 있으며, 버전 히스토리는 여기서 확인할 수 있습니다: "
           download6: ". 링크를 다음과 같이 변경해보세요:"
           download7: "아래는 HTML 페이지 샘플입니다:"
           download8: "위의 HTML 페이지 템플릿을 코드펜(CodePen)에 복사, 붙여넣기하여 프로젝트를 시작하는 것도 한 방법입니다: "
           download9: "."
           environment-title: "개발 환경"
        -  environment1: "여러분이 원하는 그 어떠한 "
        +  environment1: "여러분이 사용하는 그 어떠한 "
           environmentlink: "http://en.wikipedia.org/wiki/Source_code_editor"
           environment2: "코드 에디터"
        -  environment3: "도 p5.js를 위해 사용할 수 있습니다. 아래에 "
        +  environment3: "에서든 p5.js를 쓸 수 있습니다. 아래에 "
           environment4: " 에디터를 설정하는 방법이 있습니다.  추천하는 또다른 에디터: "
           environment5: ", "
        -  environment6: " p5 웹에디터를 이용하지 않는 스크린 리더(screen reader)라면, 다음의 에디터를 고려해보세요: "
        +  environment6: " p5 웹에디터는 스크린 리더 기능을 제공합니다. 웹에디터를 사용하지 않는 스크린 리더라면 다음의 데스크탑 에디터를 고려해보세요: "
           environment7: " 나 "
        -  environment8: "먼저, Sublime Text 2 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, html 파일과 js 파일이 위치한 폴더를 선택하세요. 폴더 이름과 폴더에 포함된 파일 리스트가 좌측 사이드바에 보일 것입니다."
        +  environment8: "먼저, Sublime Text 2 에디터 프로그램을 실행하세요. File 메뉴를 열고 Open을 클릭한 후, html 파일과 js 파일이 위치한 폴더를 선택하세요. 해당 폴더의 이름과 더불어 포함된 파일 리스트가 좌측 사이드바에 보일 것입니다."
           environment9: "sketch.js 파일을 선택하면, 우측 편집 영역에서 파일이 열립니다. "
           environment10: "Sublime 에디터에서 p5 템플릿 코드를 편집 중인 화면"
           environment11: "index.html 파일을 브라우저에서 열어볼까요? 파일 관리 시스템에서 index.html 파일을 더블 클릭하거나 브라우저 주소창에 다음을 입력하세요:"
        -  environment12: "file:///the/file/path/to/your/html"
        +  environment12: "file:///나의/html/경로"
           environment13: " "
           your-first-sketch-title: "나의 첫 스케치"
        -  your-first-sketch-intro1: "프로세싱(Processing) 유저라면 다음의 페이지를 읽어보세요: "
        +  your-first-sketch-intro1: "기존 프로세싱 사용자라면 다음의 페이지를 읽어보세요: "
           your-first-sketch-intro2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  your-first-sketch-intro3: "Processing에서 p5.js로 변환하기 튜토리얼"
        -  your-first-sketch-intro4: "에디터에 다음을 입력하세요:"
        +  your-first-sketch-intro3: "프로세싱 스케치를 p5.js로 변환하기 튜토리얼"
        +  your-first-sketch-intro4: " 에디터에 다음을 입력하세요:"
           your-first-sketch1: "After "
        -  your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다: \"좌층 상단 모서리에서 아래로 50px, 오른쪽으로 50px 떨어진 점을 중심으로 삼는 타원을 그린다. 타원의 폭과 높이는 모두 80px로 한다.\" "
        -  your-first-sketch3: "스케치를 저장하고 브라우저 페이지에서 새로고침을 해보세요. 입력한 코드에 문제가 없는 한, 다음과 같은 화면을 볼 수 있습니다:"
        -  your-first-sketch4: "주의: 스크린 리더를 사용하는 경우, p5 웹에디터에서 Accessible Outputs를 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: "
        +  your-first-sketch2: "위의 코드를 설명하자면 다음과 같습니다: \"좌측 상단 모서리로부터 아래로 50px, 오른쪽으로 50px 떨어진 점을 중심점삼아 타원을 그린다. 타원의 폭과 높이는 모두 80px로 한다.\" "
        +  your-first-sketch3: "스케치를 저장한 뒤 브라우저를 새로고침하면, 입력한 코드에 문제가 없다는 전제 하에 다음과 같은 화면을 볼 수 있습니다:"
        +  your-first-sketch4: "주의: 스크린 리더를 사용하는 경우, p5 웹에디터에서 접근성 모드 출력(Accessible Outputs)을 활성화해야 합니다. 별도의 에디터를 사용하는 경우, 접근성 라이브러리를 html 파일에 추가해야 합니다. 자세한 설명은 다음 링크를 참조하세요: "
           your-first-sketch5: "스크린 리더에서 p5를 사용하는 방법"
        -  your-first-sketch6: " , "
        +  your-first-sketch6: ""
           your-first-sketch7: "접근성 라이브러리란?"
           your-first-sketch8: "캔버스에 폭과 높이가 50인 타원이 x 80, y 80의 위치에 그려져있다"
           your-first-sketch9: "코드를 잘못 입력할 경우 화면에 아무것도 나타나지 않을 수 있습니다. 예제 코드를 정확히 따라 썼는지 확인해 보세요. 숫자는 (괄호) 안에 포함하고, 각 숫자는 쉼표(,)로 구분해야 하며, 각 라인은 세미 콜론(;)으로 끝나야 합니다"
        -  your-first-sketch10: "프로그래밍 언어를 처음 접할 때 겪는 어려움 중 하나는 문법이 매우 까다롭다는 것입니다. 브라우저는 우리가 표현하고자 바가 무엇인지 스스로 이해할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감합니다. 처음에는 이런 문법이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바 스크립트 '콘솔'을 제공합니다. 크롬(Chrome)의 경우, 보기 > 개발자 > 자바 스크립트 콘솔을 클릭하여 '콘솔'을 활성화할 수 있습니다."
        +  your-first-sketch10: "프로그래밍 언어를 처음 접할 때 겪는 어려움 중 하나는 바로 까다로운 문법입니다. 브라우저는 우리가 표현하려는 게 무엇인지 스스로 파악할 정도로 똑똑하지 않으며, 각 요소의 위치와 구두법에 매우 민감하답니다. 처음에는 이런 문법이 낯설게 느껴지겠지만, 연습을 통해 점차 익숙해질 것입니다. 몇몇 브라우저는 코드 내 오류를 확인할 수 있는 자바 스크립트 '콘솔'을 제공합니다. 크롬(Chrome)의 경우, 보기 > 개발자 > 자바 스크립트 콘솔을 클릭하여 '콘솔'을 활성화할 수 있습니다."
           your-first-sketch11: "이제 한층 더 재밌는 스케치를 만들어볼까요! 지난 예제의 코드를 에디터에서 삭제하고 아래의 코드를 입력해 보세요:"
           your-first-sketch12: "이제 프로그램은 폭 640px, 높이 480px의 캔버스를 생성하고, 마우스 커서 위치에서 흰 원을 그리기 시작합니다. 마우스 버튼을 누르고 있을 때는 원의 색이 검정색으로 바뀝니다. 마우스 위치에 대한 설명은 나중에 더 하기로 하고, 지금은 마우스를 움직이고 클릭하며 스케치의 변화를 살펴보세요."
        -  your-first-sketch13: "캔버스에 마우스 궤적을 따라 여러개의 원이 그려져있다"
        -  your-first-sketch14: "canvas has multiple circles drawn on it following the path of the mouse"
        -  first-sketch-heading1: "타원과 코드 스니펫(snippet)"
        -  first-sketch-heading2: "Note for 스크린리더 사용자를 위한"
        -  first-sketch-heading3: "인터랙션과 코드 스니펫(snippet)"
        +  your-first-sketch13: "캔버스 위의 마우스 궤적을 따라 여러 개의 원이 그려집니다:"
        +  your-first-sketch14: "캔버스 위의 마우스 궤적을 따라 여러 개의 원이 그려집니다."
        +  first-sketch-heading1: "타원과 코드 스니펫"
        +  first-sketch-heading2: "스크린리더 사용자를 위한 참고 사항"
        +  first-sketch-heading3: "인터랙션과 코드 스니펫"
           what-next-title: "다음 단계"
        -  learn1: "Check out the "
        -  learn2: "learn page"
        -  learn3: " and "
        -  learn4: "examples page"
        -  learn5: " for more."
        -  learn6: "Watch "
        -  learn7: "The Coding Train"
        -  learn8: " and "
        +  learn1: "더 많은 정보는 "
        +  learn2: "배우기"
        +  learn3: "와 "
        +  learn4: "예제"
        +  learn5: "에서 확인할 수 있습니다."
        +  learn6: "또, "
        +  learn7: "코딩 트레인(The Coding Train)"
        +  learn8: "과 "
           learn9: "Kadenze"
        -  learn10: " video tutorials."
        -  reference1: "p5.js에 대한 전체 문서를 보려면 "
        +  learn10: "의 비디오 튜토리얼을 참고하세요."
        +  reference1: "p5.js의 모든 함수 및 메소드, 그 외 문서는 "
           reference2: "레퍼런스"
        -  reference3: "를 읽어보세요."
        -  learn11: "If you wish to use p5 with a screenreader, check out the "
        -  learn12: "p5 with a screenreader tutorial"
        -  processing-transition1: "Processing을 p5.js로 전환하는 방법과 둘 간의 차이점이 궁금하다면, "
        +  reference3: "에서 확인하세요."
        +  learn11: "스크린 리더와 함께 p5를 사용하고 싶다면 다음을 확인하세요: "
        +  learn12: "스크린 리더 기반 p5 튜토리얼"
        +  processing-transition1: "프로세싱을 p5.js로 전환하는 방법과 둘 간의 차이점이 궁금하다면, "
           processing-transition2: "https://github.com/processing/p5.js/wiki/Processing-transition"
        -  processing-transition3: "Processing에서 p5.js로 변환하기 튜토리얼"
        +  processing-transition3: "프로세싱 스케치를 p5.js로 변환하기 튜토리얼"
           processing-transition4: "을 읽어보세요."
           book1: "본 튜토리얼의 일부는 로렌 맥카시(Lauren McCarthy), 캐시 리스(Casey Reas), 벤 프라이(Ben Fry), 오라일리(O'Reilly) 저 Getting Started with p5.js 에서 발췌하였습니다. / Make 2015. Copyright "
         
         download:
           Download: "다운로드"
        -  download-intro: "안녕하세요! 이 페이지는 온라인에서 바로 사용가능한 웹에디터와 각종 다운로드 링크를 소개합니다. 초심자에게 꼭 필요한 자료부터 숙련된 개발자를 위한 리소스 모두를 포괄합니다."
        +  download-intro: "안녕하세요! 이 페이지는 온라인에서 바로 사용가능한 웹에디터와 각종 다운로드 링크를 소개합니다. 입문자에게 꼭 필요한 자료부터 숙련된 개발자를 위한 리소스 모두를 포괄합니다."
           editor-title: "에디터"
           p5.js-editor: "p5.js 에디터"
           p5.js-editor-intro: "아래의 링크는 온라인 p5.js 에디터로 연결됩니다."
        @@ -184,7 +184,7 @@ download:
           link: "링크: "
           statically-hosted-file: "정적 호스팅 파일"
           etc-title: "Github 리소스"
        -  older-releases: "이전 버전 (구버전 및 변경 로그)"
        +  older-releases: "이전 버전 (구버전 및 업데이트 기록)"
           github-repository: "코드 저장소 (GitHub)"
           report-bugs: "이슈, 버그, 에러 보고하기"
           supported-browsers: "지원 브라우저 "
        @@ -242,23 +242,23 @@ download:
         
         learn:
           learn-title: "배우기"
        -  learn1: "주제별 깊이있고 순차적인 설명과 튜토리얼을 제공합니다. p5.js 함수에 대해 종류별로 알고싶다면 "
        +  learn1: "깊이있고 순차적인 설명과 튜토리얼을 주제별로 제공합니다. p5.js 함수를 종류별로 알고싶다면 "
           learn2: "예제"
           learn3: "를 클릭하세요."
           introduction-to-p5js-title: "p5.js 소개"
           hello-p5js-title: "Hello p5.js"
        -  hello-p5js: "이 영상을 통해 p5.js 라이브러리가 무엇인지, 또 어떻게 활용할 수 있을지 알아보세요."
        +  hello-p5js: "이 영상을 통해 p5.js 라이브러리가 무엇인지, 또 어떻게 활용할 수 있는지 알아보세요."
           getting-started-title: "시작하기"
        -  getting-started: "p5.js에 오신 것을 환영합니다. <br> 이 섹션은 p5.js 프로젝트 설정을 위한 기본적인 내용들을 다룹니다."
        +  getting-started: "p5.js에 오신 것을 환영합니다. <br> 이 페이지는 p5.js 프로젝트 설정을 위한 기본 내용을 다룹니다."
           p5js-overview-title: "p5.js 주요 기능"
           p5js-overview: "p5.js 주요 기능에 대한 개괄 설명을 확인하세요."
        -  p5js-processing-title: "p5.js와 Processing"
        -  p5js-processing: "p5와 Processing 간의 주요 차이점, 그리고 호환 방법을 알아보세요."
        +  p5js-processing-title: "p5.js와 프로세싱"
        +  p5js-processing: "p5와 프로세싱 간의 주요 차이점, 그리고 변환 방법을 알아보세요."
           p5-screen-reader-title: "p5와 스크린 리더"
           p5-screen-reader: "스크린 리더를 위한 p5 설정 방법을 알아보세요."
           using-local-server-title: "로컬 서버 사용하기"
           using-local-server: "맥 OSX, 윈도우, 리눅스 상에서 로컬 서버 설정하기"
        -  p5js-wiki-title: "p5.js 위키(wiki)"
        +  p5js-wiki-title: "p5.js 위키"
           p5js-wiki: "커뮤니티의 기여로 제작된 레퍼런스와 튜토리얼"
           connecting-p5js-title: "p5.js에 연결하기"
           creating-libraries-title: "라이브러리 만들기"
        @@ -276,11 +276,11 @@ learn:
           coordinate-system-and-shapes: "좌표계를 활용하여 간단한 도형 그리기"
           interactivity-title: "인터랙션"
           interactivity: "마우스 및 키보드 인터랙션 소개"
        -  program-flow-title: "프로그램 흐름(flow)"
        +  program-flow-title: "프로그램 흐름"
           program-flow: "p5.js에서 프로그램 플로우 조정하는 법 소개"
           curves-title: "곡선"
           curves: "p5.js상의 곡선 3가지 소개: 아치형 곡선, 스플라인 곡선, 베지어 곡선"
        -  becoming-a-better-programmer-title: "더 나은 프로그래머 되기"
        +  becoming-a-better-programmer-title: "더 나은 개발자 되기"
           debugging-title: "디버깅"
           debugging: "모두를 위한 디버깅 필드 가이드"
           optimizing-title: "ps.js 성능 최적화"
        @@ -296,12 +296,12 @@ learn:
           writing-tutorial: "프로그래밍 튜토리얼 제작 가이드."
           writing-a-tutorial-title: "p5.js 튜토리얼 기여를 위한 가이드"
           writing-a-tutorial-author: "이 튜토리얼은 테가 브레인(Tega Brain)이 제작하였습니다."
        -  writing-a-tutorial-1: "p5.js 튜토리얼 기여는 이에 열정을 느끼는 교육자와 모든분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 공헌 방법 등에 대한 내용을 다룹니다."
        +  writing-a-tutorial-1: "p5.js 튜토리얼은 이에 열정을 느끼는 교육자와 모든 분들께 열려있습니다. p5.js 프로젝트는 보다 다양한 사람들을 위한 크리에이티브 코딩 및 오픈 소스 개발을 추구하며, 모든 개발 과정을 공개하는 것을 하나의 즐거운 과정으로 여깁니다. 현재까지 제작된 튜토리얼은 p5 학습, 프로그래밍 기술, 오픈소스 프로젝트 공헌 방법 등에 대한 내용을 다룹니다."
           writing-a-tutorial-2: "새로운 튜토리얼을 제안하거나, 튜토리얼 준비 및 기여에 대한 가이드라인 제작을 환영합니다."
           writing-a-tutorial-how-start-title: "커뮤니티 기여 시작하기:"
           writing-a-tutorial-how-start-1: "우선, 제안하려는 튜토리얼이 현재 진행 중인 내용들과 겹치는 지의 여부를 이 "
           writing-a-tutorial-how-start-2: "스프레드시트"
        -  writing-a-tutorial-how-start-3: "에서 확인하세요. 만약 제안하고자 하는 튜토리얼 주제가 현재 진행 중인 것이라면, 해당 주제의 마무리 또는 p5.js 웹사이트 공개 작업에 참여할 수 있고 관련해서는 아래의 이메일로 연락을 주시면 감사하겠습니다. "
        +  writing-a-tutorial-how-start-3: "에서 확인하세요. 만약 제안하고자 하는 튜토리얼 주제가 현재 진행 중인 것이라면, 해당 주제의 마무리 작업 또는 p5.js 웹사이트상의 공개 작업에 참여할 수 있고 관련해서는 아래의 이메일로 연락주시면 감사하겠습니다. "
           writing-a-tutorial-how-start-4: "제안하려는 튜토리얼이 스프레드시트 리스트에 포함되지 않는다면, 튜토리얼에 대한 간략한 설명을 education@p5js.org로 보내주세요."
           writing-a-tutorial-how-prepare-title: "p5.js 튜토리얼 온라인 공개 준비하기:"
           writing-a-tutorial-how-prepare-1: "튜토리얼을 p5.js 웹사이트상 공개할 준비가 되었다면, 다음의 단계를 따라주세요."
        @@ -402,7 +402,7 @@ learn:
           coordinate-system-simple-shapes-p4x1: "선그리기를 뜻하는 "
           coordinate-system-simple-shapes-p4x2: " 함수 역시 아주 어렵진 않습니다. 선을 그리기 위해 우리는 (x1,y1)과 (x2,y2)라는 두개의 좌표값만 필요합니다:"
           coordinate-system-simple-shapes-p5x1: "사각형 그리기 함수인 "
        -  coordinate-system-simple-shapes-p5x2: "의 경우 조금 복잡해집니다. p5에서 사각형은 그것이 그려지기 시작하는 상단 좌측의 좌표값과 더불어 너비(width)와 높이(height)를 정하는 숫자들이 필요합니다."
        +  coordinate-system-simple-shapes-p5x2: "의 경우 약간 복잡합니다. p5에서 사각형은 그것이 그려지기 시작하는 상단 좌측의 좌표값과 더불어 너비(width)와 높이(height)를 정하는 숫자들이 필요합니다."
           coordinate-system-simple-shapes-p6x1: "사각형을 그리는 또 다른 방법으로, 중앙값, 너비(width), 높이값(height) 설정하기가 있습니다. 이 경우, 먼저 상단의 setup() 함수에 센터 "
           coordinate-system-simple-shapes-p6x2: " 모드를 불러오고, 그 뒤에 사각형의 중앙값, 너비, 높이값을 지정해야 합니다. p5는 대문자와 소문자 구분에 민감하니 주의하세요!"
           coordinate-system-simple-shapes-p7x1: "마지막으로, 점 두 개 만으로 사각형을 그리는 방법도 있습니다. 바로, 상단 좌측 코너와 하단 우측 코너의 좌표를 지정하는 것이지요. 여기서 우리가 setup() 함수에 포함시킬 모드는 코너 "
        @@ -478,11 +478,11 @@ community:
           community-statement-title: "p5.js 커뮤니티 성명서"
           community-statement1: "p5.js는 기술을 재료삼아 예술과 디자인을 창작하는 커뮤니티입니다."
           community-statement2: "우리는 다양한 성 정체성, 젠더 표현, 성적 지향, 인종, 민족, 언어, 사회, 규모, 능력, 계급, 종교, 문화, 하위 문화, 정치 성향, 나이, 기술적 숙련도, 직업, 배경에 속한 사람들의 공동체이자 연대입니다. 모든 사람이 우리 커뮤니티에 시간과 에너지를 할애할 수 있는 게 아니라는 걸 인지하고 있습니다. 그만큼 우리는 여러분의 참여를 환영하고 독려하며, 접근성을 향상하기 위해 늘 노력합니다. 우리 모두는 언제나 배우는 자들입니다."
        -  community-statement3: "우리가 좋아하는 해시태그는 #noCodeSnobs(우리는 효율성보다 커뮤니티를 우선시합니다), #newKidLove(우리는 모두 한 때 초심자였으니깐요!), #unassumeCore(우리는 상대가 무엇을 알고 있는지에 대해 섣불리 가정하지 않습니다), and #BlackLivesMatter (말할 필요도 없이 중요한 사실이지요!) 입니다."
        +  community-statement3: "우리가 좋아하는 해시태그는 #noCodeSnobs(우리는 효율성보다 커뮤니티를 우선시합니다), #newKidLove(우리는 모두 한 때 입문자였으니깐요!), #unassumeCore(우리는 상대가 무엇을 알고 있는지에 대해 섣불리 가정하지 않습니다), and #BlackLivesMatter (말할 필요도 없이 중요한 사실이지요!) 입니다."
           in-practice-title: "실천:"
           in-practice1: "우리는 잘난체하는 개발자들이 아닙니다. 우리는 상대가 이미 어떠한 것을 알고 있을거라 섣불리 가정하거나, 모든 사람이 반드시 알아야 할 지식이 있다고 생각하지 않습니다. "
           in-practice2: "피드백이 필요한 경우, 언제든 적극적으로 응합니다."
        -  in-practice3: "우리는 초심자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 초심자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
        +  in-practice3: "우리는 입문자를 환영하며 타인의 학습을 우선순위에 둡니다. 또, 우리는 모든 업무를 수행할 때 초심자 시절의 열정을 잃지 않습니다. 우리 커뮤니티에 있어 입문자는 숙련자만큼이나 중요한 가치를 더하는 존재입니다. "
           in-practice4: "우리는 언제나 모든 형태의 기여, 공헌, 참여를 적극적으로 인정하고 인증하고자 합니다."
           in-practice5: "우리는 언제나 기꺼이 도움과 안내를 제공합니다."
           in-times-conflict-title: "갈등이 발생할 경우:"
        @@ -607,7 +607,7 @@ community:
           2019cc_7: "많은 이들이 모여있는 교실에서 대화를 나누는 참가자들"
           2019cc_8: "한 교실에서 동료 참여자를 향해 마이크에 대고 말하는 여성"
           2019cc_9: "데이터 익명화의 문제점에 대한 글이 투사된 스크린과 그 앞 단상에서 말하는 참여자"
        -  2019cc_10: "\"p5.js는 접근성을 증진을 위한 기능 외에는 새로운 기능을 추가하지 않을 것입니다\"라고 적힌 텍스트 앞에 서서, 동료 참여자를 향해 마이크에 대고 말하는 사람"
        +  2019cc_10: "\"p5.js는 접근성을 향상을 위한 기능 외에는 향후 새로운 기능을 추가하지 않을 것입니다\"라고 적힌 텍스트 앞에 서서, 동료 참여자를 향해 마이크에 대고 말하는 사람"
           2019cc_11: "동료 참여자를 향해 마이크에 대고 말하는 여성"
           2019cc_12: "동료 참여자를 향해 마이크에 대고 말하는 남성"
           2019cc_13: "교실 속, 경청 중인 발표자들을 향해 앉아있는 참여자들"
        @@ -700,12 +700,12 @@ reference:
         
         showcase:
           showcase-title: "쇼케이스"
        -  showcase-intro1: "쇼케이스 페이지는 p5.js를 보다 흥미진진하고 포용적으로 만든 창작물, 학습물, 오픈 소스 사례들을 기쁘게 소개하고자 합니다. 쇼케이스 페이지 기획 및 제작: 애슐리 강 " 
        -  showcase-intro2: "이렇게 우리는 함께 커뮤니티를 만들어 나가는게 아닐까요?:)"
        -  showcase-intro3: "2019년 여름, 몇몇 창작자들에게 그들의 p5.js 기반의 프로젝트 소개를 요청하였습니다. 아래의 버튼을 눌러 자신 또는 타인의 p5.js 작품을 추천해보세요!"
        -  showcase-intro4: "The Summer 2020 Showcase is now open for submissions, nominate someone's p5.js work or your own to be featured here!"
        -  nominate-project: "Nominate a Project"
        -  showcase-featuring: "Featuring"
        +  showcase-intro1: "쇼케이스는 2019년 애슐리 강 " 
        +  showcase-intro2: "이 제작, 기획하였으며, 2020년에는 코니 리우 "
        +  showcase-intro3: "가 새로운 기획을 선보입니다. 쇼케이스는 p5.js를 보다 흥미진진하고 포용적으로 만든 창작물, 학습물, 오픈 소스 사례들을 기쁘게 소개합니다. 이렇게 우리는 함께 커뮤니티를 만들어 나가는게 아닐까요?:) 2019년 여름, 우리는 p5.js 기반의 다양한 프로젝트들을 소개한 바 있습니다."
        +  showcase-intro4: "현재 2020년 여름 쇼케이스를 위한 모집을 진행중입니다. 아래의 버튼을 눌러 자신 또는 타인의 p5.js 작업을 추천해주세요!"
        +  nominate-project: "프로젝트 추천하기"
        +  showcase-featuring: "선정 프로젝트"
           project-tag-art: "예술"
           project-tag-design: "디자인"
           project-tag-code: "코드"
        @@ -716,23 +716,23 @@ showcase:
           project-tag-organizing: "행사 또는 모임"
           project-tag-tool: "툴"
           project-tag-tutorial: "튜토리얼"
        -  project-roni: "프로그래밍된 각도기 드로잉(Programmed Plotter Drawings)"
        +  project-roni: "각도기 드로잉 프로그램(Programmed Plotter Drawings)"
           credit-roni: "Roni Cantor"
           description-roni: "p5.js로 제작한 싸인파(Sine wave)와 선형 보간(lerp)으로, 실물 각도기와 펜과 연결되어 드로잉하고, SVG 파일로 내보내기 가능."
        -  project-phuong: "Airi Flies"
        +  project-phuong: "날아라 아이리(Airi Flies)"
           credit-phuong: "Phuong Ngo"
        -  description-phuong: "p5.play로 제작된 게임으로, PEW라고 말해 Airi가 날 수 있도록 돕는다. 사용자들이 자신의 안전 지대를 벗어난 곳에서도 행동, 외모, 발언에 상관없이 자신감을 갖게하고자 하는 취지에서 제작."
        +  description-phuong: "p5.play로 제작된 게임으로, PEW라고 말해 아이리(Airi)가 날 수 있도록 돕는다. 사용자들이 자신의 안전 지대를 벗어난 곳에서도 행동, 외모, 발언에 상관없이 자신감을 갖게하고자 하는 취지에서 제작."
           project-daein: "Chillin'"
        -  credit-daein: "정대인 (Dae In Chung)"
        -  description-daein: "모바일 기기의 모션 센서와 p5.js를 활용한, 인터랙티브 타이포그래픽 포스터"
        +  credit-daein: "정대인(Dae In Chung)"
        +  description-daein: "모바일 기기의 모션 센서와 p5.js를 활용한 인터랙티브 타이포그래픽 포스터"
           project-qianqian: "Qtv"
        -  credit-qianqian: "Qianqian Ye"
        -  description-qianqian: "초심자를 위한 p5.js 튜토리얼을 포함하여, 코딩, 예술, 그리고 기술에 대해 다루는 1분 길이의 중국어 영상 채널들. 유투브, 인스타그램, 비리비리(Bilibili), 틱톡(TikTok)에서 확인 가능."
        +  credit-qianqian: "치안치안 예(Qianqian Ye)"
        +  description-qianqian: "입문자를 위한 p5.js 튜토리얼을 포함하여, 코딩, 예술, 그리고 기술에 대해 다루는 1분 길이의 중국어 영상 채널들. 유투브, 인스타그램, 비리비리(Bilibili), 틱톡(TikTok)에서 확인 가능."
           project-casey-louise: "p5.js 셰이더(Shaders)"
        -  credit-casey-louise: "Casey Conchinha, Louise Lessél"
        +  credit-casey-louise: "캐시 콘치나(Casey Conchinha), 루이스 레셀(Louise Lessél)"
           description-casey-louise: "셰이더(Shaders)란 무엇이고, 이를 p5.js에서 왜, 그리고 어떻게 사용하는지 배울 수 있는 자료."
           project-moon-xin: "움직이는 반응형 포스터(Moving Responsive Posters)"
        -  credit-moon-xin: "Moon Jang, Xin Xin, 그리고 학생들"
        +  credit-moon-xin: "장문(Moon Jang), 씬 씬(Xin Xin), 그리고 학생들"
           description-moon-xin: "브라우저 기반의 움직이는 포스터로, 그래픽 시스템과 변형 메소드, 그리고 p5.js를 사용하여 8자 미만 단어가 내포하는 바를 표현. 조지아 대학교(University of Georgia)의 그래픽 디자인 과정인 'Visual Narrative Systems'의 수강생들이 디자인."
         
           created-by: "Created By"
        diff --git a/src/data/reference/ko.json b/src/data/reference/ko.json
        index 9699164680..9460043665 100644
        --- a/src/data/reference/ko.json
        +++ b/src/data/reference/ko.json
        @@ -16,10 +16,10 @@
           "reference-menu-community": "커뮤니티",
           "reference-menu-forum": "포럼",
           "reference-description1": "찾는 항목이 없다면, 다음의 페이지를 살펴보세요:",
        -  "reference-description2": " 또는 ",
        -  "reference-description3": "오프라인 버전의 레퍼런스는 다음 링크에서 다운받을 수 있습니다: ",
        +  "reference-description2": "",
        +  "reference-description3": "오프라인 버전 다운로드",
           "reference-contribute1": "잘못된 부분이나 제안사항이 있다면",
        -  "reference-contribute2": "언제든 알려주세요",
        +  "reference-contribute2": "여기로 알려주세요.",
           "reference-error1": "오타나 버그를 발견했다면",
           "reference-error2": "관련 문서는 이곳에 있습니다: ",
           "reference-error3": "p5.js에 기여하고 싶다면, ",
        @@ -79,12 +79,15 @@
           "Time & Date": "날짜 & 시간",  
           "XML": "XML", 
           "Math": "수학", 
        +  "Vector": "벡터",
           "Calculation": "계산",  
        +  "Random": "랜덤",
           "Noise": "노이즈", 
           "Trigonometry": "삼각법",  
           "Typography": "타이포그래피", 
           "Font": "폰트", 
        -  "Lights, Camera": "라이트, 카메라",  
        +  "Lights, Camera": "라이트, 카메라", 
        +  "Interaction":"인터랙션",
           "Camera": "카메라",  
           "Lights": "라이트",  
           "Material": "재질(Material)", 
        @@ -2064,7 +2067,7 @@
                 "returns": "p5.Vector"
             },
         
        -    "p5.Vector()": {
        +    "p5.Vector": {
                 "description": "2차원 및 3차원 벡터, 특히 유클리드 (기하학) 벡터를 설명하는 클래스입니다. 벡터는 크기와 방향을 모두 지닌 개체입니다. 하지만, 그 데이터 유형은 벡터의 성분(2D의 경우 x와 y, 3D의 경우 x, y, z)을 저장합니다. 크기와 방향은 각각 mag() 및 heading() 메소드를 통해 접근할 수 있습니다.<br><br>p5.Vector는 위치, 속도, 가속을 다루는 수많은 p5.js 예제에서 사용됩니다. 예를 들어, 화면을 가로질러 움직이는 직사각형을 만들려면, 이 물체의 위치(원점에서 그 위치를 가리키는 벡터), 속도(단위 시간당 객체의 위치가 변하는 속도, 벡터로 표시), 그리고 가속도(단위 시간당 객체의 속도가 변하는 속도, 벡터로 표시)를 반드시 고려해야합니다.<br><br>벡터는 그룹화된 값들을 나타냅니다. 따라서, 전통적인 덧셈/곱셈 대신, p5.Vector 클래스 내부의 벡터 수학 메소드를 사용해서 계산해야 합니다.",
                 "params":["숫자: 벡터의 x성분 (선택 사항)",
                             "숫자: 벡터의 y성분 (선택 사항)",